PageSourceSearch

https://fynthesizer.github.io/Planetarium/p5.js

js fynthesizer.github.io collected 2026-10-03 09:13:12 UTC 2,751,378 bytes, 76,389 lines download raw bytes

vendor: 4,255 bytes, lines 1-125
1/*! p5.js v0.6.1 April 27, 2018 */
2(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.p5 = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
3module.exports={
4    "project": {
5        "name": "p5",
6        "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)",
7        "version": "0.6.1",
8        "url": "https://github.com/processing/p5.js#readme"
9    },
10    "files": {
11        "src/color/color_conversion.js": {
12            "name": "src/color/color_conversion.js",
13            "modules": {
14                "Color Conversion": 1
15            },
16            "classes": {},
17            "fors": {
18                "p5": 1
19            },
20            "namespaces": {}
21        },
22        "src/color/creating_reading.js": {
23            "name": "src/color/creating_reading.js",
24            "modules": {
25                "Creating & Reading": 1
26            },
27            "classes": {},
28            "fors": {
29                "p5": 1
30            },
31            "namespaces": {}
32        },
33        "src/color/p5.Color.js": {
34            "name": "src/color/p5.Color.js",
35            "modules": {},
36            "classes": {
37                "p5.Color": 1
38            },
39            "fors": {
40                "p5": 1
41            },
42            "namespaces": {}
43        },
44        "src/color/setting.js": {
45            "name": "src/color/setting.js",
46            "modules": {
47                "Setting": 1
48            },
49            "classes": {},
50            "fors": {
51                "p5": 1
52            },
53            "namespaces": {}
54        },
55        "src/core/2d_primitives.js": {
56            "name": "src/core/2d_primitives.js",
57            "modules": {
58                "2D Primitives": 1
59            },
60            "classes": {},
61            "fors": {
62                "p5": 1
63            },
64            "namespaces": {}
65        },
66        "src/core/attributes.js": {
67            "name": "src/core/attributes.js",
68            "modules": {
69                "Attributes": 1
70            },
71            "classes": {},
72            "fors": {
73                "p5": 1
74            },
75            "namespaces": {}
76        },
77        "src/core/canvas.js": {
78            "name": "src/core/canvas.js",
79            "modules": {},
80            "classes": {},
81            "fors": {},
82            "namespaces": {}
83        },
84        "src/core/constants.js": {
85            "name": "src/core/constants.js",
86            "modules": {
87                "Constants": 1
88            },
89            "classes": {},
90            "fors": {
91                "p5": 1
92            },
93            "namespaces": {}
94        },
95        "src/core/core.js": {
96            "name": "src/core/core.js",
97            "modules": {
98                "Structure": 1
99            },
100            "classes": {
101                "p5": 1
102            },
103            "fors": {
104                "p5": 1
105            },
106            "namespaces": {}
107        },
108        "src/core/curves.js": {
109            "name": "src/core/curves.js",
110            "modules": {
111                "Curves": 1
112            },
113            "classes": {},
114            "fors": {
115                "p5": 1
116            },
117            "namespaces": {}
118        },
119        "src/core/environment.js": {
120            "name": "src/core/environment.js",
121            "modules": {
122                "Environment": 1
123            },
124            "classes": {},
125            "fors": {
126                "p5": 1
127            },
128            "namespaces": {}
129        },
130        "src/core/error_helpers.js": {
131            "name": "src/core/error_helpers.js",
132            "modules": {},
133            "classes": {},
134            "fors": {
135                "p5": 1
136            },
137            "namespaces": {}
138        },
139        "src/core/init.js": {
140            "name": "src/core/init.js",
141            "modules": {},
142            "classes": {},
143            "fors": {},
144            "namespaces": {}
145        },
146        "src/core/p5.Element.js": {
147            "name": "src/core/p5.Element.js",
148            "modules": {
149                "DOM": 1
150            },
151            "classes": {
152                "p5.Element": 1
153            },
154            "fors": {
155                "p5.Element": 1
156            },
157            "namespaces": {}
158        },
159        "src/core/p5.Graphics.js": {
160            "name": "src/core/p5.Graphics.js",
161            "modules": {
162                "Rendering": 1
163            },
164            "classes": {
165                "p5.Graphics": 1
166            },
167            "fors": {
168                "p5": 1
169            },
170            "namespaces": {}
171        },
172        "src/core/p5.Renderer.js": {
173            "name": "src/core/p5.Renderer.js",
174            "modules": {},
175            "classes": {
176                "p5.Renderer": 1
177            },
178            "fors": {
179                "p5": 1
180            },
181            "namespaces": {}
182        },
183        "src/core/p5.Renderer2D.js": {
184            "name": "src/core/p5.Renderer2D.js",
185            "modules": {},
186            "classes": {},
187            "fors": {},
188            "namespaces": {}
189        },
190        "src/core/rendering.js": {
191            "name": "src/core/rendering.js",
192            "modules": {},
193            "classes": {},
194            "fors": {
195                "p5": 1
196            },
197            "namespaces": {}
198        },
199        "src/core/shim.js": {
200            "name": "src/core/shim.js",
201            "modules": {},
202            "classes": {},
203            "fors": {},
204            "namespaces": {}
205        },
206        "src/core/structure.js": {
207            "name": "src/core/structure.js",
208            "modules": {},
209            "classes": {},
210            "fors": {
211                "p5": 1
212            },
213            "namespaces": {}
214        },
215        "src/core/transform.js": {
216            "name": "src/core/transform.js",
217            "modules": {
218                "Transform": 1
219            },
220            "classes": {},
221            "fors": {
222                "p5": 1
223            },
224            "namespaces": {}
225        },
226        "src/core/vertex.js": {
227            "name": "src/core/vertex.js",
228            "modules": {
229                "Vertex": 1
230            },
231            "classes": {},
232            "fors": {
233                "p5": 1
234            },
235            "namespaces": {}
236        },
237        "src/data/p5.TypedDict.js": {
238            "name": "src/data/p5.TypedDict.js",
239            "modules": {
240                "Dictionary": 1
241            },
242            "classes": {
243                "p5.TypedDict": 1,
244                "p5.StringDict": 1,
245                "p5.NumberDict": 1
246            },
247            "fors": {
248                "p5.TypedDict": 1,
249                "p5": 1
250            },
251            "namespaces": {}
252        },
253        "src/events/acceleration.js": {
254            "name": "src/events/acceleration.js",
255            "modules": {
256                "Acceleration": 1
257            },
258            "classes": {},
259            "fors": {
260                "p5": 1
261            },
262            "namespaces": {}
263        },
264        "src/events/keyboard.js": {
265            "name": "src/events/keyboard.js",
266            "modules": {
267                "Keyboard": 1
268            },
269            "classes": {},
270            "fors": {
271                "p5": 1
272            },
273            "namespaces": {}
274        },
275        "src/events/mouse.js": {
276            "name": "src/events/mouse.js",
277            "modules": {
278                "Mouse": 1
279            },
280            "classes": {},
281            "fors": {
282                "p5": 1
283            },
284            "namespaces": {}
285        },
286        "src/events/touch.js": {
287            "name": "src/events/touch.js",
288            "modules": {
289                "Touch": 1
290            },
291            "classes": {},
292            "fors": {
293                "p5": 1
294            },
295            "namespaces": {}
296        },
297        "src/image/filters.js": {
298            "name": "src/image/filters.js",
299            "modules": {},
300            "classes": {},
301            "fors": {},
302            "namespaces": {}
303        },
304        "src/image/image.js": {
305            "name": "src/image/image.js",
306            "modules": {
307                "Image": 1
308            },
309            "classes": {},
310            "fors": {
311                "p5": 1
312            },
313            "namespaces": {}
314        },
315        "src/image/loading_displaying.js": {
316            "name": "src/image/loading_displaying.js",
317            "modules": {
318                "Loading & Displaying": 1
319            },
320            "classes": {},
321            "fors": {
322                "p5": 1
323            },
324            "namespaces": {}
325        },
326        "src/image/p5.Image.js": {
327            "name": "src/image/p5.Image.js",
328            "modules": {},
329            "classes": {
330                "p5.Image": 1
331            },
332            "fors": {},
333            "namespaces": {}
334        },
335        "src/image/pixels.js": {
336            "name": "src/image/pixels.js",
337            "modules": {
338                "Pixels": 1
339            },
340            "classes": {},
341            "fors": {
342                "p5": 1
343            },
344            "namespaces": {}
345        },
346        "src/io/files.js": {
347            "name": "src/io/files.js",
348            "modules": {
349                "Input": 1,
350                "Output": 1
351            },
352            "classes": {
353                "p5.PrintWriter": 1
354            },
355            "fors": {
356                "p5": 1
357            },
358            "namespaces": {}
359        },
360        "src/io/p5.Table.js": {
361            "name": "src/io/p5.Table.js",
362            "modules": {
363                "Table": 1
364            },
365            "classes": {
366                "p5.Table": 1
367            },
368            "fors": {},
369            "namespaces": {}
370        },
371        "src/io/p5.TableRow.js": {
372            "name": "src/io/p5.TableRow.js",
373            "modules": {},
374            "classes": {
375                "p5.TableRow": 1
376            },
377            "fors": {},
378            "namespaces": {}
379        },
380        "src/io/p5.XML.js": {
381            "name": "src/io/p5.XML.js",
382            "modules": {
383                "XML": 1
384            },
385            "classes": {
386                "p5.XML": 1
387            },
388            "fors": {},
389            "namespaces": {}
390        },
391        "src/math/calculation.js": {
392            "name": "src/math/calculation.js",
393            "modules": {
394                "Calculation": 1
395            },
396            "classes": {},
397            "fors": {
398                "p5": 1
399            },
400            "namespaces": {}
401        },
402        "src/math/math.js": {
403            "name": "src/math/math.js",
404            "modules": {
405                "Math": 1
406            },
407            "classes": {},
408            "fors": {
409                "p5": 1
410            },
411            "namespaces": {}
412        },
413        "src/math/noise.js": {
414            "name": "src/math/noise.js",
415            "modules": {
416                "Noise": 1
417            },
418            "classes": {},
419            "fors": {
420                "p5": 1
421            },
422            "namespaces": {}
423        },
424        "src/math/p5.Vector.js": {
425            "name": "src/math/p5.Vector.js",
426            "modules": {},
427            "classes": {
428                "p5.Vector": 1
429            },
430            "fors": {},
431            "namespaces": {}
432        },
433        "src/math/random.js": {
434            "name": "src/math/random.js",
435            "modules": {
436                "Random": 1
437            },
438            "classes": {},
439            "fors": {
440                "p5": 1
441            },
442            "namespaces": {}
443        },
444        "src/math/trigonometry.js": {
445            "name": "src/math/trigonometry.js",
446            "modules": {
447                "Trigonometry": 1
448            },
449            "classes": {},
450            "fors": {
451                "p5": 1
452            },
453            "namespaces": {}
454        },
455        "src/typography/attributes.js": {
456            "name": "src/typography/attributes.js",
457            "modules": {},
458            "classes": {},
459            "fors": {
460                "p5": 1
461            },
462            "namespaces": {}
463        },
464        "src/typography/loading_displaying.js": {
465            "name": "src/typography/loading_displaying.js",
466            "modules": {},
467            "classes": {},
468            "fors": {
469                "p5": 1
470            },
471            "namespaces": {}
472        },
473        "src/typography/p5.Font.js": {
474            "name": "src/typography/p5.Font.js",
475            "modules": {
476                "Font": 1
477            },
478            "classes": {
479                "p5.Font": 1
480            },
481            "fors": {},
482            "namespaces": {}
483        },
484        "src/utilities/array_functions.js": {
485            "name": "src/utilities/array_functions.js",
486            "modules": {
487                "Array Functions": 1
488            },
489            "classes": {},
490            "fors": {
491                "p5": 1
492            },
493            "namespaces": {}
494        },
495        "src/utilities/conversion.js": {
496            "name": "src/utilities/conversion.js",
497            "modules": {
498                "Conversion": 1
499            },
500            "classes": {},
501            "fors": {
502                "p5": 1
503            },
504            "namespaces": {}
505        },
506        "src/utilities/string_functions.js": {
507            "name": "src/utilities/string_functions.js",
508            "modules": {
509                "String Functions": 1
510            },
511            "classes": {},
512            "fors": {
513                "p5": 1
514            },
515            "namespaces": {}
516        },
517        "src/utilities/time_date.js": {
518            "name": "src/utilities/time_date.js",
519            "modules": {
520                "Time & Date": 1
521            },
522            "classes": {},
523            "fors": {
524                "p5": 1
525            },
526            "namespaces": {}
527        },
528        "src/webgl/camera.js": {
529            "name": "src/webgl/camera.js",
530            "modules": {
531                "Camera": 1
532            },
533            "classes": {},
534            "fors": {
535                "p5": 1
536            },
537            "namespaces": {}
538        },
539        "src/webgl/interaction.js": {
540            "name": "src/webgl/interaction.js",
541            "modules": {},
542            "classes": {},
543            "fors": {
544                "p5": 1
545            },
546            "namespaces": {}
547        },
548        "src/webgl/light.js": {
549            "name": "src/webgl/light.js",
550            "modules": {
551                "Lights": 1
552            },
553            "classes": {},
554            "fors": {
555                "p5": 1
556            },
557            "namespaces": {}
558        },
559        "src/webgl/loading.js": {
560            "name": "src/webgl/loading.js",
561            "modules": {
562                "3D Models": 1
563            },
564            "classes": {},
565            "fors": {
566                "p5": 1
567            },
568            "namespaces": {}
569        },
570        "src/webgl/material.js": {
571            "name": "src/webgl/material.js",
572            "modules": {
573                "Material": 1
574            },
575            "classes": {},
576            "fors": {
577                "p5": 1
578            },
579            "namespaces": {}
580        },
581        "src/webgl/p5.Geometry.js": {
582            "name": "src/webgl/p5.Geometry.js",
583            "modules": {},
584            "classes": {
585                "p5.Geometry": 1
586            },
587            "fors": {},
588            "namespaces": {}
589        },
590        "src/webgl/p5.Matrix.js": {
591            "name": "src/webgl/p5.Matrix.js",
592            "modules": {},
593            "classes": {
594                "p5.Matrix": 1
595            },
596            "fors": {},
597            "namespaces": {}
598        },
599        "src/webgl/p5.RendererGL.Immediate.js": {
600            "name": "src/webgl/p5.RendererGL.Immediate.js",
601            "modules": {},
602            "classes": {},
603            "fors": {},
604            "namespaces": {}
605        },
606        "src/webgl/p5.RendererGL.Retained.js": {
607            "name": "src/webgl/p5.RendererGL.Retained.js",
608            "modules": {},
609            "classes": {},
610            "fors": {},
611            "namespaces": {}
612        },
613        "src/webgl/p5.RendererGL.js": {
614            "name": "src/webgl/p5.RendererGL.js",
615            "modules": {},
616            "classes": {
617                "p5.RendererGL": 1
618            },
619            "fors": {
620                "p5": 1
621            },
622            "namespaces": {}
623        },
624        "src/webgl/p5.Shader.js": {
625            "name": "src/webgl/p5.Shader.js",
626            "modules": {
627                "Shaders": 1
628            },
629            "classes": {
630                "p5.Shader": 1
631            },
632            "fors": {
633                "p5": 1
634            },
635            "namespaces": {}
636        },
637        "src/webgl/p5.Texture.js": {
638            "name": "src/webgl/p5.Texture.js",
639            "modules": {},
640            "classes": {
641                "p5.Texture": 1
642            },
643            "fors": {
644                "p5": 1
645            },
646            "namespaces": {}
647        },
648        "src/webgl/primitives.js": {
649            "name": "src/webgl/primitives.js",
650            "modules": {
651                "3D Primitives": 1
652            },
653            "classes": {},
654            "fors": {
655                "p5": 1
656            },
657            "namespaces": {}
658        },
659        "lib/addons/p5.dom.js": {
660            "name": "lib/addons/p5.dom.js",
661            "modules": {
662                "p5.dom": 1
663            },
664            "classes": {
665                "p5.MediaElement": 1,
666                "p5.File": 1
667            },
668            "fors": {
669                "p5.dom": 1,
670                "p5.Element": 1
671            },
672            "namespaces": {}
673        },
674        "lib/addons/p5.sound.js": {
675            "name": "lib/addons/p5.sound.js",
676            "modules": {
677                "p5.sound": 1
678            },
679            "classes": {
680                "p5.SoundFile": 1,
681                "p5.Amplitude": 1,
682                "p5.FFT": 1,
683                "p5.Signal": 1,
684                "p5.Oscillator": 1,
685                "p5.SinOsc": 1,
686                "p5.TriOsc": 1,
687                "p5.SawOsc": 1,
688                "p5.SqrOsc": 1,
689                "p5.Env": 1,
690                "p5.Pulse": 1,
691                "p5.Noise": 1,
692                "p5.AudioIn": 1,
693                "p5.Effect": 1,
694                "p5.Filter": 1,
695                "p5.LowPass": 1,
696                "p5.HighPass": 1,
697                "p5.BandPass": 1,
698                "p5.EQ": 1,
699                "p5.Panner3D": 1,
700                "p5.Delay": 1,
701                "p5.Reverb": 1,
702                "p5.Convolver": 1,
703                "p5.Phrase": 1,
704                "p5.Part": 1,
705                "p5.Score": 1,
706                "p5.SoundLoop": 1,
707                "p5.Compressor": 1,
708                "p5.SoundRecorder": 1,
709                "p5.PeakDetect": 1,
710                "p5.Gain": 1,
711                "p5.AudioVoice": 1,
712                "p5.MonoSynth": 1,
713                "p5.PolySynth": 1,
714                "p5.Distortion": 1
715            },
716            "fors": {
717                "p5.sound": 1,
718                "p5": 1
719            },
720            "namespaces": {}
721        },
722        "lib/addons/p5.sound.min.js": {
723            "name": "lib/addons/p5.sound.min.js",
724            "modules": {},
725            "classes": {},
726            "fors": {},
727            "namespaces": {}
728        }
729    },
730    "modules": {
731        "Conversion": {
732            "name": "Conversion",
733            "submodules": {
734                "Color Conversion": 1
735            },
736            "elements": {},
737            "classes": {},
738            "fors": {
739                "p5": 1
740            },
741            "namespaces": {},
742            "module": "Data",
743            "file": "src/utilities/conversion.js",
744            "line": 1,
745            "requires": [
746                "core"
747            ]
748        },
749        "Color Conversion": {
750            "name": "Color Conversion",
751            "submodules": {},
752            "elements": {},
753            "classes": {},
754            "fors": {
755                "p5": 1
756            },
757            "is_submodule": 1,
758            "namespaces": {},
759            "module": "Conversion",
760            "namespace": "",
761            "file": "src/color/color_conversion.js",
762            "line": 1,
763            "requires": [
764                "core"
765            ]
766        },
767        "Color": {
768            "name": "Color",
769            "submodules": {
770                "Creating & Reading": 1,
771                "Setting": 1
772            },
773            "elements": {},
774            "classes": {
775                "p5.Color": 1
776            },
777            "fors": {
778                "p5": 1
779            },
780            "namespaces": {},
781            "file": "src/color/p5.Color.js",
782            "line": 16
783        },
784        "Creating & Reading": {
785            "name": "Creating & Reading",
786            "submodules": {},
787            "elements": {},
788            "classes": {
789                "p5.Color": 1
790            },
791            "fors": {
792                "p5": 1
793            },
794            "is_submodule": 1,
795            "namespaces": {},
796            "module": "Color",
797            "namespace": "",
798            "file": "src/color/p5.Color.js",
799            "line": 16,
800            "requires": [
801                "core",
802                "constants"
803            ],
804            "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 saturation() 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"
805        },
806        "Setting": {
807            "name": "Setting",
808            "submodules": {},
809            "elements": {},
810            "classes": {},
811            "fors": {
812                "p5": 1
813            },
814            "is_submodule": 1,
815            "namespaces": {},
816            "module": "Color",
817            "namespace": "",
818            "file": "src/color/setting.js",
819            "line": 1,
820            "requires": [
821                "core",
822                "constants"
823            ]
824        },
825        "Shape": {
826            "name": "Shape",
827            "submodules": {
828                "2D Primitives": 1,
829                "Curves": 1,
830                "Vertex": 1,
831                "3D Models": 1,
832                "3D Primitives": 1
833            },
834            "elements": {},
835            "classes": {},
836            "fors": {
837                "p5": 1
838            },
839            "namespaces": {}
840        },
841        "2D Primitives": {
842            "name": "2D Primitives",
843            "submodules": {},
844            "elements": {},
845            "classes": {},
846            "fors": {
847                "p5": 1
848            },
849            "is_submodule": 1,
850            "namespaces": {},
851            "module": "Shape",
852            "namespace": "",
853            "file": "src/core/2d_primitives.js",
854            "line": 1,
855            "requires": [
856                "core",
857                "constants"
858            ]
859        },
860        "Attributes": {
861            "name": "Attributes",
862            "submodules": {},
863            "elements": {},
864            "classes": {},
865            "fors": {
866                "p5": 1
867            },
868            "is_submodule": 1,
869            "namespaces": {},
870            "module": "Typography",
871            "namespace": "",
872            "file": "src/core/attributes.js",
873            "line": 1,
874            "requires": [
875                "core",
876                "constants"
877            ]
878        },
879        "Constants": {
880            "name": "Constants",
881            "submodules": {},
882            "elements": {},
883            "classes": {},
884            "fors": {
885                "p5": 1
886            },
887            "namespaces": {},
888            "module": "Constants",
889            "file": "src/core/constants.js",
890            "line": 1
891        },
892        "Structure": {
893            "name": "Structure",
894            "submodules": {},
895            "elements": {},
896            "classes": {},
897            "fors": {
898                "p5": 1
899            },
900            "namespaces": {},
901            "module": "IO",
902            "file": "src/core/core.js",
903            "line": 1,
904            "requires": [
905                "constants"
906            ]
907        },
908        "Curves": {
909            "name": "Curves",
910            "submodules": {},
911            "elements": {},
912            "classes": {},
913            "fors": {
914                "p5": 1
915            },
916            "is_submodule": 1,
917            "namespaces": {},
918            "module": "Shape",
919            "namespace": "",
920            "file": "src/core/curves.js",
921            "line": 1,
922            "requires": [
923                "core"
924            ]
925        },
926        "Environment": {
927            "name": "Environment",
928            "submodules": {},
929            "elements": {},
930            "classes": {},
931            "fors": {
932                "p5": 1
933            },
934            "namespaces": {},
935            "module": "Environment",
936            "file": "src/core/environment.js",
937            "line": 1,
938            "requires": [
939                "core",
940                "constants"
941            ]
942        },
943        "DOM": {
944            "name": "DOM",
945            "submodules": {},
946            "elements": {},
947            "classes": {
948                "p5.Element": 1
949            },
950            "fors": {
951                "p5.Element": 1
952            },
953            "namespaces": {},
954            "module": "DOM",
955            "file": "src/core/p5.Element.js",
956            "line": 11,
957            "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 p5.Element\nobjects are created by calling createCanvas, createGraphics,\nor in the p5.dom library, createDiv, createImg, createInput, etc.</p>\n"
958        },
959        "Rendering": {
960            "name": "Rendering",
961            "submodules": {
962                "undefined": 1
963            },
964            "elements": {},
965            "classes": {
966                "p5.RendererGL": 1,
967                "p5.Graphics": 1,
968                "p5.Renderer": 1
969            },
970            "fors": {
971                "p5": 1
972            },
973            "namespaces": {},
974            "module": "Rendering",
975            "file": "src/webgl/p5.RendererGL.js",
976            "line": 439,
977            "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"
978        },
979        "Transform": {
980            "name": "Transform",
981            "submodules": {},
982            "elements": {},
983            "classes": {},
984            "fors": {
985                "p5": 1
986            },
987            "namespaces": {},
988            "module": "Transform",
989            "file": "src/core/transform.js",
990            "line": 1,
991            "requires": [
992                "core",
993                "constants"
994            ]
995        },
996        "Vertex": {
997            "name": "Vertex",
998            "submodules": {},
999            "elements": {},
1000            "classes": {},
1001            "fors": {
1002                "p5": 1
1003            },
1004            "is_submodule": 1,
1005            "namespaces": {},
1006            "module": "Shape",
1007            "namespace": "",
1008            "file": "src/core/vertex.js",
1009            "line": 1,
1010            "requires": [
1011                "core",
1012                "constants"
1013            ]
1014        },
1015        "Data": {
1016            "name": "Data",
1017            "submodules": {
1018                "Dictionary": 1,
1019                "Array Functions": 1,
1020                "String Functions": 1
1021            },
1022            "elements": {},
1023            "classes": {
1024                "p5.TypedDict": 1,
1025                "p5.StringDict": 1,
1026                "p5.NumberDict": 1
1027            },
1028            "fors": {
1029                "p5.TypedDict": 1,
1030                "p5": 1
1031            },
1032            "namespaces": {},
1033            "file": "src/data/p5.TypedDict.js",
1034            "line": 407
1035        },
1036        "Dictionary": {
1037            "name": "Dictionary",
1038            "submodules": {},
1039            "elements": {},
1040            "classes": {
1041                "p5.TypedDict": 1,
1042                "p5.StringDict": 1,
1043                "p5.NumberDict": 1
1044            },
1045            "fors": {
1046                "p5.TypedDict": 1,
1047                "p5": 1
1048            },
1049            "is_submodule": 1,
1050            "namespaces": {},
1051            "module": "Data",
1052            "namespace": "",
1053            "file": "src/data/p5.TypedDict.js",
1054            "line": 407,
1055            "requires": [
1056                "core\n\nThis module defines the p5 methods for the p5 Dictionary classes\nthese classes StringDict and NumberDict are for storing and working\nwith key",
1057                "value pairs"
1058            ],
1059            "description": "<p>Base class for all p5.Dictionary types. More specifically\n typed Dictionary objects inherit from this</p>\n"
1060        },
1061        "Events": {
1062            "name": "Events",
1063            "submodules": {
1064                "Acceleration": 1,
1065                "Keyboard": 1,
1066                "Mouse": 1,
1067                "Touch": 1
1068            },
1069            "elements": {},
1070            "classes": {},
1071            "fors": {
1072                "p5": 1
1073            },
1074            "namespaces": {}
1075        },
1076        "Acceleration": {
1077            "name": "Acceleration",
1078            "submodules": {},
1079            "elements": {},
1080            "classes": {},
1081            "fors": {
1082                "p5": 1
1083            },
1084            "is_submodule": 1,
1085            "namespaces": {},
1086            "module": "Events",
1087            "namespace": "",
1088            "file": "src/events/acceleration.js",
1089            "line": 1,
1090            "requires": [
1091                "core"
1092            ]
1093        },
1094        "Keyboard": {
1095            "name": "Keyboard",
1096            "submodules": {},
1097            "elements": {},
1098            "classes": {},
1099            "fors": {
1100                "p5": 1
1101            },
1102            "is_submodule": 1,
1103            "namespaces": {},
1104            "module": "Events",
1105            "namespace": "",
1106            "file": "src/events/keyboard.js",
1107            "line": 1,
1108            "requires": [
1109                "core"
1110            ]
1111        },
1112        "Mouse": {
1113            "name": "Mouse",
1114            "submodules": {},
1115            "elements": {},
1116            "classes": {},
1117            "fors": {
1118                "p5": 1
1119            },
1120            "is_submodule": 1,
1121            "namespaces": {},
1122            "module": "Events",
1123            "namespace": "",
1124            "file": "src/events/mouse.js",
1125            "line": 1,
1126            "requires": [
1127                "core",
1128                "constants"
1129            ]
1130        },
1131        "Touch": {
1132            "name": "Touch",
1133            "submodules": {},
1134            "elements": {},
1135            "classes": {},
1136            "fors": {
1137                "p5": 1
1138            },
1139            "is_submodule": 1,
1140            "namespaces": {},
1141            "module": "Events",
1142            "namespace": "",
1143            "file": "src/events/touch.js",
1144            "line": 1,
1145            "requires": [
1146                "core"
1147            ]
1148        },
1149        "Image": {
1150            "name": "Image",
1151            "submodules": {
1152                "Pixels": 1
1153            },
1154            "elements": {},
1155            "classes": {
1156                "p5.Image": 1
1157            },
1158            "fors": {
1159                "p5": 1
1160            },
1161            "namespaces": {},
1162            "module": "Image",
1163            "file": "src/image/p5.Image.js",
1164            "line": 23,
1165            "requires": [
1166                "core"
1167            ],
1168            "description": "<p>Creates a new p5.Image. A p5.Image 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\nloadImage() function. The p5.Image class contains fields for the width and\nheight of the image, as well as an array called pixels[] 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 pixels[] array, be sure to use the loadPixels() method on\nthe image to make sure that the pixel data is properly loaded.</p>\n"
1169        },
1170        "Loading & Displaying": {
1171            "name": "Loading & Displaying",
1172            "submodules": {},
1173            "elements": {},
1174            "classes": {},
1175            "fors": {
1176                "p5": 1
1177            },
1178            "is_submodule": 1,
1179            "namespaces": {},
1180            "module": "Typography",
1181            "namespace": "",
1182            "file": "src/image/loading_displaying.js",
1183            "line": 1,
1184            "requires": [
1185                "core"
1186            ]
1187        },
1188        "Pixels": {
1189            "name": "Pixels",
1190            "submodules": {},
1191            "elements": {},
1192            "classes": {},
1193            "fors": {
1194                "p5": 1
1195            },
1196            "is_submodule": 1,
1197            "namespaces": {},
1198            "module": "Image",
1199            "namespace": "",
1200            "file": "src/image/pixels.js",
1201            "line": 1,
1202            "requires": [
1203                "core"
1204            ]
1205        },
1206        "IO": {
1207            "name": "IO",
1208            "submodules": {
1209                "Structure": 1,
1210                "Input": 1,
1211                "Output": 1,
1212                "Table": 1,
1213                "XML": 1,
1214                "Time & Date": 1
1215            },
1216            "elements": {},
1217            "classes": {
1218                "p5": 1,
1219                "p5.PrintWriter": 1,
1220                "p5.Table": 1,
1221                "p5.TableRow": 1,
1222                "p5.XML": 1
1223            },
1224            "fors": {
1225                "p5": 1
1226            },
1227            "namespaces": {},
1228            "file": "src/io/p5.XML.js",
1229            "line": 11
1230        },
1231        "Input": {
1232            "name": "Input",
1233            "submodules": {},
1234            "elements": {},
1235            "classes": {},
1236            "fors": {
1237                "p5": 1
1238            },
1239            "is_submodule": 1,
1240            "namespaces": {},
1241            "module": "IO",
1242            "namespace": "",
1243            "file": "src/io/files.js",
1244            "line": 1,
1245            "requires": [
1246                "core"
1247            ]
1248        },
1249        "Output": {
1250            "name": "Output",
1251            "submodules": {},
1252            "elements": {},
1253            "classes": {
1254                "p5": 1,
1255                "p5.PrintWriter": 1
1256            },
1257            "fors": {
1258                "p5": 1
1259            },
1260            "is_submodule": 1,
1261            "namespaces": {},
1262            "module": "IO",
1263            "namespace": "",
1264            "file": "src/io/files.js",
1265            "line": 1169,
1266            "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 preload(), setup(), and/or\ndraw() 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"
1267        },
1268        "Table": {
1269            "name": "Table",
1270            "submodules": {},
1271            "elements": {},
1272            "classes": {
1273                "p5.Table": 1,
1274                "p5.TableRow": 1
1275            },
1276            "fors": {},
1277            "is_submodule": 1,
1278            "namespaces": {},
1279            "module": "IO",
1280            "namespace": "",
1281            "file": "src/io/p5.TableRow.js",
1282            "line": 11,
1283            "requires": [
1284                "core"
1285            ],
1286            "description": "<p>Table 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"
1287        },
1288        "XML": {
1289            "name": "XML",
1290            "submodules": {},
1291            "elements": {},
1292            "classes": {
1293                "p5.XML": 1
1294            },
1295            "fors": {},
1296            "is_submodule": 1,
1297            "namespaces": {},
1298            "module": "IO",
1299            "namespace": "",
1300            "file": "src/io/p5.XML.js",
1301            "line": 11,
1302            "requires": [
1303                "core"
1304            ],
1305            "description": "<p>XML is a representation of an XML object, able to parse XML code. Use\nloadXML() to load external XML files and create XML objects.</p>\n"
1306        },
1307        "Math": {
1308            "name": "Math",
1309            "submodules": {
1310                "Calculation": 1,
1311                "Noise": 1,
1312                "Random": 1,
1313                "Trigonometry": 1
1314            },
1315            "elements": {},
1316            "classes": {
1317                "p5.Vector": 1
1318            },
1319            "fors": {
1320                "p5": 1
1321            },
1322            "namespaces": {},
1323            "module": "Math",
1324            "file": "src/math/p5.Vector.js",
1325            "line": 12,
1326            "requires": [
1327                "core"
1328            ],
1329            "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 mag() and heading().\n<br><br>\nIn many of the p5.js examples, you will see p5.Vector 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 p5.Vector class.</p>\n"
1330        },
1331        "Calculation": {
1332            "name": "Calculation",
1333            "submodules": {},
1334            "elements": {},
1335            "classes": {},
1336            "fors": {
1337                "p5": 1
1338            },
1339            "is_submodule": 1,
1340            "namespaces": {},
1341            "module": "Math",
1342            "namespace": "",
1343            "file": "src/math/calculation.js",
1344            "line": 1,
1345            "requires": [
1346                "core"
1347            ]
1348        },
1349        "Noise": {
1350            "name": "Noise",
1351            "submodules": {},
1352            "elements": {},
1353            "classes": {},
1354            "fors": {
1355                "p5": 1
1356            },
1357            "is_submodule": 1,
1358            "namespaces": {},
1359            "module": "Math",
1360            "namespace": "",
1361            "file": "src/math/noise.js",
1362            "line": 14,
1363            "requires": [
1364                "core"
1365            ]
1366        },
1367        "Random": {
1368            "name": "Random",
1369            "submodules": {},
1370            "elements": {},
1371            "classes": {},
1372            "fors": {
1373                "p5": 1
1374            },
1375            "is_submodule": 1,
1376            "namespaces": {},
1377            "module": "Math",
1378            "namespace": "",
1379            "file": "src/math/random.js",
1380            "line": 1,
1381            "requires": [
1382                "core"
1383            ]
1384        },
1385        "Trigonometry": {
1386            "name": "Trigonometry",
1387            "submodules": {},
1388            "elements": {},
1389            "classes": {},
1390            "fors": {
1391                "p5": 1
1392            },
1393            "is_submodule": 1,
1394            "namespaces": {},
1395            "module": "Math",
1396            "namespace": "",
1397            "file": "src/math/trigonometry.js",
1398            "line": 1,
1399            "requires": [
1400                "core",
1401                "constants"
1402            ]
1403        },
1404        "Typography": {
1405            "name": "Typography",
1406            "submodules": {
1407                "Attributes": 1,
1408                "Loading & Displaying": 1,
1409                "Font": 1
1410            },
1411            "elements": {},
1412            "classes": {
1413                "p5.Font": 1
1414            },
1415            "fors": {
1416                "p5": 1
1417            },
1418            "namespaces": {},
1419            "file": "src/typography/p5.Font.js",
1420            "line": 21
1421        },
1422        "Font": {
1423            "name": "Font",
1424            "submodules": {},
1425            "elements": {},
1426            "classes": {
1427                "p5.Font": 1
1428            },
1429            "fors": {},
1430            "is_submodule": 1,
1431            "namespaces": {},
1432            "module": "Typography",
1433            "namespace": "",
1434            "file": "src/typography/p5.Font.js",
1435            "line": 21,
1436            "description": "<p>This module defines the p5.Font class and functions for\ndrawing text to the display canvas.</p>\n",
1437            "requires": [
1438                "core",
1439                "constants"
1440            ]
1441        },
1442        "Array Functions": {
1443            "name": "Array Functions",
1444            "submodules": {},
1445            "elements": {},
1446            "classes": {},
1447            "fors": {
1448                "p5": 1
1449            },
1450            "is_submodule": 1,
1451            "namespaces": {},
1452            "module": "Data",
1453            "namespace": "",
1454            "file": "src/utilities/array_functions.js",
1455            "line": 1,
1456            "requires": [
1457                "core"
1458            ]
1459        },
1460        "String Functions": {
1461            "name": "String Functions",
1462            "submodules": {},
1463            "elements": {},
1464            "classes": {},
1465            "fors": {
1466                "p5": 1
1467            },
1468            "is_submodule": 1,
1469            "namespaces": {},
1470            "module": "Data",
1471            "namespace": "",
1472            "file": "src/utilities/string_functions.js",
1473            "line": 1,
1474            "requires": [
1475                "core"
1476            ]
1477        },
1478        "Time & Date": {
1479            "name": "Time & Date",
1480            "submodules": {},
1481            "elements": {},
1482            "classes": {},
1483            "fors": {
1484                "p5": 1
1485            },
1486            "is_submodule": 1,
1487            "namespaces": {},
1488            "module": "IO",
1489            "namespace": "",
1490            "file": "src/utilities/time_date.js",
1491            "line": 1,
1492            "requires": [
1493                "core"
1494            ]
1495        },
1496        "Lights, Camera": {
1497            "name": "Lights, Camera",
1498            "submodules": {
1499                "Camera": 1,
1500                "Lights": 1,
1501                "Material": 1,
1502                "Shaders": 1
1503            },
1504            "elements": {},
1505            "classes": {
1506                "p5.Geometry": 1,
1507                "p5.Matrix": 1,
1508                "p5.Shader": 1,
1509                "p5.Texture": 1
1510            },
1511            "fors": {
1512                "p5": 1
1513            },
1514            "namespaces": {},
1515            "file": "src/webgl/p5.Texture.js",
1516            "line": 13
1517        },
1518        "Camera": {
1519            "name": "Camera",
1520            "submodules": {},
1521            "elements": {},
1522            "classes": {},
1523            "fors": {
1524                "p5": 1
1525            },
1526            "is_submodule": 1,
1527            "namespaces": {},
1528            "module": "Lights, Camera",
1529            "namespace": "",
1530            "file": "src/webgl/camera.js",
1531            "line": 1,
1532            "requires": [
1533                "core"
1534            ]
1535        },
1536        "Lights": {
1537            "name": "Lights",
1538            "submodules": {},
1539            "elements": {},
1540            "classes": {},
1541            "fors": {
1542                "p5": 1
1543            },
1544            "is_submodule": 1,
1545            "namespaces": {},
1546            "module": "Lights, Camera",
1547            "namespace": "",
1548            "file": "src/webgl/light.js",
1549            "line": 1,
1550            "requires": [
1551                "core"
1552            ]
1553        },
1554        "3D Models": {
1555            "name": "3D Models",
1556            "submodules": {},
1557            "elements": {},
1558            "classes": {},
1559            "fors": {
1560                "p5": 1
1561            },
1562            "is_submodule": 1,
1563            "namespaces": {},
1564            "module": "Shape",
1565            "namespace": "",
1566            "file": "src/webgl/loading.js",
1567            "line": 1,
1568            "requires": [
1569                "core",
1570                "p5.Geometry"
1571            ]
1572        },
1573        "Material": {
1574            "name": "Material",
1575            "submodules": {},
1576            "elements": {},
1577            "classes": {
1578                "p5.Texture": 1
1579            },
1580            "fors": {
1581                "p5": 1
1582            },
1583            "is_submodule": 1,
1584            "namespaces": {},
1585            "module": "Lights, Camera",
1586            "namespace": "",
1587            "file": "src/webgl/p5.Texture.js",
1588            "line": 13,
1589            "requires": [
1590                "core"
1591            ],
1592            "description": "<p>This module defines the p5.Texture class</p>\n"
1593        },
1594        "Shaders": {
1595            "name": "Shaders",
1596            "submodules": {},
1597            "elements": {},
1598            "classes": {
1599                "p5.Shader": 1
1600            },
1601            "fors": {
1602                "p5": 1
1603            },
1604            "is_submodule": 1,
1605            "namespaces": {},
1606            "module": "Lights, Camera",
1607            "namespace": "",
1608            "file": "src/webgl/p5.Shader.js",
1609            "line": 13,
1610            "description": "<p>This module defines the p5.Shader class</p>\n",
1611            "requires": [
1612                "core"
1613            ]
1614        },
1615        "3D Primitives": {
1616            "name": "3D Primitives",
1617            "submodules": {},
1618            "elements": {},
1619            "classes": {},
1620            "fors": {
1621                "p5": 1
1622            },
1623            "is_submodule": 1,
1624            "namespaces": {},
1625            "module": "Shape",
1626            "namespace": "",
1627            "file": "src/webgl/primitives.js",
1628            "line": 1,
1629            "requires": [
1630                "core",
1631                "p5.Geometry"
1632            ]
1633        },
1634        "p5.dom": {
1635            "name": "p5.dom",
1636            "submodules": {},
1637            "elements": {},
1638            "classes": {
1639                "p5.dom": 1,
1640                "p5.MediaElement": 1,
1641                "p5.File": 1
1642            },
1643            "fors": {
1644                "p5.dom": 1,
1645                "p5.Element": 1
1646            },
1647            "namespaces": {},
1648            "module": "p5.dom",
1649            "file": "lib/addons/p5.dom.js",
1650            "line": 2885,
1651            "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 p5.Element 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 libary.</a></p>\n",
1652            "tag": "main",
1653            "itemtype": "main"
1654        },
1655        "p5.sound": {
1656            "name": "p5.sound",
1657            "submodules": {},
1658            "elements": {},
1659            "classes": {
1660                "p5.sound": 1,
1661                "p5.SoundFile": 1,
1662                "p5.Amplitude": 1,
1663                "p5.FFT": 1,
1664                "p5.Signal": 1,
1665                "p5.Oscillator": 1,
1666                "p5.SinOsc": 1,
1667                "p5.TriOsc": 1,
1668                "p5.SawOsc": 1,
1669                "p5.SqrOsc": 1,
1670                "p5.Env": 1,
1671                "p5.Pulse": 1,
1672                "p5.Noise": 1,
1673                "p5.AudioIn": 1,
1674                "p5.Effect": 1,
1675                "p5.Filter": 1,
1676                "p5.LowPass": 1,
1677                "p5.HighPass": 1,
1678                "p5.BandPass": 1,
1679                "p5.EQ": 1,
1680                "p5.Panner3D": 1,
1681                "p5.Delay": 1,
1682                "p5.Reverb": 1,
1683                "p5.Convolver": 1,
1684                "p5.Phrase": 1,
1685                "p5.Part": 1,
1686                "p5.Score": 1,
1687                "p5.SoundLoop": 1,
1688                "p5.Compressor": 1,
1689                "p5.SoundRecorder": 1,
1690                "p5.PeakDetect": 1,
1691                "p5.Gain": 1,
1692                "p5.AudioVoice": 1,
1693                "p5.MonoSynth": 1,
1694                "p5.PolySynth": 1,
1695                "p5.Distortion": 1
1696            },
1697            "fors": {
1698                "p5.sound": 1,
1699                "p5": 1
1700            },
1701            "namespaces": {},
1702            "module": "p5.sound",
1703            "file": "lib/addons/p5.sound.js",
1704            "line": 12243,
1705            "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  
1705<a href=\"#/p5.Noise\">p5.Noise</a> and <a href=\"#/p5.Pulse\">p5.Pulse</a>.\n  <br/>\n<a href=\"#/p5.Env\"><b>p5.Env</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",
1706            "tag": "main",
1707            "itemtype": "main"
1708        }
1709    },
1710    "classes": {
1711        "p5": {
1712            "name": "p5",
1713            "shortname": "p5",
1714            "classitems": [],
1715            "plugins": [],
1716            "extensions": [],
1717            "plugin_for": [],
1718            "extension_for": [],
1719            "module": "IO",
1720            "submodule": "Output",
1721            "namespace": "",
1722            "file": "src/core/core.js",
1723            "line": 15,
1724            "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 preload(), setup(), and/or\ndraw() 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",
1725            "is_constructor": 1,
1726            "params": [
1727                {
1728                    "name": "sketch",
1729                    "description": "<p>a closure that can set optional preload(),\n                             setup(), and/or draw() properties on the\n                             given p5 instance</p>\n",
1730                    "type": "Function"
1731                },
1732                {
1733                    "name": "node",
1734                    "description": "<p>element to attach canvas to, if a\n                                     boolean is passed in use it as sync</p>\n",
1735                    "type": "HTMLElement|Boolean",
1736                    "optional": true
1737                },
1738                {
1739                    "name": "sync",
1740                    "description": "<p>start synchronously (optional)</p>\n",
1741                    "type": "Boolean",
1742                    "optional": true
1743                }
1744            ],
1745            "return": {
1746                "description": "a p5 instance",
1747                "type": "P5"
1748            }
1749        },
1750        "p5.Color": {
1751            "name": "p5.Color",
1752            "shortname": "p5.Color",
1753            "classitems": [],
1754            "plugins": [],
1755            "extensions": [],
1756            "plugin_for": [],
1757            "extension_for": [],
1758            "module": "Color",
1759            "submodule": "Creating & Reading",
1760            "namespace": "",
1761            "file": "src/color/p5.Color.js",
1762            "line": 16,
1763            "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 saturation() 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"
1764        },
1765        "p5.Element": {
1766            "name": "p5.Element",
1767            "shortname": "p5.Element",
1768            "classitems": [],
1769            "plugins": [],
1770            "extensions": [],
1771            "plugin_for": [],
1772            "extension_for": [],
1773            "module": "DOM",
1774            "submodule": "DOM",
1775            "namespace": "",
1776            "file": "src/core/p5.Element.js",
1777            "line": 11,
1778            "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 p5.Element\nobjects are created by calling createCanvas, createGraphics,\nor in the p5.dom library, createDiv, createImg, createInput, etc.</p>\n",
1779            "params": [
1780                {
1781                    "name": "elt",
1782                    "description": "<p>DOM node that is wrapped</p>\n",
1783                    "type": "String"
1784                },
1785                {
1786                    "name": "pInst",
1787                    "description": "<p>pointer to p5 instance</p>\n",
1788                    "type": "P5",
1789                    "optional": true
1790                }
1791            ]
1792        },
1793        "p5.Graphics": {
1794            "name": "p5.Graphics",
1795            "shortname": "p5.Graphics",
1796            "classitems": [],
1797            "plugins": [],
1798            "extensions": [],
1799            "plugin_for": [],
1800            "extension_for": [],
1801            "module": "Rendering",
1802            "submodule": "Rendering",
1803            "namespace": "",
1804            "file": "src/core/p5.Graphics.js",
1805            "line": 12,
1806            "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",
1807            "extends": "p5.Element",
1808            "params": [
1809                {
1810                    "name": "w",
1811                    "description": "<p>width</p>\n",
1812                    "type": "Number"
1813                },
1814                {
1815                    "name": "h",
1816                    "description": "<p>height</p>\n",
1817                    "type": "Number"
1818                },
1819                {
1820                    "name": "renderer",
1821                    "description": "<p>the renderer to use, either P2D or WEBGL</p>\n",
1822                    "type": "Constant"
1823                },
1824                {
1825                    "name": "pInst",
1826                    "description": "<p>pointer to p5 instance</p>\n",
1827                    "type": "P5",
1828                    "optional": true
1829                }
1830            ]
1831        },
1832        "p5.Renderer": {
1833            "name": "p5.Renderer",
1834            "shortname": "p5.Renderer",
1835            "classitems": [],
1836            "plugins": [],
1837            "extensions": [],
1838            "plugin_for": [],
1839            "extension_for": [],
1840            "module": "Rendering",
1841            "submodule": "Rendering",
1842            "namespace": "",
1843            "file": "src/core/p5.Renderer.js",
1844            "line": 12,
1845            "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",
1846            "is_constructor": 1,
1847            "extends": "p5.Element",
1848            "params": [
1849                {
1850                    "name": "elt",
1851                    "description": "<p>DOM node that is wrapped</p>\n",
1852                    "type": "String"
1853                },
1854                {
1855                    "name": "pInst",
1856                    "description": "<p>pointer to p5 instance</p>\n",
1857                    "type": "P5",
1858                    "optional": true
1859                },
1860                {
1861                    "name": "isMainCanvas",
1862                    "description": "<p>whether we&#39;re using it as main canvas</p>\n",
1863                    "type": "Boolean",
1864                    "optional": true
1865                }
1866            ]
1867        },
1868        "p5.TypedDict": {
1869            "name": "p5.TypedDict",
1870            "shortname": "p5.TypedDict",
1871            "classitems": [],
1872            "plugins": [],
1873            "extensions": [],
1874            "plugin_for": [],
1875            "extension_for": [],
1876            "module": "Data",
1877            "submodule": "Dictionary",
1878            "namespace": "",
1879            "file": "src/data/p5.TypedDict.js",
1880            "line": 78,
1881            "description": "<p>Base class for all p5.Dictionary types. More specifically\n typed Dictionary objects inherit from this</p>\n"
1882        },
1883        "p5.StringDict": {
1884            "name": "p5.StringDict",
1885            "shortname": "p5.StringDict",
1886            "classitems": [],
1887            "plugins": [],
1888            "extensions": [],
1889            "plugin_for": [],
1890            "extension_for": [],
1891            "module": "Data",
1892            "submodule": "Dictionary",
1893            "namespace": "",
1894            "file": "src/data/p5.TypedDict.js",
1895            "line": 387,
1896            "description": "<p>A  Dictionary class for Strings.</p>\n",
1897            "extends": "p5.TypedDict"
1898        },
1899        "p5.NumberDict": {
1900            "name": "p5.NumberDict",
1901            "shortname": "p5.NumberDict",
1902            "classitems": [],
1903            "plugins": [],
1904            "extensions": [],
1905            "plugin_for": [],
1906            "extension_for": [],
1907            "module": "Data",
1908            "submodule": "Dictionary",
1909            "namespace": "",
1910            "file": "src/data/p5.TypedDict.js",
1911            "line": 407,
1912            "description": "<p>A simple Dictionary class for Numbers.</p>\n",
1913            "extends": "p5.TypedDict"
1914        },
1915        "p5.Image": {
1916            "name": "p5.Image",
1917            "shortname": "p5.Image",
1918            "classitems": [],
1919            "plugins": [],
1920            "extensions": [],
1921            "plugin_for": [],
1922            "extension_for": [],
1923            "module": "Image",
1924            "submodule": "Image",
1925            "namespace": "",
1926            "file": "src/image/p5.Image.js",
1927            "line": 23,
1928            "description": "<p>Creates a new p5.Image. A p5.Image 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\nloadImage() function. The p5.Image class contains fields for the width and\nheight of the image, as well as an array called pixels[] 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 pixels[] array, be sure to use the loadPixels() method on\nthe image to make sure that the pixel data is properly loaded.</p>\n",
1929            "example": [
1930                "\n<div><code>\nfunction setup() {\n  var 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    var 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  var x, y;\n  // fill with random colors\n  for (y = 0; y < img.height; y++) {\n    for (x = 0; x < img.width; x++) {\n      var red = random(255);\n      var green = random(255);\n      var blue = random(255);\n      var 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>"
1931            ],
1932            "params": [
1933                {
1934                    "name": "width",
1935                    "description": "",
1936                    "type": "Number"
1937                },
1938                {
1939                    "name": "height",
1940                    "description": "",
1941                    "type": "Number"
1942                }
1943            ]
1944        },
1945        "p5.PrintWriter": {
1946            "name": "p5.PrintWriter",
1947            "shortname": "p5.PrintWriter",
1948            "classitems": [],
1949            "plugins": [],
1950            "extensions": [],
1951            "plugin_for": [],
1952            "extension_for": [],
1953            "module": "IO",
1954            "submodule": "Output",
1955            "namespace": "",
1956            "file": "src/io/files.js",
1957            "line": 1169,
1958            "params": [
1959                {
1960                    "name": "filename",
1961                    "description": "",
1962                    "type": "String"
1963                },
1964                {
1965                    "name": "extension",
1966                    "description": "",
1967                    "type": "String",
1968                    "optional": true
1969                }
1970            ]
1971        },
1972        "p5.Table": {
1973            "name": "p5.Table",
1974            "shortname": "p5.Table",
1975            "classitems": [],
1976            "plugins": [],
1977            "extensions": [],
1978            "plugin_for": [],
1979            "extension_for": [],
1980            "module": "IO",
1981            "submodule": "Table",
1982            "namespace": "",
1983            "file": "src/io/p5.Table.js",
1984            "line": 35,
1985            "description": "<p>Table 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",
1986            "is_constructor": 1,
1987            "params": [
1988                {
1989                    "name": "rows",
1990                    "description": "<p>An array of p5.TableRow objects</p>\n",
1991                    "type": "p5.TableRow[]",
1992                    "optional": true
1993                }
1994            ]
1995        },
1996        "p5.TableRow": {
1997            "name": "p5.TableRow",
1998            "shortname": "p5.TableRow",
1999            "classitems": [],
2000            "plugins": [],
2001            "extensions": [],
2002            "plugin_for": [],
2003            "extension_for": [],
2004            "module": "IO",
2005            "submodule": "Table",
2006            "namespace": "",
2007            "file": "src/io/p5.TableRow.js",
2008            "line": 11,
2009            "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",
2010            "is_constructor": 1,
2011            "params": [
2012                {
2013                    "name": "str",
2014                    "description": "<p>optional: populate the row with a\n                            string of values, separated by the\n                            separator</p>\n",
2015                    "type": "String",
2016                    "optional": true
2017                },
2018                {
2019                    "name": "separator",
2020                    "description": "<p>comma separated values (csv) by default</p>\n",
2021                    "type": "String",
2022                    "optional": true
2023                }
2024            ]
2025        },
2026        "p5.XML": {
2027            "name": "p5.XML",
2028            "shortname": "p5.XML",
2029            "classitems": [],
2030            "plugins": [],
2031            "extensions": [],
2032            "plugin_for": [],
2033            "extension_for": [],
2034            "module": "IO",
2035            "submodule": "XML",
2036            "namespace": "",
2037            "file": "src/io/p5.XML.js",
2038            "line": 11,
2039            "description": "<p>XML is a representation of an XML object, able to parse XML code. Use\nloadXML() to load external XML files and create XML objects.</p>\n",
2040            "is_constructor": 1,
2041            "example": [
2042                "\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\nvar xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  var children = xml.getChildren('animal');\n\n  for (var i = 0; i < children.length;
2042 i++) {\n    var id = children[i].getNum('id');\n    var coloring = children[i].getString('species');\n    var 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>"
2043            ],
2044            "alt": "no image displayed"
2045        },
2046        "p5.Vector": {
2047            "name": "p5.Vector",
2048            "shortname": "p5.Vector",
2049            "classitems": [],
2050            "plugins": [],
2051            "extensions": [],
2052            "plugin_for": [],
2053            "extension_for": [],
2054            "module": "Math",
2055            "submodule": "Math",
2056            "namespace": "",
2057            "file": "src/math/p5.Vector.js",
2058            "line": 12,
2059            "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 mag() and heading().\n<br><br>\nIn many of the p5.js examples, you will see p5.Vector 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 p5.Vector class.</p>\n",
2060            "params": [
2061                {
2062                    "name": "x",
2063                    "description": "<p>x component of the vector</p>\n",
2064                    "type": "Number",
2065                    "optional": true
2066                },
2067                {
2068                    "name": "y",
2069                    "description": "<p>y component of the vector</p>\n",
2070                    "type": "Number",
2071                    "optional": true
2072                },
2073                {
2074                    "name": "z",
2075                    "description": "<p>z component of the vector</p>\n",
2076                    "type": "Number",
2077                    "optional": true
2078                }
2079            ],
2080            "example": [
2081                "\n<div>\n<code>\nvar v1 = createVector(40, 50);\nvar 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>"
2082            ],
2083            "alt": "2 white ellipses. One center-left the other bottom right and off canvas"
2084        },
2085        "p5.Font": {
2086            "name": "p5.Font",
2087            "shortname": "p5.Font",
2088            "classitems": [],
2089            "plugins": [],
2090            "extensions": [],
2091            "plugin_for": [],
2092            "extension_for": [],
2093            "module": "Typography",
2094            "submodule": "Font",
2095            "namespace": "",
2096            "file": "src/typography/p5.Font.js",
2097            "line": 21,
2098            "description": "<p>Base class for font handling</p>\n",
2099            "params": [
2100                {
2101                    "name": "pInst",
2102                    "description": "<p>pointer to p5 instance</p>\n",
2103                    "type": "P5",
2104                    "optional": true
2105                }
2106            ]
2107        },
2108        "p5.Geometry": {
2109            "name": "p5.Geometry",
2110            "shortname": "p5.Geometry",
2111            "classitems": [],
2112            "plugins": [],
2113            "extensions": [],
2114            "plugin_for": [],
2115            "extension_for": [],
2116            "module": "Lights, Camera",
2117            "namespace": "",
2118            "file": "src/webgl/p5.Geometry.js",
2119            "line": 6,
2120            "description": "<p>p5 Geometry class</p>\n",
2121            "is_constructor": 1,
2122            "params": [
2123                {
2124                    "name": "vertData",
2125                    "description": "<p>callback function or Object\n                    containing routine(s) for vertex data generation</p>\n",
2126                    "type": "Function | Object"
2127                },
2128                {
2129                    "name": "detailX",
2130                    "description": "<p>number of vertices on horizontal surface</p>\n",
2131                    "type": "Integer",
2132                    "optional": true
2133                },
2134                {
2135                    "name": "detailY",
2136                    "description": "<p>number of vertices on horizontal surface</p>\n",
2137                    "type": "Integer",
2138                    "optional": true
2139                },
2140                {
2141                    "name": "callback",
2142                    "description": "<p>function to call upon object instantiation.</p>\n",
2143                    "type": "Function",
2144                    "optional": true
2145                }
2146            ]
2147        },
2148        "p5.Shader": {
2149            "name": "p5.Shader",
2150            "shortname": "p5.Shader",
2151            "classitems": [],
2152            "plugins": [],
2153            "extensions": [],
2154            "plugin_for": [],
2155            "extension_for": [],
2156            "module": "Lights, Camera",
2157            "submodule": "Shaders",
2158            "namespace": "",
2159            "file": "src/webgl/p5.Shader.js",
2160            "line": 13,
2161            "description": "<p>Shader class for WEBGL Mode</p>\n",
2162            "params": [
2163                {
2164                    "name": "renderer",
2165                    "description": "<p>an instance of p5.RendererGL that\nwill provide the GL context for this new p5.Shader</p>\n",
2166                    "type": "p5.RendererGL"
2167                },
2168                {
2169                    "name": "vertSrc",
2170                    "description": "<p>source code for the vertex shader (as a string)</p>\n",
2171                    "type": "String"
2172                },
2173                {
2174                    "name": "fragSrc",
2175                    "description": "<p>source code for the fragment shader (as a string)</p>\n",
2176                    "type": "String"
2177                }
2178            ]
2179        },
2180        "p5.dom": {
2181            "name": "p5.dom",
2182            "shortname": "p5.dom",
2183            "classitems": [],
2184            "plugins": [],
2185            "extensions": [],
2186            "plugin_for": [],
2187            "extension_for": [],
2188            "module": "p5.dom",
2189            "submodule": "p5.dom",
2190            "namespace": ""
2191        },
2192        "p5.MediaElement": {
2193            "name": "p5.MediaElement",
2194            "shortname": "p5.MediaElement",
2195            "classitems": [],
2196            "plugins": [],
2197            "extensions": [],
2198            "plugin_for": [],
2199            "extension_for": [],
2200            "module": "p5.dom",
2201            "submodule": "p5.dom",
2202            "namespace": "",
2203            "file": "lib/addons/p5.dom.js",
2204            "line": 1829,
2205            "description": "<p>Extends p5.Element to handle audio and video. In addition to the methods\nof p5.Element, it also contains methods for controlling media. It is not\ncalled directly, but p5.MediaElements are created by calling createVideo,\ncreateAudio, and createCapture.</p>\n",
2206            "is_constructor": 1,
2207            "params": [
2208                {
2209                    "name": "elt",
2210                    "description": "<p>DOM node that is wrapped</p>\n",
2211                    "type": "String"
2212                }
2213            ]
2214        },
2215        "p5.File": {
2216            "name": "p5.File",
2217            "shortname": "p5.File",
2218            "classitems": [],
2219            "plugins": [],
2220            "extensions": [],
2221            "plugin_for": [],
2222            "extension_for": [],
2223            "module": "p5.dom",
2224            "submodule": "p5.dom",
2225            "namespace": "",
2226            "file": "lib/addons/p5.dom.js",
2227            "line": 2885,
2228            "description": "<p>Base class for a file\nUsing this for createFileInput</p>\n",
2229            "is_constructor": 1,
2230            "params": [
2231                {
2232                    "name": "file",
2233                    "description": "<p>File that is wrapped</p>\n",
2234                    "type": "File"
2235                }
2236            ]
2237        },
2238        "p5.sound": {
2239            "name": "p5.sound",
2240            "shortname": "p5.sound",
2241            "classitems": [],
2242            "plugins": [],
2243            "extensions": [],
2244            "plugin_for": [],
2245            "extension_for": [],
2246            "module": "p5.sound",
2247            "submodule": "p5.sound",
2248            "namespace": ""
2249        },
2250        "p5.SoundFile": {
2251            "name": "p5.SoundFile",
2252            "shortname": "p5.SoundFile",
2253            "classitems": [],
2254            "plugins": [],
2255            "extensions": [],
2256            "plugin_for": [],
2257            "extension_for": [],
2258            "module": "p5.sound",
2259            "submodule": "p5.sound",
2260            "namespace": "",
2261            "file": "lib/addons/p5.sound.js",
2262            "line": 740,
2263            "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>",
2264            "is_constructor": 1,
2265            "params": [
2266                {
2267                    "name": "path",
2268                    "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",
2269                    "type": "String|Array"
2270                },
2271                {
2272                    "name": "successCallback",
2273                    "description": "<p>Name of a function to call once file loads</p>\n",
2274                    "type": "Function",
2275                    "optional": true
2276                },
2277                {
2278                    "name": "errorCallback",
2279                    "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",
2280                    "type": "Function",
2281                    "optional": true
2282                },
2283                {
2284                    "name": "whileLoadingCallback",
2285                    "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",
2286                    "type": "Function",
2287                    "optional": true
2288                }
2289            ],
2290            "example": [
2291                "\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>"
2292            ]
2293        },
2294        "p5.Amplitude": {
2295            "name": "p5.Amplitude",
2296            "shortname": "p5.Amplitude",
2297            "classitems": [],
2298            "plugins": [],
2299            "extensions": [],
2300            "plugin_for": [],
2301            "extension_for": [],
2302            "module": "p5.sound",
2303            "submodule": "p5.sound",
2304            "namespace": "",
2305            "file": "lib/addons/p5.sound.js",
2306            "line": 2154,
2307            "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",
2308            "is_constructor": 1,
2309            "params": [
2310                {
2311                    "name": "smoothing",
2312                    "description": "<p>between 0.0 and .999 to smooth\n                           amplitude readings (defaults to 0)</p>\n",
2313                    "type": "Number",
2314                    "optional": true
2315                }
2316            ],
2317            "example": [
2318                "\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() {\n    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>"
2319            ]
2320        },
2321        "p5.FFT": {
2322            "name": "p5.FFT",
2323            "shortname": "p5.FFT",
2324            "classitems": [],
2325            "plugins": [],
2326            "extensions": [],
2327            "plugin_for": [],
2328            "extension_for": [],
2329            "module": "p5.sound",
2330            "submodule": "p5.sound",
2331            "namespace": "",
2332            "file": "lib/addons/p5.sound.js",
2333            "line": 2426,
2334            "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>",
2335            "is_constructor": 1,
2336            "params": [
2337                {
2338                    "name": "smoothing",
2339                    "description": "<p>Smooth results of Freq Spectrum.\n                              0.0 &lt; smoothing &lt; 1.0.\n                              Defaults to 0.8.</p>\n",
2340                    "type": "Number",
2341                    "optional": true
2342                },
2343                {
2344                    "name": "bins",
2345                    "description": "<p>Length of resulting array.\n                          Must be a power of two between\n                          16 and 1024. Defaults to 1024.</p>\n",
2346                    "type": "Number",
2347                    "optional": true
2348                }
2349            ],
2350            "example": [
2351                "\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>"
2352            ]
2353        },
2354        "p5.Signal": {
2355            "name": "p5.Signal",
2356            "shortname": "p5.Signal",
2357            "classitems": [],
2358            "plugins": [],
2359            "extensions": [],
2360            "plugin_for": [],
2361            "extension_for": [],
2362            "module": "p5.sound",
2363            "submodule": "p5.sound",
2364            "namespace": "",
2365            "file": "lib/addons/p5.sound.js",
2366            "line": 4828,
2367            "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>",
2368            "is_constructor": 1,
2369            "return": {
2370                "description": "A Signal object from the Tone.js library",
2371                "type": "Tone.Signal"
2372            },
2373            "example": [
2374                "\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 so the range is 20 to 420\n  carrier.freq( modulator.mult(-200).add(220) );\n}\n</code></div>"
2375            ]
2376        },
2377        "p5.Oscillator": {
2378            "name": "p5.Oscillator",
2379            "shortname": "p5.Oscillator",
2380            "classitems": [],
2381            "plugins": [],
2382            "extensions": [],
2383            "plugin_for": [],
2384            "extension_for": [],
2385            "module": "p5.sound",
2386            "submodule": "p5.sound",
2387            "namespace": "",
2388            "file": "lib/addons/p5.sound.js",
2389            "line": 4974,
2390            "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>",
2391            "is_constructor": 1,
2392            "params": [
2393                {
2394                    "name": "freq",
2395                    "description": "<p>frequency defaults to 440Hz</p>\n",
2396                    "type": "Number",
2397                    "optional": true
2398                },
2399                {
2400                    "name": "type",
2401                    "description": "<p>type of oscillator. Options:\n                       &#39;sine&#39; (default), &#39;triangle&#39;,\n                       &#39;sawtooth&#39;, &#39;square&#39;</p>\n",
2402                    "type": "String",
2403                    "optional": true
2404                }
2405            ],
2406            "example": [
2407                "\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>"
2408            ]
2409        },
2410        "p5.SinOsc": {
2411            "name": "p5.SinOsc",
2412            "shortname": "p5.SinOsc",
2413            "classitems": [],
2414            "plugins": [],
2415            "extensions": [],
2416            "plugin_for": [],
2417            "extension_for": [],
2418            "module": "p5.sound",
2419            "submodule": "p5.sound",
2420            "namespace": "",
2421            "file": "lib/addons/p5.sound.js",
2422            "line": 5409,
2423            "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",
2424            "is_constructor": 1,
2425            "extends": "p5.Oscillator",
2426            "params": [
2427                {
2428                    "name": "freq",
2429                    "description": "<p>Set the frequency</p>\n",
2430                    "type": "Number",
2431                    "optional": true
2432                }
2433            ]
2434        },
2435        "p5.TriOsc": {
2436            "name": "p5.TriOsc",
2437            "shortname": "p5.TriOsc",
2438            "classitems": [],
2439            "plugins": [],
2440            "extensions": [],
2441            "plugin_for": [],
2442            "extension_for": [],
2443            "module": "p5.sound",
2444            "submodule": "p5.sound",
2445            "namespace": "",
2446            "file": "lib/addons/p5.sound.js",
2447            "line": 5426,
2448            "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",
2449            "is_constructor": 1,
2450            "extends": "p5.Oscillator",
2451            "params": [
2452                {
2453                    "name": "freq",
2454                    "description": "<p>Set the frequency</p>\n",
2455                    "type": "Number",
2456                    "optional": true
2457                }
2458            ]
2459        },
2460        "p5.SawOsc": {
2461            "name": "p5.SawOsc",
2462            "shortname": "p5.SawOsc",
2463            "classitems": [],
2464            "plugins": [],
2465            "extensions": [],
2466            "plugin_for": [],
2467            "extension_for": [],
2468            "module": "p5.sound",
2469            "submodule": "p5.sound",
2470            "namespace": "",
2471            "file": "lib/addons/p5.sound.js",
2472            "line": 5443,
2473            "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",
2474            "is_constructor": 1,
2475            "extends": "p5.Oscillator",
2476            "params": [
2477                {
2478                    "name": "freq",
2479                    "description": "<p>Set the frequency</p>\n",
2480                    "type": "Number",
2481                    "optional": true
2482                }
2483            ]
2484        },
2485        "p5.SqrOsc": {
2486            "name": "p5.SqrOsc",
2487            "shortname": "p5.SqrOsc",
2488            "classitems": [],
2489            "plugins": [],
2490            "extensions": [],
2491            "plugin_for": [],
2492            "extension_for": [],
2493            "module": "p5.sound",
2494            "submodule": "p5.sound",
2495            "namespace": "",
2496            "file": "lib/addons/p5.sound.js",
2497            "line": 5460,
2498            "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",
2499            "is_constructor": 1,
2500            "extends": "p5.Oscillator",
2501            "params": [
2502                {
2503                    "name": "freq",
2504                    "description": "<p>Set the frequency</p>\n",
2505                    "type": "Number",
2506                    "optional": true
2507                }
2508            ]
2509        },
2510        "p5.Env": {
2511            "name": "p5.Env",
2512            "shortname": "p5.Env",
2513            "classitems": [],
2514            "plugins": [],
2515            "extensions": [],
2516            "plugin_for": [],
2517            "extension_for": [],
2518            "module": "p5.sound",
2519            "submodule": "p5.sound",
2520            "namespace": "",
2521            "file": "lib/addons/p5.sound.js",
2522            "line": 5917,
2523            "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.Env can\ncontrol an Oscillator&#39;s frequency like this: <code>osc.freq(env)</code>.</p>\n<p>Use <code><a href=\"#/p5.Env/setRange\">setRange</a></code> to change the attack/release level.\nUse <code><a href=\"#/p5.Env/setADSR\">setADSR</a></code> to change attackTime, decayTime, sustainPercent and releaseTime.</p>\n<p>Use the <code><a href=\"#/p5.Env/play\">play</a></code> method to play the entire envelope,\nthe <code><a href=\"#/p5.Env/ramp\">ramp</a></code> method for a pingable trigger,\nor <code><a href=\"#/p5.Env/triggerAttack\">triggerAttack</a></code>/\n<code><a href=\"#/p5.Env/triggerRelease\">triggerRelease</a></code> to trigger noteOn/noteOff.</p>",
2524            "is_constructor": 1,
2525            "example": [
2526                "\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.Env();\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>"
2527            ]
2528        },
2529        "p5.Pulse": {
2530            "name": "p5.Pulse",
2531            "shortname": "p5.Pulse",
2532            "classitems": [],
2533            "plugins": [],
2534            "extensions": [],
2535            "plugin_for": [],
2536            "extension_for": [],
2537            "module": "p5.sound",
2538            "submodule": "p5.sound",
2539            "namespace": "",
2540            "file": "lib/addons/p5.sound.js",
2541            "line": 6709,
2542            "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",
2543            "extends": "p5.Oscillator",
2544            "is_constructor": 1,
2545            "params": [
2546                {
2547                    "name": "freq",
2548                    "description": "<p>Frequency in oscillations per second (Hz)</p>\n",
2549                    "type": "Number",
2550                    "optional": true
2551                },
2552                {
2553                    "name": "w",
2554                    "description": "<p>Width between the pulses (0 to 1.0,\n                       defaults to 0)</p>\n",
2555                    "type": "Number",
2556                    "optional": true
2557                }
2558            ],
2559            "example": [
2560                "\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>"
2561            ]
2562        },
2563        "p5.Noise": {
2564            "name": "p5.Noise",
2565            "shortname": "p5.Noise",
2566            "classitems": [],
2567            "plugins": [],
2568            "extensions": [],
2569            "plugin_for": [],
2570            "extension_for": [],
2571            "module": "p5.sound",
2572            "submodule": "p5.sound",
2573            "namespace": "",
2574            "file": "lib/addons/p5.sound.js",
2575            "line": 6886,
2576            "description": "<p>Noise is a type of oscillator that generates a buffer with random values.</p>\n",
2577            "extends": "p5.Oscillator",
2578            "is_constructor": 1,
2579            "params": [
2580                {
2581                    "name": "type",
2582                    "description": "<p>Type of noise can be &#39;white&#39; (default),\n                     &#39;brown&#39; or &#39;pink&#39;.</p>\n",
2583                    "type": "String"
2584                }
2585            ]
2586        },
2587        "p5.AudioIn": {
2588            "name": "p5.AudioIn",
2589            "shortname": "p5.AudioIn",
2590            "classitems": [],
2591            "plugins": [],
2592            "extensions": [],
2593            "plugin_for": [],
2594            "extension_for": [],
2595            "module": "p5.sound",
2596            "submodule": "p5.sound",
2597            "namespace": "",
2598            "file": "lib/addons/p5.sound.js",
2599            "line": 7075,
2600            "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>",
2601            "is_constructor": 1,
2602            "params": [
2603                {
2604                    "name": "errorCallback",
2605                    "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",
2606                    "type": "Function",
2607                    "optional": true
2608                }
2609            ],
2610            "example": [
2611                "\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>"
2612            ]
2613        },
2614        "p5.Effect": {
2615            "name": "p5.Effect",
2616            "shortname": "p5.Effect",
2617            "classitems": [],
2618            "plugins": [],
2619            "extensions": [],
2620            "plugin_for": [],
2621            "extension_for": [],
2622            "module": "p5.sound",
2623            "submodule": "p5.sound",
2624            "namespace": "",
2625            "file": "lib/addons/p5.sound.js",
2626            "line": 7970,
2627            "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",
2628            "is_constructor": 1,
2629            "params": [
2630                {
2631                    "name": "ac",
2632                    "description": "<p>Reference to the audio context of the p5 object</p>\n",
2633                    "type": "Object",
2634                    "optional": true
2635                },
2636                {
2637                    "name": "input",
2638                    "description": "<p>Gain Node effect wrapper</p>\n",
2639                    "type": "AudioNode",
2640                    "optional": true
2641                },
2642                {
2643                    "name": "output",
2644                    "description": "<p>Gain Node effect wrapper</p>\n",
2645                    "type": "AudioNode",
2646                    "optional": true
2647                },
2648                {
2649                    "name": "_drywet",
2650                    "description": "<p>Tone.JS CrossFade node (defaults to value: 1)</p>\n",
2651                    "type": "Object",
2652                    "optional": true
2653                },
2654                {
2655                    "name": "wet",
2656                    "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",
2657                    "type": "AudioNode",
2658                    "optional": true
2659                }
2660            ]
2661        },
2662        "p5.Filter": {
2663            "name": "p5.Filter",
2664            "shortname": "p5.Filter",
2665            "classitems": [],
2666            "plugins": [],
2667            "extensions": [],
2668            "plugin_for": [],
2669            "extension_for": [],
2670            "module": "p5.sound",
2671            "submodule": "p5.sound",
2672            "namespace": "",
2673            "file": "lib/addons/p5.sound.js",
2674            "line": 8102,
2675            "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>.\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",
2676            "extends": "p5.Effect",
2677            "is_constructor": 1,
2678            "params": [
2679                {
2680                    "name": "type",
2681                    "description": "<p>&#39;lowpass&#39; (default), &#39;highpass&#39;, &#39;bandpass&#39;</p>\n",
2682                    "type": "String",
2683                    "optional": true
2684                }
2685            ],
2686            "example": [
2687                "\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; 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>"
2688            ]
2689        },
2690        "p5.LowPass": {
2691            "name": "p5.LowPass",
2692            "shortname": "p5.LowPass",
2693            "classitems": [],
2694            "plugins": [],
2695            "extensions": [],
2696            "plugin_for": [],
2697            "extension_for": [],
2698            "module": "p5.sound",
2699            "submodule": "p5.sound",
2700            "namespace": "",
2701            "file": "lib/addons/p5.sound.js",
2702            "line": 8332,
2703            "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",
2704            "is_constructor": 1,
2705            "extends": "p5.Filter"
2706        },
2707        "p5.HighPass": {
2708            "name": "p5.HighPass",
2709            "shortname": "p5.HighPass",
2710            "classitems": [],
2711            "plugins": [],
2712            "extensions": [],
2713            "plugin_for": [],
2714            "extension_for": [],
2715            "module": "p5.sound",
2716            "submodule": "p5.sound",
2717            "namespace": "",
2718            "file": "lib/addons/p5.sound.js",
2719            "line": 8346,
2720            "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",
2721            "is_constructor": 1,
2722            "extends": "p5.Filter"
2723        },
2724        "p5.BandPass": {
2725            "name": "p5.BandPass",
2726            "shortname": "p5.BandPass",
2727            "classitems": [],
2728            "plugins": [],
2729            "extensions": [],
2730            "plugin_for": [],
2731            "extension_for": [],
2732            "module": "p5.sound",
2733            "submodule": "p5.sound",
2734            "namespace": "",
2735            "file": "lib/addons/p5.sound.js",
2736            "line": 8360,
2737            "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",
2738            "is_constructor": 1,
2739            "extends": "p5.Filter"
2740        },
2741        "p5.EQ": {
2742            "name": "p5.EQ",
2743            "shortname": "p5.EQ",
2744            "classitems": [],
2745            "plugins": [],
2746            "extensions": [],
2747            "plugin_for": [],
2748            "extension_for": [],
2749            "module": "p5.sound",
2750            "submodule": "p5.sound",
2751            "namespace": "",
2752            "file": "lib/addons/p5.sound.js",
2753            "line": 8429,
2754            "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",
2755            "is_constructor": 1,
2756            "extends": "p5.Effect",
2757            "params": [
2758                {
2759                    "name": "_eqsize",
2760                    "description": "<p>Constructor will accept 3 or 8, defaults to 3</p>\n",
2761                    "type": "Number",
2762                    "optional": true
2763                }
2764            ],
2765            "return": {
2766                "description": "p5.EQ object",
2767                "type": "Object"
2768            },
2769            "example": [
2770                "\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>"
2771            ]
2772        },
2773        "p5.Panner3D": {
2774            "name": "p5.Panner3D",
2775            "shortname": "p5.Panner3D",
2776            "classitems": [],
2777            "plugins": [],
2778            "extensions": [],
2779            "plugin_for": [],
2780            "extension_for": [],
2781            "module": "p5.sound",
2782            "submodule": "p5.sound",
2783            "namespace": "",
2784            "file": "lib/addons/p5.sound.js",
2785            "line": 8619,
2786            "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",
2787            "is_constructor": 1
2788        },
2789        "p5.Delay": {
2790            "name": "p5.Delay",
2791            "shortname": "p5.Delay",
2792            "classitems": [],
2793            "plugins": [],
2794            "extensions": [],
2795            "plugin_for": [],
2796            "extension_for": [],
2797            "module": "p5.sound",
2798            "submodule": "p5.sound",
2799            "namespace": "",
2800            "file": "lib/addons/p5.sound.js",
2801            "line": 9068,
2802            "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>.\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",
2803            "extends": "p5.Effect",
2804            "is_constructor": 1,
2805            "example": [
2806                "\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.Env(.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>"
2807            ]
2808        },
2809        "p5.Reverb": {
2810            "name": "p5.Reverb",
2811            "shortname": "p5.Reverb",
2812            "classitems": [],
2813            "plugins": [],
2814            "extensions": [],
2815            "plugin_for": [],
2816            "extension_for": [],
2817            "module": "p5.sound",
2818            "submodule": "p5.sound",
2819            "namespace": "",
2820            "file": "lib/addons/p5.sound.js",
2821            "line": 9345,
2822            "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",
2823            "extends": "p5.Effect",
2824            "is_constructor": 1,
2825            "example": [
2826                "\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>"
2827            ]
2828        },
2829        "p5.Convolver": {
2830            "name": "p5.Convolver",
2831            "shortname": "p5.Convolver",
2832            "classitems": [],
2833            "plugins": [],
2834            "extensions": [],
2835            "plugin_for": [],
2836            "extension_for": [],
2837            "module": "p5.sound",
2838            "submodule": "p5.sound",
2839            "namespace": "",
2840            "file": "lib/addons/p5.sound.js",
2841            "line": 9505,
2842            "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\n
2842and 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>",
2843            "extends": "p5.Effect",
2844            "is_constructor": 1,
2845            "params": [
2846                {
2847                    "name": "path",
2848                    "description": "<p>path to a sound file</p>\n",
2849                    "type": "String"
2850                },
2851                {
2852                    "name": "callback",
2853                    "description": "<p>function to call when loading succeeds</p>\n",
2854                    "type": "Function",
2855                    "optional": true
2856                },
2857                {
2858                    "name": "errorCallback",
2859                    "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",
2860                    "type": "Function",
2861                    "optional": true
2862                }
2863            ],
2864            "example": [
2865                "\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'\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>"
2866            ]
2867        },
2868        "p5.Phrase": {
2869            "name": "p5.Phrase",
2870            "shortname": "p5.Phrase",
2871            "classitems": [],
2872            "plugins": [],
2873            "extensions": [],
2874            "plugin_for": [],
2875            "extension_for": [],
2876            "module": "p5.sound",
2877            "submodule": "p5.sound",
2878            "namespace": "",
2879            "file": "lib/addons/p5.sound.js",
2880            "line": 10057,
2881            "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>",
2882            "is_constructor": 1,
2883            "params": [
2884                {
2885                    "name": "name",
2886                    "description": "<p>Name so that you can access the Phrase.</p>\n",
2887                    "type": "String"
2888                },
2889                {
2890                    "name": "callback",
2891                    "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",
2892                    "type": "Function"
2893                },
2894                {
2895                    "name": "sequence",
2896                    "description": "<p>Array of values to pass into the callback\n                          at each step of the phrase.</p>\n",
2897                    "type": "Array"
2898                }
2899            ],
2900            "example": [
2901                "\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);
2901\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>"
2902            ]
2903        },
2904        "p5.Part": {
2905            "name": "p5.Part",
2906            "shortname": "p5.Part",
2907            "classitems": [],
2908            "plugins": [],
2909            "extensions": [],
2910            "plugin_for": [],
2911            "extension_for": [],
2912            "module": "p5.sound",
2913            "submodule": "p5.sound",
2914            "namespace": "",
2915            "file": "lib/addons/p5.sound.js",
2916            "line": 10142,
2917            "description": "<p>A p5.Part plays back one or more p5.Phrases. Instantiate a part\nwith steps and tatums. By default, each step represents 1/16th note.</p>\n\n<p>See p5.Phrase for more about musical timing.</p>",
2918            "is_constructor": 1,
2919            "params": [
2920                {
2921                    "name": "steps",
2922                    "description": "<p>Steps in the part</p>\n",
2923                    "type": "Number",
2924                    "optional": true
2925                },
2926                {
2927                    "name": "tatums",
2928                    "description": "<p>Divisions of a beat (default is 1/16, a quarter note)</p>\n",
2929                    "type": "Number",
2930                    "optional": true
2931                }
2932            ],
2933            "example": [
2934                "\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>"
2935            ]
2936        },
2937        "p5.Score": {
2938            "name": "p5.Score",
2939            "shortname": "p5.Score",
2940            "classitems": [],
2941            "plugins": [],
2942            "extensions": [],
2943            "plugin_for": [],
2944            "extension_for": [],
2945            "module": "p5.sound",
2946            "submodule": "p5.sound",
2947            "namespace": "",
2948            "file": "lib/addons/p5.sound.js",
2949            "line": 10396,
2950            "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",
2951            "is_constructor": 1,
2952            "params": [
2953                {
2954                    "name": "parts",
2955                    "description": "<p>One or multiple parts, to be played in sequence.</p>\n",
2956                    "type": "p5.Part",
2957                    "optional": true,
2958                    "multiple": true
2959                }
2960            ]
2961        },
2962        "p5.SoundLoop": {
2963            "name": "p5.SoundLoop",
2964            "shortname": "p5.SoundLoop",
2965            "classitems": [],
2966            "plugins": [],
2967            "extensions": [],
2968            "plugin_for": [],
2969            "extension_for": [],
2970            "module": "p5.sound",
2971            "submodule": "p5.sound",
2972            "namespace": "",
2973            "file": "lib/addons/p5.sound.js",
2974            "line": 10527,
2975            "description": "<p>SoundLoop</p>\n",
2976            "is_constructor": 1,
2977            "params": [
2978                {
2979                    "name": "callback",
2980                    "description": "<p>this function will be called on each iteration of theloop</p>\n",
2981                    "type": "Function"
2982                },
2983                {
2984                    "name": "interval",
2985                    "description": "<p>amount of time or beats for each iteration of the loop\n                                      defaults to 1</p>\n",
2986                    "type": "Number|String",
2987                    "optional": true
2988                }
2989            ],
2990            "example": [
2991                "\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>"
2992            ]
2993        },
2994        "p5.Compressor": {
2995            "name": "p5.Compressor",
2996            "shortname": "p5.Compressor",
2997            "classitems": [],
2998            "plugins": [],
2999            "extensions": [],
3000            "plugin_for": [],
3001            "extension_for": [],
3002            "module": "p5.sound",
3003            "submodule": "p5.sound",
3004            "namespace": "",
3005            "file": "lib/addons/p5.sound.js",
3006            "line": 10786,
3007            "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>.\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",
3008            "is_constructor": 1,
3009            "extends": "p5.Effect"
3010        },
3011        "p5.SoundRecorder": {
3012            "name": "p5.SoundRecorder",
3013            "shortname": "p5.SoundRecorder",
3014            "classitems": [],
3015            "plugins": [],
3016            "extensions": [],
3017            "plugin_for": [],
3018            "extension_for": [],
3019            "module": "p5.sound",
3020            "submodule": "p5.sound",
3021            "namespace": "",
3022            "file": "lib/addons/p5.sound.js",
3023            "line": 10994,
3024            "description": "<p>
3024Record 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>",
3025            "is_constructor": 1,
3026            "example": [
3027                "\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>"
3028            ]
3029        },
3030        "p5.PeakDetect": {
3031            "name": "p5.PeakDetect",
3032            "shortname": "p5.PeakDetect",
3033            "classitems": [],
3034            "plugins": [],
3035            "extensions": [],
3036            "plugin_for": [],
3037            "extension_for": [],
3038            "module": "p5.sound",
3039            "submodule": "p5.sound",
3040            "namespace": "",
3041            "file": "lib/addons/p5.sound.js",
3042            "line": 11283,
3043            "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>",
3044            "is_constructor": 1,
3045            "params": [
3046                {
3047                    "name": "freq1",
3048                    "description": "<p>lowFrequency - defaults to 20Hz</p>\n",
3049                    "type": "Number",
3050                    "optional": true
3051                },
3052                {
3053                    "name": "freq2",
3054                    "description": "<p>highFrequency - defaults to 20000 Hz</p>\n",
3055                    "type": "Number",
3056                    "optional": true
3057                },
3058                {
3059                    "name": "threshold",
3060                    "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.
3060</p>\n",
3061                    "type": "Number",
3062                    "optional": true
3063                },
3064                {
3065                    "name": "framesPerPeak",
3066                    "description": "<p>Defaults to 20.</p>\n",
3067                    "type": "Number",
3068                    "optional": true
3069                }
3070            ],
3071            "example": [
3072                "\n<div><code>\n\nvar cnv, soundFile, fft, peakDetect;\nvar ellipseWidth = 10;\n\nfunction setup() {\n  background(0);\n  noStroke();\n  fill(255);\n  textAlign(CENTER);\n\n  soundFile = loadSound('assets/beat.mp3');\n\n  // p5.PeakDetect requires a p5.FFT\n  fft = new p5.FFT();\n  peakDetect = new p5.PeakDetect();\n\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>"
3073            ]
3074        },
3075        "p5.Gain": {
3076            "name": "p5.Gain",
3077            "shortname": "p5.Gain",
3078            "classitems": [],
3079            "plugins": [],
3080            "extensions": [],
3081            "plugin_for": [],
3082            "extension_for": [],
3083            "module": "p5.sound",
3084            "submodule": "p5.sound",
3085            "namespace": "",
3086            "file": "lib/addons/p5.sound.js",
3087            "line": 11503,
3088            "description": "<p>A gain node is usefull to set the relative volume of sound.\nIt&#39;s typically used to build mixers.</p>\n",
3089            "is_constructor": 1,
3090            "example": [
3091                "\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('../_files/Damscray_01');\n sound2 = loadSound('../_files/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"
3092            ]
3093        },
3094        "p5.AudioVoice": {
3095            "name": "p5.AudioVoice",
3096            "shortname": "p5.AudioVoice",
3097            "classitems": [],
3098            "plugins": [],
3099            "extensions": [],
3100            "plugin_for": [],
3101            "extension_for": [],
3102            "module": "p5.sound",
3103            "submodule": "p5.sound",
3104            "namespace": "",
3105            "file": "lib/addons/p5.sound.js",
3106            "line": 11638,
3107            "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",
3108            "is_constructor": 1
3109        },
3110        "p5.MonoSynth": {
3111            "name": "p5.MonoSynth",
3112            "shortname": "p5.MonoSynth",
3113            "classitems": [],
3114            "plugins": [],
3115            "extensions": [],
3116            "plugin_for": [],
3117            "extension_for": [],
3118            "module": "p5.sound",
3119            "submodule": "p5.sound",
3120            "namespace": "",
3121            "file": "lib/addons/p5.sound.js",
3122            "line": 11711,
3123            "description": "<p>An MonoSynth is used as a single voice for sound synthesis.\nThis is a class to be used in conjonction with the PolySynth\nclass. Custom synthetisers should be built inheriting from\nthis class.</p>\n",
3124            "is_constructor": 1,
3125            "example": [
3126                "\n<div><code>\nvar monosynth;\nvar x;\n\nfunction setup() {\n  monosynth = new p5.MonoSynth();\n  monosynth.loadPreset('simpleBass');\n  monosynth.play(45,1,x=0,1);\n  monosynth.play(49,1,x+=1,0.25);\n  monosynth.play(50,1,x+=0.25,0.25);\n  monosynth.play(49,1,x+=0.5,0.25);\n  monosynth.play(50,1,x+=0.25,0.25);\n}\n</code></div>"
3127            ]
3128        },
3129        "p5.PolySynth": {
3130            "name": "p5.PolySynth",
3131            "shortname": "p5.PolySynth",
3132            "classitems": [],
3133            "plugins": [],
3134            "extensions": [],
3135            "plugin_for": [],
3136            "extension_for": [],
3137            "module": "p5.sound",
3138            "submodule": "p5.sound",
3139            "namespace": "",
3140            "file": "lib/addons/p5.sound.js",
3141            "line": 11943,
3142            "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",
3143            "is_constructor": 1,
3144            "params": [
3145                {
3146                    "name": "synthVoice",
3147                    "description": "<p>A monophonic synth voice inheriting\n                               the AudioVoice class. Defaults to p5.MonoSynth</p>\n",
3148                    "type": "Number",
3149                    "optional": true
3150                },
3151                {
3152                    "name": "polyValue",
3153                    "description": "<p>Number of voices, defaults to 8;</p>\n",
3154                    "type": "Number",
3155                    "optional": true
3156                }
3157            ],
3158            "example": [
3159                "\n<div><code>\nvar polysynth;\nfunction setup() {\n  polysynth = new p5.PolySynth();\n  polysynth.play(53,1,0,3);\n  polysynth.play(60,1,0,2.9);\n  polysynth.play(69,1,0,3);\n  polysynth.play(71,1,0,3);\n  polysynth.play(74,1,0,3);\n}\n</code></div>\n"
3160            ]
3161        },
3162        "p5.Distortion": {
3163            "name": "p5.Distortion",
3164            "shortname": "p5.Distortion",
3165            "classitems": [],
3166            "plugins": [],
3167            "extensions": [],
3168            "plugin_for": [],
3169            "extension_for": [],
3170            "module": "p5.sound",
3171            "submodule": "p5.sound",
3172            "namespace": "",
3173            "file": "lib/addons/p5.sound.js",
3174            "line": 12243,
3175            "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>.\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",
3176            "extends": "p5.Effect",
3177            "is_constructor": 1,
3178            "params": [
3179                {
3180                    "name": "amount",
3181                    "description": "<p>Unbounded distortion amount.\n                               Normal values range from 0-1.</p>\n",
3182                    "type": "Number",
3183                    "optional": true,
3184                    "optdefault": "0.25"
3185                },
3186                {
3187                    "name": "oversample",
3188                    "description": "<p>&#39;none&#39;, &#39;2x&#39;, or &#39;4x&#39;.</p>\n",
3189                    "type": "String",
3190                    "optional": true,
3191                    "optdefault": "'none'"
3192                }
3193            ]
3194        }
3195    },
3196    "elements": {},
3197    "classitems": [
3198        {
3199            "file": "src/color/color_conversion.js",
3200            "line": 10,
3201            "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); all other components\nare in the range [0,1]. &#39;Brightness&#39; and &#39;value&#39; are used interchangeably.</p>\n",
3202            "class": "p5",
3203            "module": "Conversion",
3204            "submodule": "Color Conversion"
3205        },
3206        {
3207            "file": "src/color/color_conversion.js",
3208            "line": 20,
3209            "description": "<p>Convert an HSBA array to HSLA.</p>\n",
3210            "class": "p5",
3211            "module": "Conversion",
3212            "submodule": "Color Conversion"
3213        },
3214        {
3215            "file": "src/color/color_conversion.js",
3216            "line": 46,
3217            "description": "<p>Convert an HSBA array to RGBA.</p>\n",
3218            "class": "p5",
3219            "module": "Conversion",
3220            "submodule": "Color Conversion"
3221        },
3222        {
3223            "file": "src/color/color_conversion.js",
3224            "line": 101,
3225            "description": "<p>Convert an HSLA array to HSBA.</p>\n",
3226            "class": "p5",
3227            "module": "Conversion",
3228            "submodule": "Color Conversion"
3229        },
3230        {
3231            "file": "src/color/color_conversion.js",
3232            "line": 124,
3233            "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",
3234            "class": "p5",
3235            "module": "Conversion",
3236            "submodule": "Color Conversion"
3237        },
3238        {
3239            "file": "src/color/color_conversion.js",
3240            "line": 188,
3241            "description": "<p>Convert an RGBA array to HSBA.</p>\n",
3242            "class": "p5",
3243            "module": "Conversion",
3244            "submodule": "Color Conversion"
3245        },
3246        {
3247            "file": "src/color/color_conversion.js",
3248            "line": 227,
3249            "description": "<p>Convert an RGBA array to HSLA.</p>\n",
3250            "class": "p5",
3251            "module": "Conversion",
3252            "submodule": "Color Conversion"
3253        },
3254        {
3255            "file": "src/color/creating_reading.js",
3256            "line": 16,
3257            "description": "<p>Extracts the alpha value from a color or pixel array.</p>\n",
3258            "itemtype": "method",
3259            "name": "alpha",
3260            "params": [
3261                {
3262                    "name": "color",
3263                    "description": "<p>p5.Color object, color components,\n                                        or CSS color</p>\n",
3264                    "type": "p5.Color|Number[]|String"
3265                }
3266            ],
3267            "return": {
3268                "description": "the alpha value",
3269                "type": "Number"
3270            },
3271            "example": [
3272                "\n<div>\n<code>\nnoStroke();\nvar c = color(0, 126, 255, 102);\nfill(c);\nrect(15, 15, 35, 70);\nvar value = alpha(c); // Sets 'value' to 102\nfill(value);\nrect(50, 15, 35, 70);\n</code>\n</div>"
3273            ],
3274            "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.",
3275            "class": "p5",
3276            "module": "Color",
3277            "submodule": "Creating & Reading"
3278        },
3279        {
3280            "file": "src/color/creating_reading.js",
3281            "line": 61,
3282            "description": "<p>Extracts the blue value from a color or pixel array.</p>\n",
3283            "itemtype": "method",
3284            "name": "blue",
3285            "params": [
3286                {
3287                    "name": "color",
3288                    "description": "<p>p5.Color object, color components,\n                                        or CSS color</p>\n",
3289                    "type": "p5.Color|Number[]|String"
3290                }
3291            ],
3292            "return": {
3293                "description": "the blue value",
3294                "type": "Number"
3295            },
3296            "example": [
3297                "\n<div>\n<code>\nvar 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\nvar 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>"
3298            ],
3299            "alt": "Left half of canvas light purple and right half a royal blue.",
3300            "class": "p5",
3301            "module": "Color",
3302            "submodule": "Creating & Reading"
3303        },
3304        {
3305            "file": "src/color/creating_reading.js",
3306            "line": 91,
3307            "description": "<p>Extracts the HSB brightness value from a color or pixel array.</p>\n",
3308            "itemtype": "method",
3309            "name": "brightness",
3310            "params": [
3311                {
3312                    "name": "color",
3313                    "description": "<p>p5.Color object, color components,\n                                        or CSS color</p>\n",
3314                    "type": "p5.Color|Number[]|String"
3315                }
3316            ],
3317            "return": {
3318                "description": "the brightness value",
3319                "type": "Number"
3320            },
3321            "example": [
3322                "\n<div>\n<code>\nnoStroke();\ncolorMode(HSB, 255);\nvar c = color(0, 126, 255);\nfill(c);\nrect(15, 20, 35, 60);\nvar value = brightness(c); // Sets 'value' to 255\nfill(value);\nrect(50, 20, 35, 60);\n</code>\n</div>"
3323            ],
3324            "alt": "Left half of canvas salmon pink and the right half white.",
3325            "class": "p5",
3326            "module": "Color",
3327            "submodule": "Creating & Reading"
3328        },
3329        {
3330            "file": "src/color/creating_reading.js",
3331            "line": 121,
3332            "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 colorMode(). 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 color(), 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>
3332\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",
3333            "itemtype": "method",
3334            "name": "color",
3335            "return": {
3336                "description": "resulting color",
3337                "type": "p5.Color"
3338            },
3339            "example": [
3340                "\n<div>\n<code>\nvar 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>\nvar 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,\nvar 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\nvar 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)\nvar 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\nvar 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\nvar 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>\nvar 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>"
3341            ],
3342            "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.",
3343            "class": "p5",
3344            "module": "Color",
3345            "submodule": "Creating & Reading",
3346            "overloads": [
3347                {
3348                    "line": 121,
3349                    "params": [
3350                        {
3351                            "name": "gray",
3352                            "description": "<p>number specifying value between white\n                                and black.</p>\n",
3353                            "type": "Number"
3354                        },
3355                        {
3356                            "name": "alpha",
3357                            "description": "<p>alpha value relative to current color range\n                                (default is 0-255)</p>\n",
3358                            "type": "Number",
3359                            "optional": true
3360                        }
3361                    ],
3362                    "return": {
3363                        "description": "resulting color",
3364                        "type": "p5.Color"
3365                    }
3366                },
3367                {
3368                    "line": 280,
3369                    "params": [
3370                        {
3371                            "name": "v1",
3372                            "description": "<p>red or hue value relative to\n                                the current color range</p>\n",
3373                            "type": "Number"
3374                        },
3375                        {
3376                            "name": "v2",
3377                            "description": "<p>
3377green or saturation value\n                                relative to the current color range</p>\n",
3378                            "type": "Number"
3379                        },
3380                        {
3381                            "name": "v3",
3382                            "description": "<p>blue or brightness value\n                                relative to the current color range</p>\n",
3383                            "type": "Number"
3384                        },
3385                        {
3386                            "name": "alpha",
3387                            "description": "",
3388                            "type": "Number",
3389                            "optional": true
3390                        }
3391                    ],
3392                    "return": {
3393                        "description": "",
3394                        "type": "p5.Color"
3395                    }
3396                },
3397                {
3398                    "line": 292,
3399                    "params": [
3400                        {
3401                            "name": "value",
3402                            "description": "<p>a color string</p>\n",
3403                            "type": "String"
3404                        }
3405                    ],
3406                    "return": {
3407                        "description": "",
3408                        "type": "p5.Color"
3409                    }
3410                },
3411                {
3412                    "line": 297,
3413                    "params": [
3414                        {
3415                            "name": "values",
3416                            "description": "<p>an array containing the red,green,blue &amp;\n                                and alpha components of the color</p>\n",
3417                            "type": "Number[]"
3418                        }
3419                    ],
3420                    "return": {
3421                        "description": "",
3422                        "type": "p5.Color"
3423                    }
3424                },
3425                {
3426                    "line": 303,
3427                    "params": [
3428                        {
3429                            "name": "color",
3430                            "description": "",
3431                            "type": "p5.Color"
3432                        }
3433                    ],
3434                    "return": {
3435                        "description": "",
3436                        "type": "p5.Color"
3437                    }
3438                }
3439            ]
3440        },
3441        {
3442            "file": "src/color/creating_reading.js",
3443            "line": 319,
3444            "description": "<p>Extracts the green value from a color or pixel array.</p>\n",
3445            "itemtype": "method",
3446            "name": "green",
3447            "params": [
3448                {
3449                    "name": "color",
3450                    "description": "<p>p5.Color object, color components,\n                                        or CSS color</p>\n",
3451                    "type": "p5.Color|Number[]|String"
3452                }
3453            ],
3454            "return": {
3455                "description": "the green value",
3456                "type": "Number"
3457            },
3458            "example": [
3459                "\n<div>\n<code>\nvar 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\nvar 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>"
3460            ],
3461            "alt": "blue rect on left and green on right, both with black outlines & 35x60.",
3462            "class": "p5",
3463            "module": "Color",
3464            "submodule": "Creating & Reading"
3465        },
3466        {
3467            "file": "src/color/creating_reading.js",
3468            "line": 350,
3469            "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",
3470            "itemtype": "method",
3471            "name": "hue",
3472            "params": [
3473                {
3474                    "name": "color",
3475                    "description": "<p>p5.Color object, color components,\n                                        or CSS color</p>\n",
3476                    "type": "p5.Color|Number[]|String"
3477                }
3478            ],
3479            "return": {
3480                "description": "the hue",
3481                "type": "Number"
3482            },
3483            "example": [
3484                "\n<div>\n<code>\nnoStroke();\ncolorMode(HSB, 255);\nvar c = color(0, 126, 255);\nfill(c);\nrect(15, 20, 35, 60);\nvar value = hue(c); // Sets 'value' to \"0\"\nfill(value);\nrect(50, 20, 35, 60);\n</code>\n</div>"
3485            ],
3486            "alt": "salmon pink rect on left and black on right, both 35x60.",
3487            "class": "p5",
3488            "module": "Color",
3489            "submodule": "Creating & Reading"
3490        },
3491        {
3492            "file": "src/color/creating_reading.js",
3493            "line": 387,
3494            "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 lerp(),\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",
3495            "itemtype": "method",
3496            "name": "lerpColor",
3497            "params": [
3498                {
3499                    "name": "c1",
3500                    "description": "<p>interpolate from this color</p>\n",
3501                    "type": "p5.Color"
3502                },
3503                {
3504                    "name": "c2",
3505                    "description": "<p>interpolate to this color</p>\n",
3506                    "type": "p5.Color"
3507                },
3508                {
3509                    "name": "amt",
3510                    "description": "<p>number between 0 and 1</p>\n",
3511                    "type": "Number"
3512                }
3513            ],
3514            "return": {
3515                "description": "interpolated color",
3516                "type": "p5.Color"
3517            },
3518            "example": [
3519                "\n<div>\n<code>\ncolorMode(RGB);
3519\nstroke(255);\nbackground(51);\nvar from = color(218, 165, 32);\nvar to = color(72, 61, 139);\ncolorMode(RGB); // Try changing to HSB.\nvar interA = lerpColor(from, to, 0.33);\nvar 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>"
3520            ],
3521            "alt": "4 rects one tan, brown, brownish purple, purple, with white outlines & 20x60",
3522            "class": "p5",
3523            "module": "Color",
3524            "submodule": "Creating & Reading"
3525        },
3526        {
3527            "file": "src/color/creating_reading.js",
3528            "line": 484,
3529            "description": "<p>Extracts the HSL lightness value from a color or pixel array.</p>\n",
3530            "itemtype": "method",
3531            "name": "lightness",
3532            "params": [
3533                {
3534                    "name": "color",
3535                    "description": "<p>p5.Color object, color components,\n                                        or CSS color</p>\n",
3536                    "type": "p5.Color|Number[]|String"
3537                }
3538            ],
3539            "return": {
3540                "description": "the lightness",
3541                "type": "Number"
3542            },
3543            "example": [
3544                "\n<div>\n<code>\nnoStroke();\ncolorMode(HSL);\nvar c = color(156, 100, 50, 1);\nfill(c);\nrect(15, 20, 35, 60);\nvar value = lightness(c); // Sets 'value' to 50\nfill(value);\nrect(50, 20, 35, 60);\n</code>\n</div>"
3545            ],
3546            "alt": "light pastel green rect on left and dark grey rect on right, both 35x60.",
3547            "class": "p5",
3548            "module": "Color",
3549            "submodule": "Creating & Reading"
3550        },
3551        {
3552            "file": "src/color/creating_reading.js",
3553            "line": 514,
3554            "description": "<p>Extracts the red value from a color or pixel array.</p>\n",
3555            "itemtype": "method",
3556            "name": "red",
3557            "params": [
3558                {
3559                    "name": "color",
3560                    "description": "<p>p5.Color object, color components,\n                                        or CSS color</p>\n",
3561                    "type": "p5.Color|Number[]|String"
3562                }
3563            ],
3564            "return": {
3565                "description": "the red value",
3566                "type": "Number"
3567            },
3568            "example": [
3569                "\n<div>\n<code>\nvar 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\nvar 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);\nvar c = color(127, 255, 0);\ncolorMode(RGB, 1);\nvar myColor = red(c);\nprint(myColor);\n</code>\n</div>"
3570            ],
3571            "alt": "yellow rect on left and red rect on right, both with black outlines and 35x60.\ngrey canvas",
3572            "class": "p5",
3573            "module": "Color",
3574            "submodule": "Creating & Reading"
3575        },
3576        {
3577            "file": "src/color/creating_reading.js",
3578            "line": 554,
3579            "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",
3580            "itemtype": "method",
3581            "name": "saturation",
3582            "params": [
3583                {
3584                    "name": "color",
3585                    "description": "<p>p5.Color object, color components,\n                                        or CSS color</p>\n",
3586                    "type": "p5.Color|Number[]|String"
3587                }
3588            ],
3589            "return": {
3590                "description": "the saturation value",
3591                "type": "Number"
3592            },
3593            "example": [
3594                "\n<div>\n<code>\nnoStroke();\ncolorMode(HSB, 255);\nvar c = color(0, 126, 255);\nfill(c);\nrect(15, 20, 35, 60);\nvar value = saturation(c); // Sets 'value' to 126\nfill(value);\nrect(50, 20, 35, 60);\n</code>\n</div>"
3595            ],
3596            "alt": "deep pink rect on left and grey rect on right, both 35x60.",
3597            "class": "p5",
3598            "module": "Color",
3599            "submodule": "Creating & Reading"
3600        },
3601        {
3602            "file": "src/color/p5.Color.js",
3603            "line": 52,
3604            "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",
3605            "itemtype": "method",
3606            "name": "toString",
3607            "params": [
3608                {
3609                    "name": "format",
3610                    "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",
3611                    "type": "String",
3612                    "optional": true
3613                }
3614            ],
3615            "return": {
3616                "description": "the formatted string",
3617                "type": "String"
3618            },
3619            "example": [
3620                "\n<div>\n<code>\nvar myColor;\nfunction setup() {\n  createCanvas(200, 200);
3620\n  stroke(255);\n  myColor = color(100, 100, 250);\n  fill(myColor);\n}\n\nfunction draw() {\n  text(myColor.toString(), 10, 10);\n  text(myColor.toString('#rrggbb'), 10, 95);\n  text(myColor.toString('rgba%'), 10, 180);\n}\n</code>\n</div>"
3621            ],
3622            "alt": "canvas with text representation of color",
3623            "class": "p5.Color",
3624            "module": "Color",
3625            "submodule": "Creating & Reading"
3626        },
3627        {
3628            "file": "src/color/p5.Color.js",
3629            "line": 247,
3630            "itemtype": "method",
3631            "name": "setRed",
3632            "params": [
3633                {
3634                    "name": "red",
3635                    "description": "<p>the new red value</p>\n",
3636                    "type": "Number"
3637                }
3638            ],
3639            "example": [
3640                "\n<div>\n<code>\nvar 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>"
3641            ],
3642            "alt": "canvas with gradually changing background color",
3643            "class": "p5.Color",
3644            "module": "Color",
3645            "submodule": "Creating & Reading"
3646        },
3647        {
3648            "file": "src/color/p5.Color.js",
3649            "line": 274,
3650            "itemtype": "method",
3651            "name": "setGreen",
3652            "params": [
3653                {
3654                    "name": "green",
3655                    "description": "<p>the new green value</p>\n",
3656                    "type": "Number"
3657                }
3658            ],
3659            "example": [
3660                "\n<div>\n<code>\nvar 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>"
3661            ],
3662            "alt": "canvas with gradually changing background color",
3663            "class": "p5.Color",
3664            "module": "Color",
3665            "submodule": "Creating & Reading"
3666        },
3667        {
3668            "file": "src/color/p5.Color.js",
3669            "line": 301,
3670            "itemtype": "method",
3671            "name": "setBlue",
3672            "params": [
3673                {
3674                    "name": "blue",
3675                    "description": "<p>the new blue value</p>\n",
3676                    "type": "Number"
3677                }
3678            ],
3679            "example": [
3680                "\n<div>\n<code>\nvar 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>"
3681            ],
3682            "alt": "canvas with gradually changing background color",
3683            "class": "p5.Color",
3684            "module": "Color",
3685            "submodule": "Creating & Reading"
3686        },
3687        {
3688            "file": "src/color/p5.Color.js",
3689            "line": 328,
3690            "itemtype": "method",
3691            "name": "setAlpha",
3692            "params": [
3693                {
3694                    "name": "alpha",
3695                    "description": "<p>the new alpha value</p>\n",
3696                    "type": "Number"
3697                }
3698            ],
3699            "example": [
3700                "\n<div>\n<code>\nvar 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>"
3701            ],
3702            "alt": "circle behind a square with gradually changing opacity",
3703            "class": "p5.Color",
3704            "module": "Color",
3705            "submodule": "Creating & Reading"
3706        },
3707        {
3708            "file": "src/color/p5.Color.js",
3709            "line": 406,
3710            "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",
3711            "class": "p5.Color",
3712            "module": "Color",
3713            "submodule": "Creating & Reading"
3714        },
3715        {
3716            "file": "src/color/p5.Color.js",
3717            "line": 437,
3718            "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",
3719            "class": "p5.Color",
3720            "module": "Color",
3721            "submodule": "Creating & Reading"
3722        },
3723        {
3724            "file": "src/color/p5.Color.js",
3725            "line": 456,
3726            "description": "<p>CSS named colors.</p>\n",
3727            "class": "p5.Color",
3728            "module": "Color",
3729            "submodule": "Creating & Reading"
3730        },
3731        {
3732            "file": "src/color/p5.Color.js",
3733            "line": 609,
3734            "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",
3735            "class": "p5.Color",
3736            "module": "Color",
3737            "submodule": "Creating & Reading"
3738        },
3739        {
3740            "file": "src/color/p5.Color.js",
3741            "line": 622,
3742            "description": "<p>Full color string patterns. The capture groups are necessary.</p>\n",
3743            "class": "p5.Color",
3744            "module": "Color",
3745            "submodule": "Creating & Reading"
3746        },
3747        {
3748            "file": "src/color/p5.Color.js",
3749            "line": 976,
3750            "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",
3751            "class": "p5.Color",
3752            "module": "Color",
3753            "submodule": "Creating & Reading"
3754        },
3755        {
3756            "file": "src/color/setting.js",
3757            "line": 15,
3758            "description": "<p>The background() function sets the color used for the background of the\np5.js canvas. The default background is light gray. This function is\ntypically used within draw() to clear the display window at the beginning\nof each frame, but it can be used inside setup() 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 colorMode. (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>
3758\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.Color object can also be provided to set the background color.\n<br><br>\nA p5.Image can also be provided to set the background image.</p>\n",
3759            "itemtype": "method",
3760            "name": "background",
3761            "chainable": 1,
3762            "example": [
3763                "\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>"
3764            ],
3765            "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.",
3766            "class": "p5",
3767            "module": "Color",
3768            "submodule": "Setting",
3769            "overloads": [
3770                {
3771                    "line": 15,
3772                    "params": [
3773                        {
3774                            "name": "color",
3775                            "description": "<p>any value created by the color() function</p>\n",
3776                            "type": "p5.Color"
3777                        }
3778                    ],
3779                    "chainable": 1
3780                },
3781                {
3782                    "line": 131,
3783                    "params": [
3784                        {
3785                            "name": "colorstring",
3786                            "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",
3787                            "type": "String"
3788                        },
3789                        {
3790                            "name": "a",
3791                            "description": "<p>opacity of the background relative to current\n                            color range (default is 0-255)</p>\n",
3792                            "type": "Number",
3793                            "optional": true
3794                        }
3795                    ],
3796                    "chainable": 1
3797                },
3798                {
3799                    "line": 141,
3800                    "params": [
3801                        {
3802                            "name": "gray",
3803                            "description": "<p>specifies a value between white and black</p>\n",
3804                            "type": "Number"
3805                        },
3806                        {
3807                            "name": "a",
3808                            "description": "",
3809                            "type": "Number",
3810                            "optional": true
3811                        }
3812                    ],
3813                    "chainable": 1
3814                },
3815                {
3816                    "line": 148,
3817                    "params": [
3818                        {
3819                            "name": "v1",
3820                            "description": "<p>red or hue value (depending on the current color\n                       mode)</p>\n",
3821                            "type": "Number"
3822                        },
3823                        {
3824                            "name": "v2",
3825                            "description": "<p>green or saturation value (depending on the current\n                       color mode)</p>\n",
3826                            "type": "Number"
3827                        },
3828                        {
3829                            "name": "v3",
3830                            "description": "<p>blue or brightness value (depending on the current\n                       color mode)</p>\n",
3831                            "type": "Number"
3832                        },
3833                        {
3834                            "name": "a",
3835                            "description": "",
3836                            "type": "Number",
3837                            "optional": true
3838                        }
3839                    ],
3840                    "chainable": 1
3841                },
3842                {
3843                    "line": 160,
3844                    "params": [
3845                        {
3846                            "name": "values",
3847                            "description": "<p>an array containing the red,green,blue &amp;\n                                and alpha components of the color</p>\n",
3848                            "type": "Number[]"
3849                        }
3850                    ],
3851                    "chainable": 1
3852                },
3853                {
3854                    "line": 167,
3855                    "params": [
3856                        {
3857                            "name": "image",
3858                            "description": "<p>image created with loadImage() or createImage(),\n                            to set as background\n                            (must be same size as the sketch window)</p>\n",
3859                            "type": "p5.Image"
3860                        },
3861                        {
3862                            "name": "a",
3863                            "description": "",
3864                            "type": "Number",
3865                            "optional": true
3866                        }
3867                    ],
3868                    "chainable": 1
3869                }
3870            ]
3871        },
3872        {
3873            "file": "src/color/setting.js",
3874            "line": 185,
3875            "description": "<p>Clears the pixels within a buffer. This function only works on p5.Canvas\nobjects created with the createCanvas() function; it won&#39;t work with the\nmain display window. Unlike the main graphics context, pixels in\nadditional graphics areas created with createGraphics() can be entirely\nor partially transparent. This function clears everything to make all of\nthe pixels 100% transparent.</p>\n",
3876            "itemtype": "method",
3877            "name": "clear",
3878            "chainable": 1,
3879            "example": [
3880                "\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>"
3881            ],
3882            "alt": "20x20 white ellipses are continually drawn at mouse x and y coordinates.",
3883            "class": "p5",
3884            "module": "Color",
3885            "submodule": "Setting"
3886        },
3887        {
3888            "file": "src/color/setting.js",
3889            "line": 223,
3890            "description": "<p>colorMode() changes the way p5.js interprets color data. By default, the\nparameters for fill(), stroke(), background(), and color() 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",
3891            "itemtype": "method",
3892            "name": "colorMode",
3893            "chainable": 1,
3894            "example": [
3895                "\n<div>\n<code>\nnoStroke();\ncolorMode(RGB, 100);\nfor (var i = 0; i < 100; i++) {\n  for (var 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 (var i = 0; i < 100; i++) {\n  for (var 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);\nvar c = color(127, 255, 0);\n\ncolorMode(RGB, 1);\nvar 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>"
3896            ],
3897            "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.",
3898            "class": "p5",
3899            "module": "Color",
3900            "submodule": "Setting",
3901            "overloads": [
3902                {
3903                    "line": 223,
3904                    "params": [
3905                        {
3906                            "name": "mode",
3907                            "description": "<p>either RGB, HSB or HSL, corresponding to\n                         Red/Green/Blue and Hue/Saturation/Brightness\n                         (or Lightness)</p>\n",
3908                            "type": "Constant"
3909                        },
3910                        {
3911                            "name": "max",
3912                            "description": "<p>range for all values</p>\n",
3913                            "type": "Number",
3914                            "optional": true
3915                        }
3916                    ],
3917                    "chainable": 1
3918                },
3919                {
3920                    "line": 300,
3921                    "params": [
3922                        {
3923                            "name": "mode",
3924                            "description": "",
3925                            "type": "Constant"
3926                        },
3927                        {
3928                            "name": "max1",
3929                            "description": "<p>range for the red or hue depending on the\n                             current color mode</p>\n",
3930                            "type": "Number"
3931                        },
3932                        {
3933                            "name": "max2",
3934                            "description": "<p>range for the green or saturation depending\n                             on the current color mode</p>\n",
3935                            "type": "Number"
3936                        },
3937                        {
3938                            "name": "max3",
3939                            "description": "<p>range for the blue or brightness/lighntess\n                             depending on the current color mode</p>\n",
3940                            "type": "Number"
3941                        },
3942                        {
3943                            "name": "maxA",
3944                            "description": "<p>range for the alpha</p>\n",
3945                            "type": "Number",
3946                            "optional": true
3947                        }
3948                    ],
3949                    "chainable": 1
3950                }
3951            ]
3952        },
3953        {
3954            "file": "src/color/setting.js",
3955            "line": 344,
3956            "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 colorMode(). (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>
3956\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 Color object can also be provided to set the fill color.</p>\n",
3957            "itemtype": "method",
3958            "name": "fill",
3959            "chainable": 1,
3960            "example": [
3961                "\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>"
3962            ],
3963            "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.",
3964            "class": "p5",
3965            "module": "Color",
3966            "submodule": "Setting",
3967            "overloads": [
3968                {
3969                    "line": 344,
3970                    "params": [
3971                        {
3972                            "name": "v1",
3973                            "description": "<p>red or hue value relative to\n                                the current color range</p>\n",
3974                            "type": "Number"
3975                        },
3976                        {
3977                            "name": "v2",
3978                            "description": "<p>green or saturation value\n                                relative to the current color range</p>\n",
3979                            "type": "Number"
3980                        },
3981                        {
3982                            "name": "v3",
3983                            "description": "<p>blue or brightness value\n                                relative to the current color range</p>\n",
3984                            "type": "Number"
3985                        },
3986                        {
3987                            "name": "alpha",
3988                            "description": "",
3989                            "type": "Number",
3990                            "optional": true
3991                        }
3992                    ],
3993                    "chainable": 1
3994                },
3995                {
3996                    "line": 469,
3997                    "params": [
3998                        {
3999                            "name": "value",
4000                            "description": "<p>a color string</p>\n",
4001                            "type": "String"
4002                        }
4003                    ],
4004                    "chainable": 1
4005                },
4006                {
4007                    "line": 475,
4008                    "params": [
4009                        {
4010                            "name": "gray",
4011                            "description": "<p>a gray value</p>\n",
4012                            "type": "Number"
4013                        },
4014                        {
4015                            "name": "alpha",
4016                            "description": "",
4017                            "type": "Number",
4018                            "optional": true
4019                        }
4020                    ],
4021                    "chainable": 1
4022                },
4023                {
4024                    "line": 482,
4025                    "params": [
4026                        {
4027                            "name": "values",
4028                            "description": "<p>an array containing the red,green,blue &amp;\n                                and alpha components of the color</p>\n",
4029                            "type": "Number[]"
4030                        }
4031                    ],
4032                    "chainable": 1
4033                },
4034                {
4035                    "line": 489,
4036                    "params": [
4037                        {
4038                            "name": "color",
4039                            "description": "<p>the fill color</p>\n",
4040                            "type": "p5.Color"
4041                        }
4042                    ],
4043                    "chainable": 1
4044                }
4045            ]
4046        },
4047        {
4048            "file": "src/color/setting.js",
4049            "line": 501,
4050            "description": "<p>Disables filling geometry. If both noStroke() and noFill() are called,\nnothing will be drawn to the screen.</p>\n",
4051            "itemtype": "method",
4052            "name": "noFill",
4053            "chainable": 1,
4054            "example": [
4055                "\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>"
4056            ],
4057            "alt": "white rect top middle and noFill rect center. Both 60x60 with black outlines.\nblack canvas with purple cube wireframe spinning",
4058            "class": "p5",
4059            "module": "Color",
4060            "submodule": "Setting"
4061        },
4062        {
4063            "file": "src/color/setting.js",
4064            "line": 542,
4065            "description": "<p>Disables drawing the stroke (outline). If both noStroke() and noFill()\nare c
4065alled, nothing will be drawn to the screen.</p>\n",
4066            "itemtype": "method",
4067            "name": "noStroke",
4068            "chainable": 1,
4069            "example": [
4070                "\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>"
4071            ],
4072            "alt": "60x60 white rect at center. no outline.\nblack canvas with pink cube spinning",
4073            "class": "p5",
4074            "module": "Color",
4075            "submodule": "Setting"
4076        },
4077        {
4078            "file": "src/color/setting.js",
4079            "line": 582,
4080            "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 colorMode() (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 Color object can also be provided to set the stroke color.</p>\n",
4081            "itemtype": "method",
4082            "name": "stroke",
4083            "chainable": 1,
4084            "example": [
4085                "\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>"
4086            ],
4087            "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.",
4088            "class": "p5",
4089            "module": "Color",
4090            "submodule": "Setting",
4091            "overloads": [
4092                {
4093                    "line": 582,
4094                    "params": [
4095                        {
4096                            "name": "v1",
4097                            "description": "<p>red or hue value relative to\n                                the current color range</p>\n",
4098                            "type": "Number"
4099                        },
4100                        {
4101                            "name": "v2",
4102                            "description": "<p>
4102green or saturation value\n                                relative to the current color range</p>\n",
4103                            "type": "Number"
4104                        },
4105                        {
4106                            "name": "v3",
4107                            "description": "<p>blue or brightness value\n                                relative to the current color range</p>\n",
4108                            "type": "Number"
4109                        },
4110                        {
4111                            "name": "alpha",
4112                            "description": "",
4113                            "type": "Number",
4114                            "optional": true
4115                        }
4116                    ],
4117                    "chainable": 1
4118                },
4119                {
4120                    "line": 721,
4121                    "params": [
4122                        {
4123                            "name": "value",
4124                            "description": "<p>a color string</p>\n",
4125                            "type": "String"
4126                        }
4127                    ],
4128                    "chainable": 1
4129                },
4130                {
4131                    "line": 727,
4132                    "params": [
4133                        {
4134                            "name": "gray",
4135                            "description": "<p>a gray value</p>\n",
4136                            "type": "Number"
4137                        },
4138                        {
4139                            "name": "alpha",
4140                            "description": "",
4141                            "type": "Number",
4142                            "optional": true
4143                        }
4144                    ],
4145                    "chainable": 1
4146                },
4147                {
4148                    "line": 734,
4149                    "params": [
4150                        {
4151                            "name": "values",
4152                            "description": "<p>an array containing the red,green,blue &amp;\n                                and alpha components of the color</p>\n",
4153                            "type": "Number[]"
4154                        }
4155                    ],
4156                    "chainable": 1
4157                },
4158                {
4159                    "line": 741,
4160                    "params": [
4161                        {
4162                            "name": "color",
4163                            "description": "<p>the stroke color</p>\n",
4164                            "type": "p5.Color"
4165                        }
4166                    ],
4167                    "chainable": 1
4168                }
4169            ]
4170        },
4171        {
4172            "file": "src/core/2d_primitives.js",
4173            "line": 16,
4174            "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 ellipseMode() 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 ellipse() function instead\nto create a closed ellipse, and to use the arc() function\nonly to draw parts of an ellipse.</p>\n",
4175            "itemtype": "method",
4176            "name": "arc",
4177            "params": [
4178                {
4179                    "name": "x",
4180                    "description": "<p>x-coordinate of the arc&#39;s ellipse</p>\n",
4181                    "type": "Number"
4182                },
4183                {
4184                    "name": "y",
4185                    "description": "<p>y-coordinate of the arc&#39;s ellipse</p>\n",
4186                    "type": "Number"
4187                },
4188                {
4189                    "name": "w",
4190                    "description": "<p>width of the arc&#39;s ellipse by default</p>\n",
4191                    "type": "Number"
4192                },
4193                {
4194                    "name": "h",
4195                    "description": "<p>height of the arc&#39;s ellipse by default</p>\n",
4196                    "type": "Number"
4197                },
4198                {
4199                    "name": "start",
4200                    "description": "<p>angle to start the arc, specified in radians</p>\n",
4201                    "type": "Number"
4202                },
4203                {
4204                    "name": "stop",
4205                    "description": "<p>angle to stop the arc, specified in radians</p>\n",
4206                    "type": "Number"
4207                },
4208                {
4209                    "name": "mode",
4210                    "description": "<p>optional parameter to determine the way of drawing\n                        the arc. either CHORD, PIE or OPEN</p>\n",
4211                    "type": "Constant",
4212                    "optional": true
4213                }
4214            ],
4215            "chainable": 1,
4216            "example": [
4217                "\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>"
4218            ],
4219            "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.",
4220            "class": "p5",
4221            "module": "Shape",
4222            "submodule": "2D Primitives"
4223        },
4224        {
4225            "file": "src/core/2d_primitives.js",
4226            "line": 133,
4227            "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;
4227s 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 ellipseMode() function.</p>\n",
4228            "itemtype": "method",
4229            "name": "ellipse",
4230            "chainable": 1,
4231            "example": [
4232                "\n<div>\n<code>\nellipse(56, 46, 55, 55);\n</code>\n</div>"
4233            ],
4234            "alt": "white ellipse with black outline in middle-right of canvas that is 55x55.",
4235            "class": "p5",
4236            "module": "Shape",
4237            "submodule": "2D Primitives",
4238            "overloads": [
4239                {
4240                    "line": 133,
4241                    "params": [
4242                        {
4243                            "name": "x",
4244                            "description": "<p>x-coordinate of the ellipse.</p>\n",
4245                            "type": "Number"
4246                        },
4247                        {
4248                            "name": "y",
4249                            "description": "<p>y-coordinate of the ellipse.</p>\n",
4250                            "type": "Number"
4251                        },
4252                        {
4253                            "name": "w",
4254                            "description": "<p>width of the ellipse.</p>\n",
4255                            "type": "Number"
4256                        },
4257                        {
4258                            "name": "h",
4259                            "description": "<p>height of the ellipse.</p>\n",
4260                            "type": "Number",
4261                            "optional": true
4262                        }
4263                    ],
4264                    "chainable": 1
4265                },
4266                {
4267                    "line": 158,
4268                    "params": [
4269                        {
4270                            "name": "x",
4271                            "description": "",
4272                            "type": "Number"
4273                        },
4274                        {
4275                            "name": "y",
4276                            "description": "",
4277                            "type": "Number"
4278                        },
4279                        {
4280                            "name": "w",
4281                            "description": "",
4282                            "type": "Number"
4283                        },
4284                        {
4285                            "name": "h",
4286                            "description": "",
4287                            "type": "Number"
4288                        },
4289                        {
4290                            "name": "detail",
4291                            "description": "<p>number of radial sectors to draw</p>\n",
4292                            "type": "Integer"
4293                        }
4294                    ]
4295                }
4296            ]
4297        },
4298        {
4299            "file": "src/core/2d_primitives.js",
4300            "line": 188,
4301            "description": "<p>Draws a line (a direct path between two points) to the screen. The version\nof line() with four parameters draws the line in 2D. To color a line, use\nthe stroke() function. A line cannot be filled, therefore the fill()\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\nstrokeWeight(
4301) function.</p>\n",
4302            "itemtype": "method",
4303            "name": "line",
4304            "chainable": 1,
4305            "example": [
4306                "\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>"
4307            ],
4308            "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.",
4309            "class": "p5",
4310            "module": "Shape",
4311            "submodule": "2D Primitives",
4312            "overloads": [
4313                {
4314                    "line": 188,
4315                    "params": [
4316                        {
4317                            "name": "x1",
4318                            "description": "<p>the x-coordinate of the first point</p>\n",
4319                            "type": "Number"
4320                        },
4321                        {
4322                            "name": "y1",
4323                            "description": "<p>the y-coordinate of the first point</p>\n",
4324                            "type": "Number"
4325                        },
4326                        {
4327                            "name": "x2",
4328                            "description": "<p>the x-coordinate of the second point</p>\n",
4329                            "type": "Number"
4330                        },
4331                        {
4332                            "name": "y2",
4333                            "description": "<p>the y-coordinate of the second point</p>\n",
4334                            "type": "Number"
4335                        }
4336                    ],
4337                    "chainable": 1
4338                },
4339                {
4340                    "line": 224,
4341                    "params": [
4342                        {
4343                            "name": "x1",
4344                            "description": "",
4345                            "type": "Number"
4346                        },
4347                        {
4348                            "name": "y1",
4349                            "description": "",
4350                            "type": "Number"
4351                        },
4352                        {
4353                            "name": "z1",
4354                            "description": "<p>the z-coordinate of the first point</p>\n",
4355                            "type": "Number"
4356                        },
4357                        {
4358                            "name": "x2",
4359                            "description": "",
4360                            "type": "Number"
4361                        },
4362                        {
4363                            "name": "y2",
4364                            "description": "",
4365                            "type": "Number"
4366                        },
4367                        {
4368                            "name": "z2",
4369                            "description": "<p>the z-coordinate of the second point</p>\n",
4370                            "type": "Number"
4371                        }
4372                    ],
4373                    "chainable": 1
4374                }
4375            ]
4376        },
4377        {
4378            "file": "src/core/2d_primitives.js",
4379            "line": 244,
4380            "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",
4381            "itemtype": "method",
4382            "name": "point",
4383            "params": [
4384                {
4385                    "name": "x",
4386                    "description": "<p>the x-coordinate</p>\n",
4387                    "type": "Number"
4388                },
4389                {
4390                    "name": "y",
4391                    "description": "<p>the y-coordinate</p>\n",
4392                    "type": "Number"
4393                },
4394                {
4395                    "name": "z",
4396                    "description": "<p>the z-coordinate (for WEBGL mode)</p>\n",
4397                    "type": "Number",
4398                    "optional": true
4399                }
4400            ],
4401            "chainable": 1,
4402            "example": [
4403                "\n<div>\n<code>\npoint(30, 20);\npoint(85, 20);\npoint(85, 75);\npoint(30, 75);\n</code>\n</div>"
4404            ],
4405            "alt": "4 points centered in the middle-right of the canvas.",
4406            "class": "p5",
4407            "module": "Shape",
4408            "submodule": "2D Primitives"
4409        },
4410        {
4411            "file": "src/core/2d_primitives.js",
4412            "line": 279,
4413            "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 
4413ninety 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",
4414            "itemtype": "method",
4415            "name": "quad",
4416            "chainable": 1,
4417            "example": [
4418                "\n<div>\n<code>\nquad(38, 31, 86, 20, 69, 63, 30, 76);\n</code>\n</div>"
4419            ],
4420            "alt": "irregular white quadrilateral shape with black outline mid-right of canvas.",
4421            "class": "p5",
4422            "module": "Shape",
4423            "submodule": "2D Primitives",
4424            "overloads": [
4425                {
4426                    "line": 279,
4427                    "params": [
4428                        {
4429                            "name": "x1",
4430                            "description": "<p>the x-coordinate of the first point</p>\n",
4431                            "type": "Number"
4432                        },
4433                        {
4434                            "name": "y1",
4435                            "description": "<p>the y-coordinate of the first point</p>\n",
4436                            "type": "Number"
4437                        },
4438                        {
4439                            "name": "x2",
4440                            "description": "<p>the x-coordinate of the second point</p>\n",
4441                            "type": "Number"
4442                        },
4443                        {
4444                            "name": "y2",
4445                            "description": "<p>the y-coordinate of the second point</p>\n",
4446                            "type": "Number"
4447                        },
4448                        {
4449                            "name": "x3",
4450                            "description": "<p>the x-coordinate of the third point</p>\n",
4451                            "type": "Number"
4452                        },
4453                        {
4454                            "name": "y3",
4455                            "description": "<p>the y-coordinate of the third point</p>\n",
4456                            "type": "Number"
4457                        },
4458                        {
4459                            "name": "x4",
4460                            "description": "<p>the x-coordinate of the fourth point</p>\n",
4461                            "type": "Number"
4462                        },
4463                        {
4464                            "name": "y4",
4465                            "description": "<p>the y-coordinate of the fourth point</p>\n",
4466                            "type": "Number"
4467                        }
4468                    ],
4469                    "chainable": 1
4470                },
4471                {
4472                    "line": 307,
4473                    "params": [
4474                        {
4475                            "name": "x1",
4476                            "description": "",
4477                            "type": "Number"
4478                        },
4479                        {
4480                            "name": "y1",
4481                            "description": "",
4482                            "type": "Number"
4483                        },
4484                        {
4485                            "name": "z1",
4486                            "description": "",
4487                            "type": "Number"
4488                        },
4489                        {
4490                            "name": "x2",
4491                            "description": "",
4492                            "type": "Number"
4493                        },
4494                        {
4495                            "name": "y2",
4496                            "description": "",
4497                            "type": "Number"
4498                        },
4499                        {
4500                            "name": "z2",
4501                            "description": "",
4502                            "type": "Number"
4503                        },
4504                        {
4505                            "name": "x3",
4506                            "description": "",
4507                            "type": "Number"
4508                        },
4509                        {
4510                            "name": "y3",
4511                            "description": "",
4512                            "type": "Number"
4513                        },
4514                        {
4515                            "name": "z3",
4516                            "description": "",
4517                            "type": "Number"
4518                        },
4519                        {
4520                            "name": "x4",
4521                            "description": "",
4522                            "type": "Number"
4523                        },
4524                        {
4525                            "name": "y4",
4526                            "description": "",
4527                            "type": "Number"
4528                        },
4529                        {
4530                            "name": "z4",
4531                            "description": "",
4532                            "type": "Number"
4533                        }
4534                    ],
4535                    "chainable": 1
4536                }
4537            ]
4538        },
4539        {
4540            "file": "src/core/2d_primitives.js",
4541            "line": 333,
4542            "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 rectMode() function.\n<br><br>\nThe fifth, sixth, seventh and eighth parameters, if specified,\ndetermine corner radius for the top-right, top-left, 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",
4543            "itemtype": "method",
4544            "name": "rect",
4545            "chainable": 1,
4546            "example": [
4547                "\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>"
4548            ],
4549            "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.",
4550            "class": "p5",
4551            "module": "Shape",
4552            "submodule": "2D Primitives",
4553            "overloads": [
4554                {
4555                    "line": 333,
4556                    "params": [
4557                        {
4558                            "name": "x",
4559                            "description": "<p>x-coordinate of the rectangle.</p>\n",
4560                            "type": "Number"
4561                        },
4562                        {
4563                            "name": "y",
4564                            "description": "<p>y-coordinate of the rectangle.</p>\n",
4565                            "type": "Number"
4566                        },
4567                        {
4568                            "name": "w",
4569                            "description": "<p>width of the rectangle.</p>\n",
4570                            "type": "Number"
4571                        },
4572                        {
4573                            "name": "h",
4574                            "description": "<p>height of the rectangle.</p>\n",
4575                            "type": "Number"
4576                        },
4577                        {
4578                            "name": "tl",
4579                            "description": "<p>optional radius of top-left corner.</p>\n",
4580                            "type": "Number",
4581                            "optional": true
4582                        },
4583                        {
4584                            "name": "tr",
4585                            "description": "<p>optional radius of top-right corner.</p>\n",
4586                            "type": "Number",
4587                            "optional": true
4588                        },
4589                        {
4590                            "name": "br",
4591                            "description": "<p>optional radius of bottom-right corner.</p>\n",
4592                            "type": "Number",
4593                            "optional": true
4594                        },
4595                        {
4596                            "name": "bl",
4597                            "description": "<p>optional radius of bottom-left corner.</p>\n",
4598                            "type": "Number",
4599                            "optional": true
4600                        }
4601                    ],
4602                    "chainable": 1
4603                },
4604                {
4605                    "line": 383,
4606                    "params": [
4607                        {
4608                            "name": "x",
4609                            "description": "",
4610                            "type": "Number"
4611                        },
4612                        {
4613                            "name": "y",
4614                            "description": "",
4615                            "type": "Number"
4616                        },
4617                        {
4618                            "name": "w",
4619                            "description": "",
4620                            "type": "Number"
4621                        },
4622                        {
4623                            "name": "h",
4624                            "description": "",
4625                            "type": "Number"
4626                        },
4627                        {
4628                            "name": "detailX",
4629                            "description": "<p>number of segments in the x-direction</p>\n",
4630                            "type": "Integer",
4631                            "optional": true
4632                        },
4633                        {
4634                            "name": "detailY",
4635                            "description": "<p>number of segments in the y-direction</p>\n",
4636                            "type": "Integer",
4637                            "optional": true
4638                        }
4639                    ],
4640                    "chainable": 1
4641                }
4642            ]
4643        },
4644        {
4645            "file": "src/core/2d_primitives.js",
4646            "line": 416,
4647            "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",
4648            "itemtype": "method",
4649            "name": "triangle",
4650            "params": [
4651                {
4652                    "name": "x1",
4653                    "description": "<p>x-coordinate of the first point</p>\n",
4654                    "type": "Number"
4655                },
4656                {
4657                    "name": "y1",
4658                    "description": "<p>y-coordinate of the first point</p>\n",
4659                    "type": "Number"
4660                },
4661                {
4662                    "name": "x2",
4663                    "description": "<p>x-coordinate of the second point</p>\n",
4664                    "type": "Number"
4665                },
4666                {
4667                    "name": "y2",
4668                    "description": "<p>y-coordinate of the second point</p>\n",
4669                    "type": "Number"
4670                },
4671                {
4672                    "name": "x3",
4673                    "description": "<p>x-coordinate of the third point</p>\n",
4674                    "type": "Number"
4675                },
4676                {
4677                    "name": "y3",
4678                    "description": "<p>y-coordinate of the third point</p>\n",
4679                    "type": "Number"
4680                }
4681            ],
4682            "chainable": 1,
4683            "example": [
4684                "\n<div>\n<code>\ntriangle(30, 75, 58, 20, 86, 75);\n</code>\n</div>"
4685            ],
4686            "alt": "white triangle with black outline in mid-right of canvas.",
4687            "class": "p5",
4688            "module": "Shape",
4689            "submodule": "2D Primitives"
4690        },
4691        {
4692            "file": "src/core/attributes.js",
4693            "line": 14,
4694            "description": "<p>Modifies the location from which ellipses are drawn by changing the way\nin which parameters given to ellipse() are interpreted.\n<br><br>\nThe default mode is ellipseMode(CENTER), which interprets the first two\nparameters of ellipse() 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 ellipse() as\nthe shape&#39;s center point, but uses the 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 ellipse() 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 ellipse() 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",
4695            "itemtype": "method",
4696            "name": "ellipseMode",
4697            "params": [
4698                {
4699                    "name": "mode",
4700                    "description": "<p>either CENTER, RADIUS, CORNER, or CORNERS</p>\n",
4701                    "type": "Constant"
4702                }
4703            ],
4704            "chainable": 1,
4705            "example": [
4706                "\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>"
4707            ],
4708            "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.",
4709            "class": "p5",
4710            "module": "Shape",
4711            "submodule": "Attributes"
4712        },
4713        {
4714            "file": "src/core/attributes.js",
4715            "line": 83,
4716            "description": "<p>Draws all geometry with jagged (aliased) edges. Note that smooth() is\nactive by default, so it is necessary to call noSmooth() to disable\nsmoothing of geometry, images, and fonts.</p>\n",
4717            "itemtype": "method",
4718            "name": "noSmooth",
4719            "chainable": 1,
4720            "example": [
4721                "\n<div>\n<code>\nbackground(0);\nnoStroke();\nsmooth();\nellipse(30, 48, 36, 36);\nnoSmooth();\nellipse(70, 48, 36, 36);\n</code>\n</div>"
4722            ],
4723            "alt": "2 pixelated 36x36 white ellipses to left & right of center, black background",
4724            "class": "p5",
4725            "module": "Shape",
4726            "submodule": "Attributes"
4727        },
4728        {
4729            "file": "src/core/attributes.js",
4730            "line": 111,
4731            "description": "<p>Modifies the location from which rectangles are drawn by changing the way\nin which parameters given to rect() are interpreted.\n<br><br>\nThe default mode is rectMode(CORNER), which interprets the first two\nparameters of rect() 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 rect() 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 rect() 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 rect() 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",
4732            "itemtype": "method",
4733            "name": "rectMode",
4734            "params": [
4735                {
4736                    "name": "mode",
4737                    "description": "<p>either CORNER, CORNERS, CENTER, or RADIUS</p>\n",
4738                    "type": "Constant"
4739                }
4740            ],
4741            "chainable": 1,
4742            "example": [
4743                "\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>"
4744            ],
4745            "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.",
4746            "class": "p5",
4747            "module": "Shape",
4748            "submodule": "Attributes"
4749        },
4750        {
4751            "file": "src/core/attributes.js",
4752            "line": 180,
4753            "description": "<p>Draws all geometry with smooth (anti-aliased) edges. smooth() will also\nimprove image quality of resized images. Note that smooth() is active by\ndefault; noSmooth() can be used to disable smoothing of geometry,\nimages, and fonts.</p>\n",
4754            "itemtype": "method",
4755            "name": "smooth",
4756            "chainable": 1,
4757            "example": [
4758                "\n<div>\n<code>\nbackground(0);\nnoStroke();\nsmooth();\nellipse(30, 48, 36, 36);\nnoSmooth();\nellipse(70, 48, 36, 36);\n</code>\n</div>"
4759            ],
4760            "alt": "2 pixelated 36x36 white ellipses one left one right of center. On black.",
4761            "class": "p5",
4762            "module": "Shape",
4763            "submodule": "Attributes"
4764        },
4765        {
4766            "file": "src/core/attributes.js",
4767            "line": 209,
4768            "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",
4769            "itemtype": "method",
4770            "name": "strokeCap",
4771            "params": [
4772                {
4773                    "name": "cap",
4774                    "description": "<p>either SQUARE, PROJECT, or ROUND</p>\n",
4775                    "type": "Constant"
4776                }
4777            ],
4778            "chainable": 1,
4779            "example": [
4780                "\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>"
4781            ],
4782            "alt": "3 lines. Top line: rounded ends, mid: squared, bottom:longer squared ends.",
4783            "class": "p5",
4784            "module": "Shape",
4785            "submodule": "Attributes"
4786        },
4787        {
4788            "file": "src/core/attributes.js",
4789            "line": 246,
4790            "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",
4791            "itemtype": "method",
4792            "name": "strokeJoin",
4793            "params": [
4794                {
4795                    "name": "join",
4796                    "description": "<p>either MITER, BEVEL, ROUND</p>\n",
4797                    "type": "Constant"
4798                }
4799            ],
4800            "chainable": 1,
4801            "example": [
4802                "\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>"
4803            ],
4804            "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.",
4805            "class": "p5",
4806            "module": "Shape",
4807            "submodule": "Attributes"
4808        },
4809        {
4810            "file": "src/core/attributes.js",
4811            "line": 313,
4812            "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",
4813            "itemtype": "method",
4814            "name": "strokeWeight",
4815            "params": [
4816                {
4817                    "name": "weight",
4818                    "description": "<p>the weight (in pixels) of the stroke</p>\n",
4819                    "type": "Number"
4820                }
4821            ],
4822            "chainable": 1,
4823            "example": [
4824                "\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>"
4825            ],
4826            "alt": "3 horizontal black lines. Top line: thin, mid: medium, bottom:thick.",
4827            "class": "p5",
4828            "module": "Shape",
4829            "submodule": "Attributes"
4830        },
4831        {
4832            "file": "src/core/canvas.js",
4833            "line": 1,
4834            "requires": [
4835                "constants"
4836            ],
4837            "class": "p5",
4838            "module": "Shape"
4839        },
4840        {
4841            "file": "src/core/constants.js",
4842            "line": 13,
4843            "itemtype": "property",
4844            "name": "P2D",
4845            "type": "String",
4846            "final": 1,
4847            "class": "p5",
4848            "module": "Constants",
4849            "submodule": "Constants"
4850        },
4851        {
4852            "file": "src/core/constants.js",
4853            "line": 18,
4854            "itemtype": "property",
4855            "name": "WEBGL",
4856            "type": "String",
4857            "final": 1,
4858            "class": "p5",
4859            "module": "Constants",
4860            "submodule": "Constants"
4861        },
4862        {
4863            "file": "src/core/constants.js",
4864            "line": 34,
4865            "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 sin() and cos().</p>\n",
4866            "itemtype": "property",
4867            "name": "HALF_PI",
4868            "type": "Number",
4869            "final": 1,
4870            "example": [
4871                "\n<div><code>\narc(50, 50, 80, 80, 0, HALF_PI);\n</code></div>"
4872            ],
4873            "alt": "80x80 white quarter-circle with curve toward bottom right of canvas.",
4874            "class": "p5",
4875            "module": "Constants",
4876            "submodule": "Constants"
4877        },
4878        {
4879            "file": "src/core/constants.js",
4880            "line": 53,
4881            "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 sin() and cos().</p>\n",
4882            "itemtype": "property",
4883            "name": "PI",
4884            "type": "Number",
4885            "final": 1,
4886            "example": [
4887                "\n<div><code>\narc(50, 50, 80, 80, 0, PI);\n</code></div>"
4888            ],
4889            "alt": "white half-circle with curve toward bottom of canvas.",
4890            "class": "p5",
4891            "module": "Constants",
4892            "submodule": "Constants"
4893        },
4894        {
4895            "file": "src/core/constants.js",
4896            "line": 72,
4897            "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 sin() and cos().</p>\n",
4898            "itemtype": "property",
4899            "name": "QUARTER_PI",
4900            "type": "Number",
4901            "final": 1,
4902            "example": [
4903                "\n<div><code>\narc(50, 50, 80, 80, 0, QUARTER_PI);\n</code></div>"
4904            ],
4905            "alt": "white eighth-circle rotated about 40 degrees with curve bottom right canvas.",
4906            "class": "p5",
4907            "module": "Constants",
4908            "submodule": "Constants"
4909        },
4910        {
4911            "file": "src/core/constants.js",
4912            "line": 91,
4913            "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 sin() and cos().</p>\n",
4914            "itemtype": "property",
4915            "name": "TAU",
4916            "type": "Number",
4917            "final": 1,
4918            "example": [
4919                "\n<div><code>\narc(50, 50, 80, 80, 0, TAU);\n</code></div>"
4920            ],
4921            "alt": "80x80 white ellipse shape in center of canvas.",
4922            "class": "p5",
4923            "module": "Constants",
4924            "submodule": "Constants"
4925        },
4926        {
4927            "file": "src/core/constants.js",
4928            "line": 110,
4929            "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 sin() and cos().</p>\n",
4930            "itemtype": "property",
4931            "name": "TWO_PI",
4932            "type": "Number",
4933            "final": 1,
4934            "example": [
4935                "\n<div><code>\narc(50, 50, 80, 80, 0, TWO_PI);\n</code></div>"
4936            ],
4937            "alt": "80x80 white ellipse shape in center of canvas.",
4938            "class": "p5",
4939            "module": "Constants",
4940            "submodule": "Constants"
4941        },
4942        {
4943            "file": "src/core/constants.js",
4944            "line": 129,
4945            "description": "<p>Constant to be used with angleMode() function, to set the mode which\np5.js interprates and calculates angles (either DEGREES or RADIANS).</p>\n",
4946            "itemtype": "property",
4947            "name": "DEGREES",
4948            "type": "String",
4949            "final": 1,
4950            "example": [
4951                "\n<div class='norender'><code>\nfunction setup() {\n  angleMode(DEGREES);\n}\n</code></div>"
4952            ],
4953            "class": "p5",
4954            "module": "Constants",
4955            "submodule": "Constants"
4956        },
4957        {
4958            "file": "src/core/constants.js",
4959            "line": 143,
4960            "description": "<p>Constant to be used with angleMode() function, to set the mode which\np5.js interprates and calculates angles (either RADIANS or DEGREES).</p>\n",
4961            "itemtype": "property",
4962            "name": "RADIANS",
4963            "type": "String",
4964            "final": 1,
4965            "example": [
4966                "\n<div class='norender'><code>\nfunction setup() {\n  angleMode(RADIANS);\n}\n</code></div>"
4967            ],
4968            "class": "p5",
4969            "module": "Constants",
4970            "submodule": "Constants"
4971        },
4972        {
4973            "file": "src/core/constants.js",
4974            "line": 161,
4975            "itemtype": "property",
4976            "name": "CORNER",
4977            "type": "String",
4978            "final": 1,
4979            "class": "p5",
4980            "module": "Constants",
4981            "submodule": "Constants"
4982        },
4983        {
4984            "file": "src/core/constants.js",
4985            "line": 166,
4986            "itemtype": "property",
4987            "name": "CORNERS",
4988            "type": "String",
4989            "final": 1,
4990            "class": "p5",
4991            "module": "Constants",
4992            "submodule": "Constants"
4993        },
4994        {
4995            "file": "src/core/constants.js",
4996            "line": 171,
4997            "itemtype": "property",
4998            "name": "RADIUS",
4999            "type": "String",
5000            "final": 1,
5001            "class": "p5",
5002            "module": "Constants",
5003            "submodule": "Constants"
5004        },
5005        {
5006            "file": "src/core/constants.js",
5007            "line": 176,
5008            "itemtype": "property",
5009            "name": "RIGHT",
5010            "type": "String",
5011            "final": 1,
5012            "class": "p5",
5013            "module": "Constants",
5014            "submodule": "Constants"
5015        },
5016        {
5017            "file": "src/core/constants.js",
5018            "line": 181,
5019            "itemtype": "property",
5020            "name": "LEFT",
5021            "type": "String",
5022            "final": 1,
5023            "class": "p5",
5024            "module": "Constants",
5025            "submodule": "Constants"
5026        },
5027        {
5028            "file": "src/core/constants.js",
5029            "line": 186,
5030            "itemtype": "property",
5031            "name": "CENTER",
5032            "type": "String",
5033            "final": 1,
5034            "class": "p5",
5035            "module": "Constants",
5036            "submodule": "Constants"
5037        },
5038        {
5039            "file": "src/core/constants.js",
5040            "line": 191,
5041            "itemtype": "property",
5042            "name": "TOP",
5043            "type": "String",
5044            "final": 1,
5045            "class": "p5",
5046            "module": "Constants",
5047            "submodule": "Constants"
5048        },
5049        {
5050            "file": "src/core/constants.js",
5051            "line": 196,
5052            "itemtype": "property",
5053            "name": "BOTTOM",
5054            "type": "String",
5055            "final": 1,
5056            "class": "p5",
5057            "module": "Constants",
5058            "submodule": "Constants"
5059        },
5060        {
5061            "file": "src/core/constants.js",
5062            "line": 201,
5063            "itemtype": "property",
5064            "name": "BASELINE",
5065            "type": "String",
5066            "final": 1,
5067            "default": "alphabetic",
5068            "class": "p5",
5069            "module": "Constants",
5070            "submodule": "Constants"
5071        },
5072        {
5073            "file": "src/core/constants.js",
5074            "line": 207,
5075            "itemtype": "property",
5076            "name": "POINTS",
5077            "type": "Number",
5078            "final": 1,
5079            "default": "0x0000",
5080            "class": "p5",
5081            "module": "Constants",
5082            "submodule": "Constants"
5083        },
5084        {
5085            "file": "src/core/constants.js",
5086            "line": 213,
5087            "itemtype": "property",
5088            "name": "LINES",
5089            "type": "Number",
5090            "final": 1,
5091            "default": "0x0001",
5092            "class": "p5",
5093            "module": "Constants",
5094            "submodule": "Constants"
5095        },
5096        {
5097            "file": "src/core/constants.js",
5098            "line": 219,
5099            "itemtype": "property",
5100            "name": "LINE_STRIP",
5101            "type": "Number",
5102            "final": 1,
5103            "default": "0x0003",
5104            "class": "p5",
5105            "module": "Constants",
5106            "submodule": "Constants"
5107        },
5108        {
5109            "file": "src/core/constants.js",
5110            "line": 225,
5111            "itemtype": "property",
5112            "name": "LINE_LOOP",
5113            "type": "Number",
5114            "final": 1,
5115            "default": "0x0002",
5116            "class": "p5",
5117            "module": "Constants",
5118            "submodule": "Constants"
5119        },
5120        {
5121            "file": "src/core/constants.js",
5122            "line": 231,
5123            "itemtype": "property",
5124            "name": "TRIANGLES",
5125            "type": "Number",
5126            "final": 1,
5127            "default": "0x0004",
5128            "class": "p5",
5129            "module": "Constants",
5130            "submodule": "Constants"
5131        },
5132        {
5133            "file": "src/core/constants.js",
5134            "line": 237,
5135            "itemtype": "property",
5136            "name": "TRIANGLE_FAN",
5137            "type": "Number",
5138            "final": 1,
5139            "default": "0x0006",
5140            "class": "p5",
5141            "module": "Constants",
5142            "submodule": "Constants"
5143        },
5144        {
5145            "file": "src/core/constants.js",
5146            "line": 243,
5147            "itemtype": "property",
5148            "name": "TRIANGLE_STRIP",
5149            "type": "Number",
5150            "final": 1,
5151            "default": "0x0005",
5152            "class": "p5",
5153            "module": "Constants",
5154            "submodule": "Constants"
5155        },
5156        {
5157            "file": "src/core/constants.js",
5158            "line": 249,
5159            "itemtype": "property",
5160            "name": "QUADS",
5161            "type": "String",
5162            "final": 1,
5163            "class": "p5",
5164            "module": "Constants",
5165            "submodule": "Constants"
5166        },
5167        {
5168            "file": "src/core/constants.js",
5169            "line": 254,
5170            "itemtype": "property",
5171            "name": "QUAD_STRIP",
5172            "type": "String",
5173            "final": 1,
5174            "default": "quad_strip",
5175            "class": "p5",
5176            "module": "Constants",
5177            "submodule": "Constants"
5178        },
5179        {
5180            "file": "src/core/constants.js",
5181            "line": 260,
5182            "itemtype": "property",
5183            "name": "CLOSE",
5184            "type": "String",
5185            "final": 1,
5186            "class": "p5",
5187            "module": "Constants",
5188            "submodule": "Constants"
5189        },
5190        {
5191            "file": "src/core/constants.js",
5192            "line": 265,
5193            "itemtype": "property",
5194            "name": "OPEN",
5195            "type": "String",
5196            "final": 1,
5197            "class": "p5",
5198            "module": "Constants",
5199            "submodule": "Constants"
5200        },
5201        {
5202            "file": "src/core/constants.js",
5203            "line": 270,
5204            "itemtype": "property",
5205            "name": "CHORD",
5206            "type": "String",
5207            "final": 1,
5208            "class": "p5",
5209            "module": "Constants",
5210            "submodule": "Constants"
5211        },
5212        {
5213            "file": "src/core/constants.js",
5214            "line": 275,
5215            "itemtype": "property",
5216            "name": "PIE",
5217            "type": "String",
5218            "final": 1,
5219            "class": "p5",
5220            "module": "Constants",
5221            "submodule": "Constants"
5222        },
5223        {
5224            "file": "src/core/constants.js",
5225            "line": 280,
5226            "itemtype": "property",
5227            "name": "PROJECT",
5228            "type": "String",
5229            "final": 1,
5230            "default": "square",
5231            "class": "p5",
5232            "module": "Constants",
5233            "submodule": "Constants"
5234        },
5235        {
5236            "file": "src/core/constants.js",
5237            "line": 286,
5238            "itemtype": "property",
5239            "name": "SQUARE",
5240            "type": "String",
5241            "final": 1,
5242            "default": "butt",
5243            "class": "p5",
5244            "module": "Constants",
5245            "submodule": "Constants"
5246        },
5247        {
5248            "file": "src/core/constants.js",
5249            "line": 292,
5250            "itemtype": "property",
5251            "name": "ROUND",
5252            "type": "String",
5253            "final": 1,
5254            "class": "p5",
5255            "module": "Constants",
5256            "submodule": "Constants"
5257        },
5258        {
5259            "file": "src/core/constants.js",
5260            "line": 297,
5261            "itemtype": "property",
5262            "name": "BEVEL",
5263            "type": "String",
5264            "final": 1,
5265            "class": "p5",
5266            "module": "Constants",
5267            "submodule": "Constants"
5268        },
5269        {
5270            "file": "src/core/constants.js",
5271            "line": 302,
5272            "itemtype": "property",
5273            "name": "MITER",
5274            "type": "String",
5275            "final": 1,
5276            "class": "p5",
5277            "module": "Constants",
5278            "submodule": "Constants"
5279        },
5280        {
5281            "file": "src/core/constants.js",
5282            "line": 309,
5283            "itemtype": "property",
5284            "name": "RGB",
5285            "type": "String",
5286            "final": 1,
5287            "class": "p5",
5288            "module": "Constants",
5289            "submodule": "Constants"
5290        },
5291        {
5292            "file": "src/core/constants.js",
5293            "line": 314,
5294            "itemtype": "property",
5295            "name": "HSB",
5296            "type": "String",
5297            "final": 1,
5298            "class": "p5",
5299            "module": "Constants",
5300            "submodule": "Constants"
5301        },
5302     
5302   {
5303            "file": "src/core/constants.js",
5304            "line": 319,
5305            "itemtype": "property",
5306            "name": "HSL",
5307            "type": "String",
5308            "final": 1,
5309            "class": "p5",
5310            "module": "Constants",
5311            "submodule": "Constants"
5312        },
5313        {
5314            "file": "src/core/constants.js",
5315            "line": 345,
5316            "itemtype": "property",
5317            "name": "BLEND",
5318            "type": "String",
5319            "final": 1,
5320            "default": "source-over",
5321            "class": "p5",
5322            "module": "Constants",
5323            "submodule": "Constants"
5324        },
5325        {
5326            "file": "src/core/constants.js",
5327            "line": 351,
5328            "itemtype": "property",
5329            "name": "ADD",
5330            "type": "String",
5331            "final": 1,
5332            "default": "lighter",
5333            "class": "p5",
5334            "module": "Constants",
5335            "submodule": "Constants"
5336        },
5337        {
5338            "file": "src/core/constants.js",
5339            "line": 359,
5340            "itemtype": "property",
5341            "name": "DARKEST",
5342            "type": "String",
5343            "final": 1,
5344            "class": "p5",
5345            "module": "Constants",
5346            "submodule": "Constants"
5347        },
5348        {
5349            "file": "src/core/constants.js",
5350            "line": 364,
5351            "itemtype": "property",
5352            "name": "LIGHTEST",
5353            "type": "String",
5354            "final": 1,
5355            "default": "lighten",
5356            "class": "p5",
5357            "module": "Constants",
5358            "submodule": "Constants"
5359        },
5360        {
5361            "file": "src/core/constants.js",
5362            "line": 370,
5363            "itemtype": "property",
5364            "name": "DIFFERENCE",
5365            "type": "String",
5366            "final": 1,
5367            "class": "p5",
5368            "module": "Constants",
5369            "submodule": "Constants"
5370        },
5371        {
5372            "file": "src/core/constants.js",
5373            "line": 375,
5374            "itemtype": "property",
5375            "name": "EXCLUSION",
5376            "type": "String",
5377            "final": 1,
5378            "class": "p5",
5379            "module": "Constants",
5380            "submodule": "Constants"
5381        },
5382        {
5383            "file": "src/core/constants.js",
5384            "line": 380,
5385            "itemtype": "property",
5386            "name": "MULTIPLY",
5387            "type": "String",
5388            "final": 1,
5389            "class": "p5",
5390            "module": "Constants",
5391            "submodule": "Constants"
5392        },
5393        {
5394            "file": "src/core/constants.js",
5395            "line": 385,
5396            "itemtype": "property",
5397            "name": "SCREEN",
5398            "type": "String",
5399            "final": 1,
5400            "class": "p5",
5401            "module": "Constants",
5402            "submodule": "Constants"
5403        },
5404        {
5405            "file": "src/core/constants.js",
5406            "line": 390,
5407            "itemtype": "property",
5408            "name": "REPLACE",
5409            "type": "String",
5410            "final": 1,
5411            "default": "copy",
5412            "class": "p5",
5413            "module": "Constants",
5414            "submodule": "Constants"
5415        },
5416        {
5417            "file": "src/core/constants.js",
5418            "line": 396,
5419            "itemtype": "property",
5420            "name": "OVERLAY",
5421            "type": "String",
5422            "final": 1,
5423            "class": "p5",
5424            "module": "Constants",
5425            "submodule": "Constants"
5426        },
5427        {
5428            "file": "src/core/constants.js",
5429            "line": 401,
5430            "itemtype": "property",
5431            "name": "HARD_LIGHT",
5432            "type": "String",
5433            "final": 1,
5434            "class": "p5",
5435            "module": "Constants",
5436            "submodule": "Constants"
5437        },
5438        {
5439            "file": "src/core/constants.js",
5440            "line": 406,
5441            "itemtype": "property",
5442            "name": "SOFT_LIGHT",
5443            "type": "String",
5444            "final": 1,
5445            "class": "p5",
5446            "module": "Constants",
5447            "submodule": "Constants"
5448        },
5449        {
5450            "file": "src/core/constants.js",
5451            "line": 411,
5452            "itemtype": "property",
5453            "name": "DODGE",
5454            "type": "String",
5455            "final": 1,
5456            "default": "color-dodge",
5457            "class": "p5",
5458            "module": "Constants",
5459            "submodule": "Constants"
5460        },
5461        {
5462            "file": "src/core/constants.js",
5463            "line": 417,
5464            "itemtype": "property",
5465            "name": "BURN",
5466            "type": "String",
5467            "final": 1,
5468            "default": "color-burn",
5469            "class": "p5",
5470            "module": "Constants",
5471            "submodule": "Constants"
5472        },
5473        {
5474            "file": "src/core/constants.js",
5475            "line": 425,
5476            "itemtype": "property",
5477            "name": "THRESHOLD",
5478            "type": "String",
5479            "final": 1,
5480            "class": "p5",
5481            "module": "Constants",
5482            "submodule": "Constants"
5483        },
5484        {
5485            "file": "src/core/constants.js",
5486            "line": 430,
5487            "itemtype": "property",
5488            "name": "GRAY",
5489            "type": "String",
5490            "final": 1,
5491            "class": "p5",
5492            "module": "Constants",
5493            "submodule": "Constants"
5494        },
5495        {
5496            "file": "src/core/constants.js",
5497            "line": 435,
5498            "itemtype": "property",
5499            "name": "OPAQUE",
5500            "type": "String",
5501            "final": 1,
5502            "class": "p5",
5503            "module": "Constants",
5504            "submodule": "Constants"
5505        },
5506        {
5507            "file": "src/core/constants.js",
5508            "line": 440,
5509            "itemtype": "property",
5510            "name": "INVERT",
5511            "type": "String",
5512            "final": 1,
5513            "class": "p5",
5514            "module": "Constants",
5515            "submodule": "Constants"
5516        },
5517        {
5518            "file": "src/core/constants.js",
5519            "line": 445,
5520            "itemtype": "property",
5521            "name": "POSTERIZE",
5522            "type": "String",
5523            "final": 1,
5524            "class": "p5",
5525            "module": "Constants",
5526            "submodule": "Constants"
5527        },
5528        {
5529            "file": "src/core/constants.js",
5530            "line": 450,
5531            "itemtype": "property",
5532            "name": "DILATE",
5533            "type": "String",
5534            "final": 1,
5535            "class": "p5",
5536            "module": "Constants",
5537            "submodule": "Constants"
5538        },
5539        {
5540            "file": "src/core/constants.js",
5541            "line": 455,
5542            "itemtype": "property",
5543            "name": "ERODE",
5544            "type": "String",
5545            "final": 1,
5546            "class": "p5",
5547            "module": "Constants",
5548            "submodule": "Constants"
5549        },
5550        {
5551            "file": "src/core/constants.js",
5552            "line": 460,
5553            "itemtype": "property",
5554            "name": "BLUR",
5555            "type": "String",
5556            "final": 1,
5557            "class": "p5",
5558            "module": "Constants",
5559            "submodule": "Constants"
5560        },
5561        {
5562            "file": "src/core/constants.js",
5563            "line": 467,
5564            "itemtype": "property",
5565            "name": "NORMAL",
5566            "type": "String",
5567            "final": 1,
5568            "class": "p5",
5569            "module": "Constants",
5570            "submodule": "Constants"
5571        },
5572        {
5573            "file": "src/core/constants.js",
5574            "line": 472,
5575            "itemtype": "property",
5576            "name": "ITALIC",
5577            "type": "String",
5578            "final": 1,
5579            "class": "p5",
5580            "module": "Constants",
5581            "submodule": "Constants"
5582        },
5583        {
5584            "file": "src/core/constants.js",
5585            "line": 477,
5586            "itemtype": "property",
5587            "name": "BOLD",
5588            "type": "String",
5589            "final": 1,
5590            "class": "p5",
5591            "module": "Constants",
5592            "submodule": "Constants"
5593        },
5594        {
5595            "file": "src/core/constants.js",
5596            "line": 501,
5597            "itemtype": "property",
5598            "name": "LANDSCAPE",
5599            "type": "String",
5600            "final": 1,
5601            "class": "p5",
5602            "module": "Constants",
5603            "submodule": "Constants"
5604        },
5605        {
5606            "file": "src/core/constants.js",
5607            "line": 506,
5608            "itemtype": "property",
5609            "name": "PORTRAIT",
5610            "type": "String",
5611            "final": 1,
5612            "class": "p5",
5613            "module": "Constants",
5614            "submodule": "Constants"
5615        },
5616        {
5617            "file": "src/core/core.js",
5618            "line": 49,
5619            "description": "<p>Called directly before setup(), the preload() function is used to handle\nasynchronous loading of external files in a blocking way. If a preload \nfunction is defined, setup() will wait until any load calls within have\nfinished. Nothing besides load calls (loadImage, loadJSON, loadFont,\nloadStrings, etc.) should be inside preload function. If asynchronous\nloading is preferred, the load methods can instead be called in setup()\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",
5620            "itemtype": "method",
5621            "name": "preload",
5622            "example": [
5623                "\n<div><code>\nvar img;\nvar 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>"
5624            ],
5625            "alt": "nothing displayed",
5626            "class": "p5",
5627            "module": "Structure",
5628            "submodule": "Structure"
5629        },
5630        {
5631            "file": "src/core/core.js",
5632            "line": 90,
5633            "description": "<p>The setup() 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 setup() function for each program and it shouldn&#39;t\nbe called again after its initial execution.\n<br><br>\nNote: Variables declared within setup() are not accessible within other\nfunctions, including draw().</p>\n",
5634            "itemtype": "method",
5635            "name": "setup",
5636            "example": [
5637                "\n<div><code>\nvar 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>"
5638            ],
5639            "alt": "nothing displayed",
5640            "class": "p5",
5641            "module": "Structure",
5642            "submodule": "Structure"
5643        },
5644        {
5645            "file": "src/core/core.js",
5646            "line": 121,
5647            "description": "<p>Called directly after setup(), the draw() function continuously executes\nthe lines of code contained inside its block until the program is stopped\nor noLoop() is called. Note if noLoop() is called 
5647in setup(), draw() will\nstill be executed once before stopping. draw() is called automatically and\nshould never be called explicitly.\n<br><br>\nIt should always be controlled with noLoop(), redraw() and loop(). After\nnoLoop() stops the code in draw() from executing, redraw() causes the\ncode inside draw() to execute once, and loop() will cause the code\ninside draw() to resume executing continuously.\n<br><br>\nThe number of times draw() executes in each second may be controlled with\nthe frameRate() function.\n<br><br>\nThere can only be one draw() function for each sketch, and draw() must\nexist if you want the code to run continuously, or to process events such\nas mousePressed(). Sometimes, you might have an empty call to draw() 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 draw() call. If any transformations are performed\nwithin draw() (ex: scale, rotate, translate), their effects will be\nundone at the beginning of draw(), so transformations will not accumulate\nover time. On the other hand, styling applied (ex: fill, stroke, etc) will\nremain in effect.</p>\n",
5648            "itemtype": "method",
5649            "name": "draw",
5650            "example": [
5651                "\n<div><code>\nvar 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>"
5652            ],
5653            "alt": "nothing displayed",
5654            "class": "p5",
5655            "module": "Structure",
5656            "submodule": "Structure"
5657        },
5658        {
5659            "file": "src/core/core.js",
5660            "line": 407,
5661            "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",
5662            "itemtype": "method",
5663            "name": "remove",
5664            "example": [
5665                "\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>"
5666            ],
5667            "alt": "nothing displayed",
5668            "class": "p5",
5669            "module": "Structure",
5670            "submodule": "Structure"
5671        },
5672        {
5673            "file": "src/core/curves.js",
5674            "line": 13,
5675            "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 curve().</p>\n",
5676            "itemtype": "method",
5677            "name": "bezier",
5678            "chainable": 1,
5679            "example": [
5680                "\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>"
5681            ],
5682            "alt": "stretched black s-shape in center with orange lines extending from end points.\
5682nstretched 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.",
5683            "class": "p5",
5684            "module": "Shape",
5685            "submodule": "Curves",
5686            "overloads": [
5687                {
5688                    "line": 13,
5689                    "params": [
5690                        {
5691                            "name": "x1",
5692                            "description": "<p>x-coordinate for the first anchor point</p>\n",
5693                            "type": "Number"
5694                        },
5695                        {
5696                            "name": "y1",
5697                            "description": "<p>y-coordinate for the first anchor point</p>\n",
5698                            "type": "Number"
5699                        },
5700                        {
5701                            "name": "x2",
5702                            "description": "<p>x-coordinate for the first control point</p>\n",
5703                            "type": "Number"
5704                        },
5705                        {
5706                            "name": "y2",
5707                            "description": "<p>y-coordinate for the first control point</p>\n",
5708                            "type": "Number"
5709                        },
5710                        {
5711                            "name": "x3",
5712                            "description": "<p>x-coordinate for the second control point</p>\n",
5713                            "type": "Number"
5714                        },
5715                        {
5716                            "name": "y3",
5717                            "description": "<p>y-coordinate for the second control point</p>\n",
5718                            "type": "Number"
5719                        },
5720                        {
5721                            "name": "x4",
5722                            "description": "<p>x-coordinate for the second anchor point</p>\n",
5723                            "type": "Number"
5724                        },
5725                        {
5726                            "name": "y4",
5727                            "description": "<p>y-coordinate for the second anchor point</p>\n",
5728                            "type": "Number"
5729                        }
5730                    ],
5731                    "chainable": 1
5732                },
5733                {
5734                    "line": 66,
5735                    "params": [
5736                        {
5737                            "name": "x1",
5738                            "description": "",
5739                            "type": "Number"
5740                        },
5741                        {
5742                            "name": "y1",
5743                            "description": "",
5744                            "type": "Number"
5745                        },
5746                        {
5747                            "name": "z1",
5748                            "description": "<p>z-coordinate for the first anchor point</p>\n",
5749                            "type": "Number"
5750                        },
5751                        {
5752                            "name": "x2",
5753                            "description": "",
5754                            "type": "Number"
5755                        },
5756                        {
5757                            "name": "y2",
5758                            "description": "",
5759                            "type": "Number"
5760                        },
5761                        {
5762                            "name": "z2",
5763                            "description": "<p>z-coordinate for the first control point</p>\n",
5764                            "type": "Number"
5765                        },
5766                        {
5767                            "name": "x3",
5768                            "description": "",
5769                            "type": "Number"
5770                        },
5771                        {
5772                            "name": "y3",
5773                            "description": "",
5774                            "type": "Number"
5775                        },
5776                        {
5777                            "name": "z3",
5778                            "description": "<p>z-coordinate for the second control point</p>\n",
5779                            "type": "Number"
5780                        },
5781                        {
5782                            "name": "x4",
5783                            "description": "",
5784                            "type": "Number"
5785                        },
5786                        {
5787                            "name": "y4",
5788                            "description": "",
5789                            "type": "Number"
5790                        },
5791                        {
5792                            "name": "z4",
5793                            "description": "<p>z-coordinate for the second anchor point</p>\n",
5794                            "type": "Number"
5795                        }
5796                    ],
5797                    "chainable": 1
5798                }
5799            ]
5800        },
5801        {
5802            "file": "src/core/curves.js",
5803            "line": 92,
5804            "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",
5805            "itemtype": "method",
5806            "name": "bezierDetail",
5807            "params": [
5808                {
5809                    "name": "detail",
5810                    "description": "<p>resolution of the curves</p>\n",
5811                    "type": "Number"
5812                }
5813            ],
5814            "chainable": 1,
5815            "example": [
5816                "\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>"
5817            ],
5818            "alt": "stretched black s-shape with a low level of bezier detail",
5819            "class": "p5",
5820            "module": "Shape",
5821            "submodule": "Curves"
5822        },
5823        {
5824            "file": "src/core/curves.js",
5825            "line": 135,
5826            "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.\
5826nThe 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",
5827            "itemtype": "method",
5828            "name": "bezierPoint",
5829            "params": [
5830                {
5831                    "name": "a",
5832                    "description": "<p>coordinate of first point on the curve</p>\n",
5833                    "type": "Number"
5834                },
5835                {
5836                    "name": "b",
5837                    "description": "<p>coordinate of first control point</p>\n",
5838                    "type": "Number"
5839                },
5840                {
5841                    "name": "c",
5842                    "description": "<p>coordinate of second control point</p>\n",
5843                    "type": "Number"
5844                },
5845                {
5846                    "name": "d",
5847                    "description": "<p>coordinate of second point on the curve</p>\n",
5848                    "type": "Number"
5849                },
5850                {
5851                    "name": "t",
5852                    "description": "<p>value between 0 and 1</p>\n",
5853                    "type": "Number"
5854                }
5855            ],
5856            "return": {
5857                "description": "the value of the Bezier at position t",
5858                "type": "Number"
5859            },
5860            "example": [
5861                "\n<div>\n<code>\nnoFill();\nvar x1 = 85,\n x2 = 10,\n x3 = 90,\n x4 = 15;\nvar y1 = 20,\n y2 = 10,\n y3 = 90,\n y4 = 80;\nbezier(x1, y1, x2, y2, x3, y3, x4, y4);\nfill(255);\nvar steps = 10;\nfor (var i = 0; i <= steps; i++) {\n  var t = i / steps;\n  var x = bezierPoint(x1, x2, x3, x4, t);\n  var y = bezierPoint(y1, y2, y3, y4, t);\n  ellipse(x, y, 5, 5);\n}\n</code>\n</div>"
5862            ],
5863            "alt": "stretched black s-shape with 17 small orange lines extending from under shape.",
5864            "class": "p5",
5865            "module": "Shape",
5866            "submodule": "Curves"
5867        },
5868        {
5869            "file": "src/core/curves.js",
5870            "line": 190,
5871            "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",
5872            "itemtype": "method",
5873            "name": "bezierTangent",
5874            "params": [
5875                {
5876                    "name": "a",
5877                    "description": "<p>coordinate of first point on the curve</p>\n",
5878                    "type": "Number"
5879                },
5880                {
5881                    "name": "b",
5882                    "description": "<p>coordinate of first control point</p>\n",
5883                    "type": "Number"
5884                },
5885                {
5886                    "name": "c",
5887                    "description": "<p>coordinate of second control point</p>\n",
5888                    "type": "Number"
5889                },
5890                {
5891                    "name": "d",
5892                    "description": "<p>coordinate of second point on the curve</p>\n",
5893                    "type": "Number"
5894                },
5895                {
5896                    "name": "t",
5897                    "description": "<p>value between 0 and 1</p>\n",
5898                    "type": "Number"
5899                }
5900            ],
5901            "return": {
5902                "description": "the tangent at position t",
5903                "type": "Number"
5904            },
5905            "example": [
5906                "\n<div>\n<code>\nnoFill();\nbezier(85, 20, 10, 10, 90, 90, 15, 80);\nvar steps = 6;\nfill(255);\nfor (var i = 0; i <= steps; i++) {\n  var t = i / steps;\n  // Get the location of the point\n  var x = bezierPoint(85, 10, 90, 15, t);\n  var y = bezierPoint(20, 10, 90, 80, t);\n  // Get the tangent points\n  var tx = bezierTangent(85, 10, 90, 15, t);\n  var ty = bezierTangent(20, 10, 90, 80, t);\n  // Calculate an angle from the tangent points\n  var 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);\nvar steps = 16;\nfor (var i = 0; i <= steps;
5906 i++) {\n  var t = i / steps;\n  var x = bezierPoint(85, 10, 90, 15, t);\n  var y = bezierPoint(20, 10, 90, 80, t);\n  var tx = bezierTangent(85, 10, 90, 15, t);\n  var ty = bezierTangent(20, 10, 90, 80, t);\n  var 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>"
5907            ],
5908            "alt": "s-shaped line with 17 short orange lines extending from underside of shape",
5909            "class": "p5",
5910            "module": "Shape",
5911            "submodule": "Curves"
5912        },
5913        {
5914            "file": "src/core/curves.js",
5915            "line": 269,
5916            "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;s not drawn. The last\ntwo parameters similarly describe the other control point. <br /><br />\nLonger curves can be created by putting a series of curve() functions\ntogether or using curveVertex(). An additional function called\ncurveTightness() provides control for the visual quality of the curve.\nThe curve() function is an implementation of Catmull-Rom splines.</p>\n",
5917            "itemtype": "method",
5918            "name": "curve",
5919            "chainable": 1,
5920            "example": [
5921                "\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\nvar p1 = { x: 5, y: 26 },\n p2 = { x: 73, y: 24 };\nvar 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>"
5922            ],
5923            "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.",
5924            "class": "p5",
5925            "module": "Shape",
5926            "submodule": "Curves",
5927            "overloads": [
5928                {
5929                    "line": 269,
5930                    "params": [
5931                        {
5932                            "name": "x1",
5933                            "description": "<p>x-coordinate for the beginning control point</p>\n",
5934                            "type": "Number"
5935                        },
5936                        {
5937                            "name": "y1",
5938                            "description": "<p>y-coordinate for the beginning control point</p>\n",
5939                            "type": "Number"
5940                        },
5941                        {
5942                            "name": "x2",
5943                            "description": "<p>x-coordinate for the first point</p>\n",
5944                            "type": "Number"
5945                        },
5946                        {
5947                            "name": "y2",
5948                            "description": "<p>y-coordinate for the first point</p>\n",
5949                            "type": "Number"
5950                        },
5951                        {
5952                            "name": "x3",
5953                            "description": "<p>x-coordinate for the second point</p>\n",
5954                            "type": "Number"
5955                        },
5956                        {
5957                            "name": "y3",
5958                            "description": "<p>y-coordinate for the second point</p>\n",
5959                            "type": "Number"
5960                        },
5961                        {
5962                            "name": "x4",
5963                            "description": "<p>x-coordinate for the ending control point</p>\n",
5964                            "type": "Number"
5965                        },
5966                        {
5967                            "name": "y4",
5968                            "description": "<p>y-coordinate for the ending control point</p>\n",
5969                            "type": "Number"
5970                        }
5971                    ],
5972                    "chainable": 1
5973                },
5974                {
5975                    "line": 334,
5976                    "params": [
5977                        {
5978                            "name": "x1",
5979                            "description": "",
5980                            "type": "Number"
5981                        },
5982                        {
5983                            "name": "y1",
5984                            "description": "",
5985                            "type": "Number"
5986                        },
5987                        {
5988                            "name": "z1",
5989                            "description": "<p>z-coordinate for the beginning control point</p>\n",
5990                            "type": "Number"
5991                        },
5992                        {
5993                            "name": "x2",
5994                            "description": "",
5995                            "type": "Number"
5996                        },
5997                        {
5998                            "name": "y2",
5999                            "description": "",
6000                            "type": "Number"
6001                        },
6002                        {
6003                            "name": "z2",
6004                            "description": "<p>z-coordinate for the first point</p>\n",
6005                            "type": "Number"
6006                        },
6007                        {
6008                            "name": "x3",
6009                            "description": "",
6010                            "type": "Number"
6011                        },
6012                        {
6013                            "name": "y3",
6014                            "description": "",
6015                            "type": "Number"
6016                        },
6017                        {
6018                            "name": "z3",
6019                            "description": "<p>z-coordinate for the second point</p>\n",
6020                            "type": "Number"
6021                        },
6022                        {
6023                            "name": "x4",
6024                            "description": "",
6025                            "type": "Number"
6026                        },
6027                        {
6028                            "name": "y4",
6029                            "description": "",
6030                            "type": "Number"
6031                        },
6032                        {
6033                            "name": "z4",
6034                            "description": "<p>z-coordinate for the ending control point</p>\n",
6035                            "type": "Number"
6036                        }
6037                    ],
6038                    "chainable": 1
6039                }
6040            ]
6041        },
6042        {
6043            "file": "src/core/curves.js",
6044            "line": 360,
6045            "description": "<p>Sets the resolution at which curves 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\ninformation.</p>\n",
6046            "itemtype": "method",
6047            "name": "curveDetail",
6048            "params": [
6049                {
6050                    "name": "resolution",
6051                    "description": "<p>of the curves</p>\n",
6052                    "type": "Number"
6053                }
6054            ],
6055            "chainable": 1,
6056            "example": [
6057                "\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  // prettier-ignore\n  curve( 250, 600, 0,\n         -30,  40, 0,\n          30,  30, 0,\n        -250, 600, 0);\n}\n</code>\n</div>"
6058            ],
6059            "alt": "white arch shape with a low level of curve detail.",
6060            "class": "p5",
6061            "module": "Shape",
6062            "submodule": "Curves"
6063        },
6064        {
6065            "file": "src/core/curves.js",
6066            "line": 402,
6067            "description": "<p>
6067Modifies the quality of forms created with curve() and curveVertex().\nThe parameter tightness determines how the curve fits to the vertex\npoints. The value 0.0 is the default value for tightness (this value\ndefines 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",
6068            "itemtype": "method",
6069            "name": "curveTightness",
6070            "params": [
6071                {
6072                    "name": "amount",
6073                    "description": "<p>of deformation from the original vertices</p>\n",
6074                    "type": "Number"
6075                }
6076            ],
6077            "chainable": 1,
6078            "example": [
6079                "\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  var 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>"
6080            ],
6081            "alt": "Line shaped like right-facing arrow,points move with mouse-x and warp shape.",
6082            "class": "p5",
6083            "module": "Shape",
6084            "submodule": "Curves"
6085        },
6086        {
6087            "file": "src/core/curves.js",
6088            "line": 448,
6089            "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 points\non the curve, and b and c are the control points.\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",
6090            "itemtype": "method",
6091            "name": "curvePoint",
6092            "params": [
6093                {
6094                    "name": "a",
6095                    "description": "<p>coordinate of first point on the curve</p>\n",
6096                    "type": "Number"
6097                },
6098                {
6099                    "name": "b",
6100                    "description": "<p>coordinate of first control point</p>\n",
6101                    "type": "Number"
6102                },
6103                {
6104                    "name": "c",
6105                    "description": "<p>coordinate of second control point</p>\n",
6106                    "type": "Number"
6107                },
6108                {
6109                    "name": "d",
6110                    "description": "<p>coordinate of second point on the curve</p>\n",
6111                    "type": "Number"
6112                },
6113                {
6114                    "name": "t",
6115                    "description": "<p>value between 0 and 1</p>\n",
6116                    "type": "Number"
6117                }
6118            ],
6119            "return": {
6120                "description": "bezier value at position t",
6121                "type": "Number"
6122            },
6123            "example": [
6124                "\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);\nvar steps = 6;\nfor (var i = 0; i <= steps; i++) {\n  var t = i / steps;\n  var x = curvePoint(5, 5, 73, 73, t);\n  var 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"
6125            ],
6126            "class": "p5",
6127            "module": "Shape",
6128            "submodule": "Curves"
6129        },
6130        {
6131            "file": "src/core/curves.js",
6132            "line": 497,
6133            "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",
6134            "itemtype": "method",
6135            "name": "curveTangent",
6136            "params": [
6137                {
6138                    "name": "a",
6139                    "description": "<p>coordinate of first point on the curve</p>\n",
6140                    "type": "Number"
6141                },
6142                {
6143                    "name": "b",
6144                    "description": "<p>coordinate of first control point</p>\n",
6145                    "type": "Number"
6146                },
6147                {
6148                    "name": "c",
6149                    "description": "<p>coordinate of second control point</p>\n",
6150                    "type": "Number"
6151                },
6152                {
6153                    "name": "d",
6154                    "description": "<p>coordinate of second point on the curve</p>\n",
6155                    "type": "Number"
6156                },
6157                {
6158                    "name": "t",
6159                    "description": "<p>value between 0 and 1</p>\n",
6160                    "type": "Number"
6161                }
6162            ],
6163            "return": {
6164                "description": "the tangent at position t",
6165                "type": "Number"
6166            },
6167            "example": [
6168                "\n<div>\n<code>\nnoFill();\ncurve(5, 26, 73, 24, 73, 61, 15, 65);\nvar steps = 6;\nfor (var i = 0; i <= steps;
6168 i++) {\n  var t = i / steps;\n  var x = curvePoint(5, 73, 73, 15, t);\n  var y = curvePoint(26, 24, 61, 65, t);\n  //ellipse(x, y, 5, 5);\n  var tx = curveTangent(5, 73, 73, 15, t);\n  var ty = curveTangent(26, 24, 61, 65, t);\n  var 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>"
6169            ],
6170            "alt": "right curving line mid-right of canvas with 7 short lines radiating from it.",
6171            "class": "p5",
6172            "module": "Shape",
6173            "submodule": "Curves"
6174        },
6175        {
6176            "file": "src/core/environment.js",
6177            "line": 22,
6178            "description": "<p>The print() 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",
6179            "itemtype": "method",
6180            "name": "print",
6181            "params": [
6182                {
6183                    "name": "contents",
6184                    "description": "<p>any combination of Number, String, Object, Boolean,\n                      Array to print</p>\n",
6185                    "type": "Any"
6186                }
6187            ],
6188            "example": [
6189                "\n<div><code class='norender'>\nvar x = 10;\nprint('The value of x is ' + x);\n// prints \"The value of x is 10\"\n</code></div>"
6190            ],
6191            "alt": "default grey canvas",
6192            "class": "p5",
6193            "module": "Environment",
6194            "submodule": "Environment"
6195        },
6196        {
6197            "file": "src/core/environment.js",
6198            "line": 49,
6199            "description": "<p>The system variable frameCount contains the number of frames that have\nbeen displayed since the program started. Inside setup() the value is 0,\nafter the first iteration of draw it is 1, etc.</p>\n",
6200            "itemtype": "property",
6201            "name": "frameCount",
6202            "type": "Integer",
6203            "readonly": "",
6204            "example": [
6205                "\n  <div><code>\nfunction setup() {\n  frameRate(30);\n  textSize(20);\n  textSize(30);\n  textAlign(CENTER);\n}\n\nfunction draw() {\n  background(200);\n  text(frameCount, width / 2, height / 2);\n}\n</code></div>"
6206            ],
6207            "alt": "numbers rapidly counting upward with frame count set to 30.",
6208            "class": "p5",
6209            "module": "Environment",
6210            "submodule": "Environment"
6211        },
6212        {
6213            "file": "src/core/environment.js",
6214            "line": 77,
6215            "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",
6216            "itemtype": "property",
6217            "name": "focused",
6218            "type": "Boolean",
6219            "readonly": "",
6220            "example": [
6221                "\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>"
6222            ],
6223            "alt": "green 50x50 ellipse at top left. Red X covers canvas when page focus changes",
6224            "class": "p5",
6225            "module": "Environment",
6226            "submodule": "Environment"
6227        },
6228        {
6229            "file": "src/core/environment.js",
6230            "line": 109,
6231            "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. It is not possible to load an\nimage as the cursor if you are exporting your program for the Web, and n
6231ot\nall MODES work with all browsers. The values for parameters x and y must\nbe less than the dimensions of the image.</p>\n",
6232            "itemtype": "method",
6233            "name": "cursor",
6234            "params": [
6235                {
6236                    "name": "type",
6237                    "description": "<p>either ARROW, CROSS, HAND, MOVE, TEXT, or\n                              WAIT, or path for image</p>\n",
6238                    "type": "String|Constant"
6239                },
6240                {
6241                    "name": "x",
6242                    "description": "<p>the horizontal active spot of the cursor</p>\n",
6243                    "type": "Number",
6244                    "optional": true
6245                },
6246                {
6247                    "name": "y",
6248                    "description": "<p>the vertical active spot of the cursor</p>\n",
6249                    "type": "Number",
6250                    "optional": true
6251                }
6252            ],
6253            "example": [
6254                "\n<div><code>\n// Move the mouse left and right across the image\n// to see the cursor change from a cross to a hand\nfunction draw() {\n  line(width / 2, 0, width / 2, height);\n  if (mouseX < 50) {\n    cursor(CROSS);\n  } else {\n    cursor(HAND);\n  }\n}\n</code></div>"
6255            ],
6256            "alt": "horizontal line divides canvas. cursor on left is a cross, right is hand.",
6257            "class": "p5",
6258            "module": "Environment",
6259            "submodule": "Environment"
6260        },
6261        {
6262            "file": "src/core/environment.js",
6263            "line": 170,
6264            "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 setup() is\nrecommended. The default rate is 60 frames per second. This is the same as\nsetFrameRate(val).\n<br><br>\nCalling frameRate() 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 getFrameRate().\n<br><br>\nCalling frameRate() with arguments that are not of the type numbers\nor are non positive also returns current framerate.</p>\n",
6265            "itemtype": "method",
6266            "name": "frameRate",
6267            "chainable": 1,
6268            "example": [
6269                "\n\n<div><code>\nvar rectX = 0;\nvar fr = 30; //starting FPS\nvar 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>"
6270            ],
6271            "alt": "blue rect moves left to right, followed by red rect moving faster. Loops.",
6272            "class": "p5",
6273            "module": "Environment",
6274            "submodule": "Environment",
6275            "overloads": [
6276                {
6277                    "line": 170,
6278                    "params": [
6279                        {
6280                            "name": "fps",
6281                            "description": "<p>number of frames to be displayed every second</p>\n",
6282                            "type": "Number"
6283                        }
6284                    ],
6285                    "chainable": 1
6286                },
6287                {
6288                    "line": 228,
6289                    "params": [],
6290                    "return": {
6291                        "description": "current frameRate",
6292                        "type": "Number"
6293                    }
6294                }
6295            ]
6296        },
6297        {
6298            "file": "src/core/environment.js",
6299            "line": 268,
6300            "description": "<p>Hides the cursor from view.</p>\n",
6301            "itemtype": "method",
6302            "name": "noCursor",
6303            "example": [
6304                "\n<div><code>\nfunction setup() {\n  noCursor();\n}\n\nfunction draw() {\n  background(200);\n  ellipse(mouseX, mouseY, 10, 10);\n}\n</code></div>"
6305            ],
6306            "alt": "cursor becomes 10x 10 white ellipse the moves with mouse x and y.",
6307            "class": "p5",
6308            "module": "Environment",
6309            "submodule": "Environment"
6310        },
6311        {
6312            "file": "src/core/environment.js",
6313            "line": 293,
6314            "description": "<p>System variable that stores the width of the entire screen display. This\nis used to run a full-screen program on any display size.</p>\n",
6315            "itemtype": "property",
6316            "name": "displayWidth",
6317            "type": "Number",
6318            "readonly": "",
6319            "example": [
6320                "\n<div class=\"norender\"><code>\ncreateCanvas(displayWidth, displayHeight);\n</code></div>"
6321            ],
6322            "alt": "cursor becomes 10x 10 white ellipse the moves with mouse x and y.",
6323            "class": "p5",
6324            "module": "Environment",
6325            "submodule": "Environment"
6326        },
6327        {
6328            "file": "src/core/environment.js",
6329            "line": 310,
6330            "description": "<p>System variable that stores the height of the entire screen display. This\nis used to run a full-screen program on any display size.</p>\n",
6331            "itemtype": "property",
6332            "name": "displayHeight",
6333            "type": "Number",
6334            "readonly": "",
6335            "example": [
6336                "\n<div class=\"norender\"><code>\ncreateCanvas(displayWidth, displayHeight);\n</code></div>"
6337            ],
6338            "alt": "no display.",
6339            "class": "p5",
6340            "module": "Environment",
6341            "submodule": "Environment"
6342        },
6343        {
6344            "file": "src/core/environment.js",
6345            "line": 327,
6346            "description": "<p>System variable that stores the width of the inner window, it maps to\nwindow.innerWidth.</p>\n",
6347            "itemtype": "property",
6348            "name": "windowWidth",
6349            "type": "Number",
6350            "readonly": "",
6351            "example": [
6352                "\n<div class=\"norender\"><code>\ncreateCanvas(windowWidth, windowHeight);\n</code></div>"
6353            ],
6354            "alt": "no display.",
6355            "class": "p5",
6356            "module": "Environment",
6357            "submodule": "Environment"
6358        },
6359        {
6360            "file": "src/core/environment.js",
6361            "line": 343,
6362            "description": "<p>System variable that stores the height of the inner window, it maps to\nwindow.innerHeight.</p>\n",
6363            "itemtype": "property",
6364            "name": "windowHeight",
6365            "type": "Number",
6366            "readonly": "",
6367            "example": [
6368                "\n<div class=\"norender\"><code>\ncreateCanvas(windowWidth, windowHeight);\n</code></div>"
6369            ],
6370            "alt": "no display.",
6371            "class": "p5",
6372            "module": "Environment",
6373            "submodule": "Environment"
6374        },
6375        {
6376            "file": "src/core/environment.js",
6377            "line": 359,
6378            "description": "<p>The windowResized() 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",
6379            "itemtype": "method",
6380            "name": "windowResized",
6381            "example": [
6382                "\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>"
6383            ],
6384            "alt": "no display.",
6385            "class": "p5",
6386            "module": "Environment",
6387            "submodule": "Environment"
6388        },
6389        {
6390            "file": "src/core/environment.js",
6391            "line": 413,
6392            "description": "<p>System variable that stores the width of the drawing canvas. This value\nis set by the first parameter of the createCanvas() 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\ncreateCanvas() is not used in a program.</p>\n",
6393            "itemtype": "property",
6394            "name": "width",
6395            "type": "Number",
6396            "readonly": "",
6397            "class": "p5",
6398            "module": "Environment",
6399            "submodule": "Environment"
6400        },
6401        {
6402            "file": "src/core/environment.js",
6403            "line": 425,
6404            "description": "<p>System variable that stores the height of the drawing canvas. This value\nis set by the second parameter of the createCanvas() 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\ncreateCanvas() is not used in a program.</p>\n",
6405            "itemtype": "property",
6406            "name": "height",
6407            "type": "Number",
6408            "readonly": "",
6409            "class": "p5",
6410            "module": "Environment",
6411            "submodule": "Environment"
6412        },
6413        {
6414            "file": "src/core/environment.js",
6415            "line": 437,
6416            "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",
6417            "itemtype": "method",
6418            "name": "fullscreen",
6419            "params": [
6420                {
6421                    "name": "val",
6422                    "description": "<p>whether the sketch should be in fullscreen mode\nor not</p>\n",
6423                    "type": "Boolean",
6424                    "optional": true
6425                }
6426            ],
6427            "return": {
6428                "description": "current fullscreen state",
6429                "type": "Boolean"
6430            },
6431            "example": [
6432                "\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    var fs = fullscreen();\n    fullscreen(!fs);\n  }\n}\n</code>\n</div>"
6433            ],
6434            "alt": "no display.",
6435            "class": "p5",
6436            "module": "Environment",
6437            "submodule": "Environment"
6438        },
6439        {
6440            "file": "src/core/environment.js",
6441            "line": 488,
6442            "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 pixelDensity() with no arguments returns\nthe current pixel density of the sketch.</p>\n",
6443            "itemtype": "method",
6444            "name": "pixelDensity",
6445            "params": [
6446                {
6447                    "name": "val",
6448                    "description": "<p>whether or how much the sketch should scale</p>\n",
6449                    "type": "Number",
6450                    "optional": true
6451                }
6452            ],
6453            "return": {
6454                "description": "current pixel density of the sketch",
6455                "type": "Number"
6456            },
6457            "example": [
6458                "\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>"
6459            ],
6460            "alt": "fuzzy 50x50 white ellipse with black outline in center of canvas.\nsharp 50x50 white ellipse with black outline in center of canvas.",
6461            "class": "p5",
6462            "module": "Environment",
6463            "submodule": "Environment"
6464        },
6465        {
6466            "file": "src/core/environment.js",
6467            "line": 534,
6468            "description": "<p>Returns the pixel density of the current display the sketch is running on.</p>\n",
6469            "itemtype": "method",
6470            "name": "displayDensity",
6471            "return": {
6472                "description": "current pixel density of the display",
6473                "type": "Number"
6474            },
6475            "example": [
6476                "\n<div>\n<code>\nfunction setup() {\n  var 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>"
6477            ],
6478            "alt": "50x50 white ellipse with black outline in center of canvas.",
6479            "class": "p5",
6480            "module": "Environment",
6481            "submodule": "Environment"
6482        },
6483        {
6484            "file": "src/core/environment.js",
6485            "line": 591,
6486            "description": "<p>Gets the current URL.</p>\n",
6487            "itemtype": "method",
6488            "name": "getURL",
6489            "return": {
6490                "description": "url",
6491                "type": "String"
6492            },
6493            "example": [
6494                "\n<div>\n<code>\nvar url;\nvar 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>"
6495            ],
6496            "alt": "current url (http://p5js.org/reference/#/p5/getURL) moves right to left.",
6497            "class": "p5",
6498            "module": "Environment",
6499            "submodule": "Environment"
6500        },
6501        {
6502            "file": "src/core/environment.js",
6503            "line": 622,
6504            "description": "<p>Gets the current URL path as an array.</p>\n",
6505            "itemtype": "method",
6506            "name": "getURLPath",
6507            "return": {
6508                "description": "path components",
6509                "type": "String[]"
6510            },
6511            "example": [
6512                "\n<div class='norender'><code>\nfunction setup() {\n  var urlPath = getURLPath();\n  for (var i = 0; i < urlPath.length; i++) {\n    text(urlPath[i], 10, i * 20 + 20);\n  }\n}\n</code></div>"
6513            ],
6514            "alt": "no display",
6515            "class": "p5",
6516            "module": "Environment",
6517            "submodule": "Environment"
6518        },
6519        {
6520            "file": "src/core/environment.js",
6521            "line": 645,
6522            "description": "<p>Gets the current URL params as an Object.</p>\n",
6523            "itemtype": "method",
6524            "name": "getURLParams",
6525            "return": {
6526                "description": "URL params",
6527                "type": "Object"
6528            },
6529            "example": [
6530                "\n<div class='norender notest'>\n<code>\n// Example: http://p5js.org?year=2014&month=May&day=15\n\nfunction setup() {\n  var 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>"
6531            ],
6532            "alt": "no display.",
6533            "class": "p5",
6534            "module": "Environment",
6535            "submodule": "Environment"
6536        },
6537        {
6538            "file": "src/core/error_helpers.js",
6539            "line": 1,
6540            "requires": [
6541                "core"
6542            ],
6543            "class": "p5",
6544            "module": "Environment"
6545        },
6546        {
6547            "file": "src/core/error_helpers.js",
6548            "line": 405,
6549            "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",
6550            "class": "p5",
6551            "module": "Environment"
6552        },
6553        {
6554            "file": "src/core/error_helpers.js",
6555            "line": 457,
6556            "description": "<p>Prints out all the colors in the color pallete with white text.\nFor color blindness testing.</p>\n",
6557            "class": "p5",
6558            "module": "Environment"
6559        },
6560        {
6561            "file": "src/core/p5.Element.js",
6562            "line": 26,
6563            "description": "<p>Underlying HTML element. All normal HTML methods can be called on this.</p>\n",
6564            "example": [
6565                "\n<div>\n<code>\ncreateCanvas(300, 500);\nbackground(0, 0, 0, 0);\nvar input = createInput();\ninput.position(20, 225);\nvar inputElem = new p5.Element(input.elt);\ninputElem.style('width:450px;');\ninputElem.value('some string');\n</code>\n</div>"
6566            ],
6567            "itemtype": "property",
6568            "name": "elt",
6569            "readonly": "",
6570            "class": "p5.Element",
6571            "module": "DOM",
6572            "submodule": "DOM"
6573        },
6574        {
6575            "file": "src/core/p5.Element.js",
6576            "line": 51,
6577            "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 p5.Element. 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.</p>\n",
6578            "itemtype": "method",
6579            "name": "parent",
6580            "chainable": 1,
6581            "example": [
6582                "\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);
6582 // use element from page\n </code></div>"
6583            ],
6584            "alt": "no display.",
6585            "class": "p5.Element",
6586            "module": "DOM",
6587            "submodule": "DOM",
6588            "overloads": [
6589                {
6590                    "line": 51,
6591                    "params": [
6592                        {
6593                            "name": "parent",
6594                            "description": "<p>the ID, DOM node, or p5.Element\n                         of desired parent element</p>\n",
6595                            "type": "String|p5.Element|Object"
6596                        }
6597                    ],
6598                    "chainable": 1
6599                },
6600                {
6601                    "line": 94,
6602                    "params": [],
6603                    "return": {
6604                        "description": "",
6605                        "type": "p5.Element"
6606                    }
6607                }
6608            ]
6609        },
6610        {
6611            "file": "src/core/p5.Element.js",
6612            "line": 116,
6613            "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",
6614            "itemtype": "method",
6615            "name": "id",
6616            "chainable": 1,
6617            "example": [
6618                "\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>"
6619            ],
6620            "alt": "no display.",
6621            "class": "p5.Element",
6622            "module": "DOM",
6623            "submodule": "DOM",
6624            "overloads": [
6625                {
6626                    "line": 116,
6627                    "params": [
6628                        {
6629                            "name": "id",
6630                            "description": "<p>ID of the element</p>\n",
6631                            "type": "String"
6632                        }
6633                    ],
6634                    "chainable": 1
6635                },
6636                {
6637                    "line": 138,
6638                    "params": [],
6639                    "return": {
6640                        "description": "the id of the element",
6641                        "type": "String"
6642                    }
6643                }
6644            ]
6645        },
6646        {
6647            "file": "src/core/p5.Element.js",
6648            "line": 153,
6649            "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",
6650            "itemtype": "method",
6651            "name": "class",
6652            "chainable": 1,
6653            "example": [
6654                "\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>"
6655            ],
6656            "alt": "no display.",
6657            "class": "p5.Element",
6658            "module": "DOM",
6659            "submodule": "DOM",
6660            "overloads": [
6661                {
6662                    "line": 153,
6663                    "params": [
6664                        {
6665                            "name": "class",
6666                            "description": "<p>class to add</p>\n",
6667                            "type": "String"
6668                        }
6669                    ],
6670                    "chainable": 1
6671                },
6672                {
6673                    "line": 175,
6674                    "params": [],
6675                    "return": {
6676                        "description": "the class of the element",
6677                        "type": "String"
6678                    }
6679                }
6680            ]
6681        },
6682        {
6683            "file": "src/core/p5.Element.js",
6684            "line": 188,
6685            "description": "<p>The .mousePressed() function is called once after every time a\nmouse button is pressed over the element. This can be used to\nattach element specific event listeners.</p>\n",
6686            "itemtype": "method",
6687            "name": "mousePressed",
6688            "params": [
6689                {
6690                    "name": "fxn",
6691                    "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",
6692                    "type": "Function|Boolean"
6693                }
6694            ],
6695            "chainable": 1,
6696            "example": [
6697                "\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}
6697\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>"
6698            ],
6699            "alt": "no display.",
6700            "class": "p5.Element",
6701            "module": "DOM",
6702            "submodule": "DOM"
6703        },
6704        {
6705            "file": "src/core/p5.Element.js",
6706            "line": 238,
6707            "description": "<p>The .doubleClicked() 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",
6708            "itemtype": "method",
6709            "name": "doubleClicked",
6710            "params": [
6711                {
6712                    "name": "fxn",
6713                    "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",
6714                    "type": "Function|Boolean"
6715                }
6716            ],
6717            "return": {
6718                "description": "",
6719                "type": "p5.Element"
6720            },
6721            "example": [
6722                "\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>"
6723            ],
6724            "alt": "no display.",
6725            "class": "p5.Element",
6726            "module": "DOM",
6727            "submodule": "DOM"
6728        },
6729        {
6730            "file": "src/core/p5.Element.js",
6731            "line": 287,
6732            "description": "<p>The .mouseWheel() 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",
6733            "itemtype": "method",
6734            "name": "mouseWheel",
6735            "params": [
6736                {
6737                    "name": "fxn",
6738                    "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",
6739                    "type": "Function|Boolean"
6740                }
6741            ],
6742            "chainable": 1,
6743            "example": [
6744                "\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>"
6745            ],
6746            "alt": "no display.",
6747            "class": "p5.Element",
6748            "module": "DOM",
6749            "submodule": "DOM"
6750        },
6751        {
6752            "file": "src/core/p5.Element.js",
6753            "line": 353,
6754            "description": "<p>The .mouseReleased() function is called once after every time a\nmouse button is released over the element. This can be used to\nattach element specific event listeners.</p>\n",
6755            "itemtype": "method",
6756            "name": "mouseReleased",
6757            "params": [
6758                {
6759                    "name": "fxn",
6760                    "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",
6761                    "type": "Function|Boolean"
6762                }
6763            ],
6764            "chainable": 1,
6765            "example": [
6766                "\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>"
6767            ],
6768            "alt": "no display.",
6769            "class": "p5.Element",
6770            "module": "DOM",
6771            "submodule": "DOM"
6772        },
6773        {
6774            "file": "src/core/p5.Element.js",
6775            "line": 406,
6776            "description": "<p>The .mouseClicked() function is called once after a mouse button is\npressed and released over the element. This can be used to\nattach element specific event listeners.</p>\n",
6777            "itemtype": "method",
6778            "name": "mouseClicked",
6779            "params": [
6780                {
6781                    "name": "fxn",
6782                    "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",
6783                    "type": "Function|Boolean"
6784                }
6785            ],
6786            "chainable": 1,
6787            "example": [
6788                "\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>"
6789            ],
6790            "alt": "no display.",
6791            "class": "p5.Element",
6792            "module": "DOM",
6793            "submodule": "DOM"
6794        },
6795        {
6796            "file": "src/core/p5.Element.js",
6797            "line": 460,
6798            "description": "<p>The .mouseMoved() 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",
6799            "itemtype": "method",
6800            "name": "mouseMoved",
6801            "params": [
6802                {
6803                    "name": "fxn",
6804                    "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",
6805                    "type": "Function|Boolean"
6806                }
6807            ],
6808            "chainable": 1,
6809            "example": [
6810                "\n<div class='norender'><code>\nvar cnv;\nvar d = 30;\nvar g;\nfunction setup() {\n  cnv = createCanvas(100, 100);
6810\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>"
6811            ],
6812            "alt": "no display.",
6813            "class": "p5.Element",
6814            "module": "DOM",
6815            "submodule": "DOM"
6816        },
6817        {
6818            "file": "src/core/p5.Element.js",
6819            "line": 519,
6820            "description": "<p>The .mouseOver() 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",
6821            "itemtype": "method",
6822            "name": "mouseOver",
6823            "params": [
6824                {
6825                    "name": "fxn",
6826                    "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",
6827                    "type": "Function|Boolean"
6828                }
6829            ],
6830            "chainable": 1,
6831            "example": [
6832                "\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>"
6833            ],
6834            "alt": "no display.",
6835            "class": "p5.Element",
6836            "module": "DOM",
6837            "submodule": "DOM"
6838        },
6839        {
6840            "file": "src/core/p5.Element.js",
6841            "line": 562,
6842            "description": "<p>The .changed() function is called when the value of an\nelement changes.\nThis can be used to attach an element specific event listener.</p>\n",
6843            "itemtype": "method",
6844            "name": "changed",
6845            "params": [
6846                {
6847                    "name": "fxn",
6848                    "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",
6849                    "type": "Function|Boolean"
6850                }
6851            ],
6852            "chainable": 1,
6853            "example": [
6854                "\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<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>"
6855            ],
6856            "alt": "dropdown: pear, kiwi, grape. When selected text \"its a\" + selection shown.",
6857            "class": "p5.Element",
6858            "module": "DOM",
6859            "submodule": "DOM"
6860        },
6861        {
6862            "file": "src/core/p5.Element.js",
6863            "line": 629,
6864            "description": "<p>The .input() 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\nsl
6864ider element. This can be used to attach an element specific\nevent listener.</p>\n",
6865            "itemtype": "method",
6866            "name": "input",
6867            "params": [
6868                {
6869                    "name": "fxn",
6870                    "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",
6871                    "type": "Function|Boolean"
6872                }
6873            ],
6874            "chainable": 1,
6875            "example": [
6876                "\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>"
6877            ],
6878            "alt": "no display.",
6879            "class": "p5.Element",
6880            "module": "DOM",
6881            "submodule": "DOM"
6882        },
6883        {
6884            "file": "src/core/p5.Element.js",
6885            "line": 664,
6886            "description": "<p>The .mouseOut() 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",
6887            "itemtype": "method",
6888            "name": "mouseOut",
6889            "params": [
6890                {
6891                    "name": "fxn",
6892                    "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",
6893                    "type": "Function|Boolean"
6894                }
6895            ],
6896            "chainable": 1,
6897            "example": [
6898                "\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>"
6899            ],
6900            "alt": "no display.",
6901            "class": "p5.Element",
6902            "module": "DOM",
6903            "submodule": "DOM"
6904        },
6905        {
6906            "file": "src/core/p5.Element.js",
6907            "line": 706,
6908            "description": "<p>The .touchStarted() function is called once after every time a touch is\nregistered. This can be used to attach element specific event listeners.</p>\n",
6909            "itemtype": "method",
6910            "name": "touchStarted",
6911            "params": [
6912                {
6913                    "name": "fxn",
6914                    "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",
6915                    "type": "Function|Boolean"
6916                }
6917            ],
6918            "chainable": 1,
6919            "example": [
6920                "\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>"
6921            ],
6922            "alt": "no display.",
6923            "class": "p5.Element",
6924            "module": "DOM",
6925            "submodule": "DOM"
6926        },
6927        {
6928            "file": "src/core/p5.Element.js",
6929            "line": 755,
6930            "description": "<p>The .touchMoved() function is called once after every time a touch move is\nregistered. This can be used to attach element specific event listeners.</p>\n",
6931            "itemtype": "method",
6932            "name": "touchMoved",
6933            "params": [
6934                {
6935                    "name": "fxn",
6936                    "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",
6937                    "type": "Function|Boolean"
6938                }
6939            ],
6940            "chainable": 1,
6941            "example": [
6942                "\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>"
6943            ],
6944            "alt": "no display.",
6945            "class": "p5.Element",
6946            "module": "DOM",
6947            "submodule": "DOM"
6948        },
6949        {
6950            "file": "src/core/p5.Element.js",
6951            "line": 796,
6952            "description": "<p>The .touchEnded() function is called once after every time a touch is\nregistered. This can be used to attach element specific event listeners.</p>\n",
6953            "itemtype": "method",
6954            "name": "touchEnded",
6955            "params": [
6956                {
6957                    "name": "fxn",
6958                    "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",
6959                    "type": "Function|Boolean"
6960                }
6961            ],
6962            "chainable": 1,
6963            "example": [
6964                "\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>"
6965            ],
6966            "alt": "no display.",
6967            "class": "p5.Element",
6968            "module": "DOM",
6969            "submodule": "DOM"
6970        },
6971        {
6972            "file": "src/core/p5.Element.js",
6973            "line": 846,
6974            "description": "<p>The .dragOver() 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",
6975            "itemtype": "method",
6976            "name": "dragOver",
6977            "params": [
6978                {
6979                    "name": "fxn",
6980                    "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",
6981                    "type": "Function|Boolean"
6982                }
6983            ],
6984            "chainable": 1,
6985            "example": [
6986                "\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>"
6987            ],
6988            "alt": "nothing displayed",
6989            "class": "p5.Element",
6990            "module": "DOM",
6991            "submodule": "DOM"
6992        },
6993        {
6994            "file": "src/core/p5.Element.js",
6995            "line": 884,
6996            "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",
6997            "itemtype": "method",
6998            "name": "dragLeave",
6999            "params": [
7000                {
7001                    "name": "fxn",
7002                    "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",
7003                    "type": "Function|Boolean"
7004                }
7005            ],
7006            "chainable": 1,
7007            "example": [
7008                "\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>"
7009            ],
7010            "alt": "nothing displayed",
7011            "class": "p5.Element",
7012            "module": "DOM",
7013            "submodule": "DOM"
7014        },
7015        {
7016            "file": "src/core/p5.Element.js",
7017            "line": 922,
7018            "description": "<p>The .drop() function is called for each file dropped on the element.\nIt requires a callback that is passed a p5.File object.  You can\noptionally pass two callbacks, the first one (required) is triggered\nfor each file dropped when the file is loaded.  The second (optional)\nis triggered just once when a file (or files) are dropped.</p>\n",
7019            "itemtype": "method",
7020            "name": "drop",
7021            "params": [
7022                {
7023                    "name": "callback",
7024                    "description": "<p>callback triggered when files are dropped.</p>\n",
7025                    "type": "Function"
7026                },
7027                {
7028                    "name": "fxn",
7029                    "description": "<p>callback to receive loaded file.</p>\n",
7030                    "type": "Function",
7031                    "optional": true
7032                }
7033            ],
7034            "chainable": 1,
7035            "example": [
7036                "\n<div><code>\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 gotFile(file) {\n  var img = createImg(file.data).hide();\n  // Draw the image onto the canvas\n  image(img, 0, 0, width, height);\n}\n</code></div>"
7037            ],
7038            "alt": "Canvas turns into whatever image is dragged/dropped onto it.",
7039            "class": "p5.Element",
7040            "module": "DOM",
7041            "submodule": "DOM"
7042        },
7043        {
7044            "file": "src/core/p5.Element.js",
7045            "line": 1057,
7046            "description": "<p>Helper fxn for sharing pixel methods</p>\n",
7047            "class": "p5.Element",
7048            "module": "DOM",
7049            "submodule": "DOM"
7050        },
7051        {
7052            "file": "src/core/p5.Graphics.js",
7053            "line": 65,
7054            "description": "<p>Removes a Graphics object from the page and frees any resources\nassociated with it.</p>\n",
7055            "itemtype": "method",
7056            "name": "remove",
7057            "example": [
7058                "\n<div class='norender'><code>\nvar 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>\nvar bg;\nfunction setup() {\n  pixelDensity(1);\n  createCanvas(100, 100);
7058\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  var 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  var 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>"
7059            ],
7060            "alt": "no image\na multi-colored circle moving back and forth over a scrolling background.",
7061            "class": "p5.Graphics",
7062            "module": "Rendering",
7063            "submodule": "Rendering"
7064        },
7065        {
7066            "file": "src/core/p5.Renderer.js",
7067            "line": 113,
7068            "description": "<p>Resize our canvas element.</p>\n",
7069            "class": "p5.Renderer",
7070            "module": "Rendering",
7071            "submodule": "Rendering"
7072        },
7073        {
7074            "file": "src/core/p5.Renderer.js",
7075            "line": 182,
7076            "description": "<p>Helper fxn to check font type (system or otf)</p>\n",
7077            "class": "p5.Renderer",
7078            "module": "Rendering",
7079            "submodule": "Rendering"
7080        },
7081        {
7082            "file": "src/core/p5.Renderer.js",
7083            "line": 235,
7084            "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",
7085            "class": "p5.Renderer",
7086            "module": "Rendering",
7087            "submodule": "Rendering"
7088        },
7089        {
7090            "file": "src/core/p5.Renderer2D.js",
7091            "line": 10,
7092            "description": "<p>p5.Renderer2D\nThe 2D graphics canvas renderer class.\nextends p5.Renderer</p>\n",
7093            "class": "p5",
7094            "module": "Rendering"
7095        },
7096        {
7097            "file": "src/core/p5.Renderer2D.js",
7098            "line": 395,
7099            "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",
7100            "class": "p5",
7101            "module": "Rendering"
7102        },
7103        {
7104            "file": "src/core/rendering.js",
7105            "line": 17,
7106            "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 createCanvas more than once in a sketch will result in very\nunpredictable behavior. If you want more than one drawing canvas\nyou could use createGraphics (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 createCanvas() 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",
7107            "itemtype": "method",
7108            "name": "createCanvas",
7109            "params": [
7110                {
7111                    "name": "w",
7112                    "description": "<p>width of the canvas</p>\n",
7113                    "type": "Number"
7114                },
7115                {
7116                    "name": "h",
7117                    "description": "<p>height of the canvas</p>\n",
7118                    "type": "Number"
7119                },
7120                {
7121                    "name": "renderer",
7122                    "description": "<p>either P2D or WEBGL</p>\n",
7123                    "type": "Constant",
7124                    "optional": true
7125                }
7126            ],
7127            "return": {
7128                "description": "",
7129                "type": "p5.Renderer"
7130            },
7131            "example": [
7132                "\n<div>\n<code>\nfunction setup() {\n  createCanvas(100, 50);\n  background(153);\n  line(0, 0, width, height);\n}\n</code>\n</div>"
7133            ],
7134            "alt": "Black line extending from top-left of canvas to bottom right.",
7135            "class": "p5",
7136            "module": "Rendering",
7137            "submodule": "Rendering"
7138        },
7139        {
7140            "file": "src/core/rendering.js",
7141            "line": 119,
7142            "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",
7143            "itemtype": "method",
7144            "name": "resizeCanvas",
7145            "params": [
7146                {
7147                    "name": "w",
7148                    "description": "<p>width of the canvas</p>\n",
7149                    "type": "Number"
7150                },
7151                {
7152                    "name": "h",
7153                    "description": "<p>height of the canvas</p>\n",
7154                    "type": "Number"
7155                },
7156                {
7157                    "name": "noRedraw",
7158                    "description": "<p>don&#39;t redraw the canvas immediately</p>\n",
7159                    "type": "Boolean",
7160                    "optional": true
7161                }
7162            ],
7163            "example": [
7164                "\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>"
7165            ],
7166            "alt": "No image displayed.",
7167            "class": "p5",
7168            "module": "Rendering",
7169            "submodule": "Rendering"
7170        },
7171        {
7172            "file": "src/core/rendering.js",
7173            "line": 172,
7174            "description": "<p>Removes the default canvas for a p5 sketch that doesn&#39;t\nrequire a canvas</p>\n",
7175            "itemtype": "method",
7176            "name": "noCanvas",
7177            "example": [
7178                "\n<div>\n<code>\nfunction setup() {\n  noCanvas();\n}\n</code>\n</div>"
7179            ],
7180            "alt": "no image displayed",
7181            "class": "p5",
7182            "module": "Rendering",
7183            "submodule": "Rendering"
7184        },
7185        {
7186            "file": "src/core/rendering.js",
7187            "line": 195,
7188            "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",
7189            "itemtype": "method",
7190            "name": "createGraphics",
7191            "params": [
7192                {
7193                    "name": "w",
7194                    "description": "<p>width of the offscreen graphics buffer</p>\n",
7195                    "type": "Number"
7196                },
7197                {
7198                    "name": "h",
7199                    "description": "<p>height of the offscreen graphics buffer</p>\n",
7200                    "type": "Number"
7201                },
7202                {
7203                    "name": "renderer",
7204                    "description": "<p>either P2D or WEBGL\nundefined defaults to p2d</p>\n",
7205                    "type": "Constant",
7206                    "optional": true
7207                }
7208            ],
7209            "return": {
7210                "description": "offscreen graphics buffer",
7211                "type": "p5.Graphics"
7212            },
7213            "example": [
7214                "\n<div>\n<code>\nvar 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>"
7215            ],
7216            "alt": "4 grey squares alternating light and dark grey. White quarter circle mid-left.",
7217            "class": "p5",
7218            "module": "Rendering",
7219            "submodule": "Rendering"
7220        },
7221        {
7222            "file": "src/core/rendering.js",
7223            "line": 234,
7224            "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;
7224t 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>",
7225            "itemtype": "method",
7226            "name": "blendMode",
7227            "params": [
7228                {
7229                    "name": "mode",
7230                    "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",
7231                    "type": "Constant"
7232                }
7233            ],
7234            "example": [
7235                "\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>"
7236            ],
7237            "alt": "translucent image thick red & blue diagonal rounded lines intersecting center\nThick red & blue diagonal rounded lines intersecting center. dark at overlap",
7238            "class": "p5",
7239            "module": "Rendering",
7240            "submodule": "Rendering"
7241        },
7242        {
7243            "file": "src/core/shim.js",
7244            "line": 70,
7245            "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",
7246            "class": "p5",
7247            "module": "Rendering"
7248        },
7249        {
7250            "file": "src/core/structure.js",
7251            "line": 15,
7252            "description": "<p>Stops p5.js from continuously executing the code within draw().\nIf loop() is called, the code in draw() begins to run continuously again.\nIf using noLoop() in setup(), it should be the last line inside the block.\n<br><br>\nWhen noLoop() is used, it&#39;s not possible to manipulate or access the\nscreen inside event handling functions such as mousePressed() or\nkeyPressed(). Instead, use those functions to call redraw() or loop(),\nwhich will run draw(), which can update the screen properly. This means\nthat when noLoop() has been called, no drawing can happen, and functions\nlike saveFrame() or loadPixels() may not be used.\n<br><br>\nNote that if the sketch is resized, redraw() will be called to update\nthe sketch, even after noLoop() has been specified. Otherwise, the sketch\nwould enter an odd state until loop() was called.</p>\n",
7253            "itemtype": "method",
7254            "name": "noLoop",
7255            "example": [
7256                "\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>\nvar 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>"
7257            ],
7258            "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.",
7259            "class": "p5",
7260            "module": "Structure",
7261            "submodule": "Structure"
7262        },
7263        {
7264            "file": "src/core/structure.js",
7265            "line": 77,
7266            "description": "<p>By default, p5.js loops through draw() continuously, executing the code\nwithin it. However, the draw() loop may be stopped by calling noLoop().\nIn that case, the draw() loop can be resumed with loop().</p>\n",
7267            "itemtype": "method",
7268            "name": "loop",
7269            "example": [
7270                "\n<div><code>\nvar 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>"
7271            ],
7272            "alt": "horizontal line moves slowly from left. Loops but stops on mouse press.",
7273            "class": "p5",
7274            "module": "Structure",
7275            "submodule": "Structure"
7276        },
7277        {
7278            "file": "src/core/structure.js",
7279            "line": 132,
7280            "description": "<p>The push() function saves the current drawing style settings and\ntransformations, while pop() 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 push(), it builds on the current style and transform\ninformation. The push() and pop() functions can be embedded to provide\nmore control. (See the second example for a demonstration.)\n<br><br>\npush() stores information related to the current transformation state\nand style settings controlled by the following functions: fill(),\nstroke(), tint(), strokeWeight(
7280), strokeCap(), strokeJoin(),\nimageMode(), rectMode(), ellipseMode(), colorMode(), textAlign(),\ntextFont(), textMode(), textSize(), textLeading().</p>\n",
7281            "itemtype": "method",
7282            "name": "push",
7283            "example": [
7284                "\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>"
7285            ],
7286            "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.",
7287            "class": "p5",
7288            "module": "Structure",
7289            "submodule": "Structure"
7290        },
7291        {
7292            "file": "src/core/structure.js",
7293            "line": 197,
7294            "description": "<p>The push() function saves the current drawing style settings and\ntransformations, while pop() 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 push(), it builds on the current style and transform\ninformation. The push() and pop() functions can be embedded to provide\nmore control. (See the second example for a demonstration.)\n<br><br>\npush() stores information related to the current transformation state\nand style settings controlled by the following functions: fill(),\nstroke(), tint(), strokeWeight(
7294), strokeCap(), strokeJoin(),\nimageMode(), rectMode(), ellipseMode(), colorMode(), textAlign(),\ntextFont(), textMode(), textSize(), textLeading().</p>\n",
7295            "itemtype": "method",
7296            "name": "pop",
7297            "example": [
7298                "\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>"
7299            ],
7300            "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.",
7301            "class": "p5",
7302            "module": "Structure",
7303            "submodule": "Structure"
7304        },
7305        {
7306            "file": "src/core/structure.js",
7307            "line": 271,
7308            "description": "<p>Executes the code within draw() one time. This functions allows the\n program to update the display window only when necessary, for example\n when an event registered by mousePressed() or keyPressed() occurs.\n <br><br>\n In structuring a program, it only makes sense to call redraw() within\n events such as mousePressed(). This is because redraw() does not run\n draw() immediately (it only sets a flag that indicates an update is\n needed).\n <br><br>\n The redraw() function does not work properly when called inside draw().\n To enable/disable animations, use loop() and noLoop().\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",
7309            "itemtype": "method",
7310            "name": "redraw",
7311            "params": [
7312                {
7313                    "name": "n",
7314                    "description": "<p>Redraw for n-times. The default value is 1.</p>\n",
7315                    "type": "Integer",
7316                    "optional": true
7317                }
7318            ],
7319            "example": [
7320                "\n <div><code>\n var 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 var 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>"
7321            ],
7322            "alt": "black line on far left of canvas\n black line on far left of canvas",
7323            "class": "p5",
7324            "module": "Structure",
7325            "submodule": "Structure"
7326        },
7327        {
7328            "file": "src/core/transform.js",
7329            "line": 13,
7330            "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 applyMatrix is called\"/></p>\n</blockquote>\n",
7331            "itemtype": "method",
7332            "name": "applyMatrix",
7333            "params": [
7334                {
7335                    "name": "a",
7336                    "description": "<p>numbers which define the 2x3 matrix to be multiplied</p>\n",
7337                    "type": "Number"
7338                },
7339                {
7340                    "name": "b",
7341                    "description": "<p>numbers which define the 2x3 matrix to be multiplied</p>\n",
7342                    "type": "Number"
7343                },
7344                {
7345                    "name": "c",
7346                    "description": "<p>numbers which define the 2x3 matrix to be multiplied</p>\n",
7347                    "type": "Number"
7348                },
7349                {
7350                    "name": "d",
7351                    "description": "<p>numbers which define the 2x3 matrix to be multiplied</p>\n",
7352                    "type": "Number"
7353                },
7354                {
7355                    "name": "e",
7356                    "description": "<p>numbers which define the 2x3 matrix to be multiplied</p>\n",
7357                    "type": "Number"
7358                },
7359                {
7360                    "name": "f",
7361                    "description": "<p>numbers which define the 2x3 matrix to be multiplied</p>\n",
7362                    "type": "Number"
7363                }
7364            ],
7365            "chainable": 1,
7366            "example": [
7367                "\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);
7367\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>"
7368            ],
7369            "alt": "A rectangle translating to the right\nA rectangle shrinking to the center\nA rectangle rotating clockwise about the center\nA rectangle shearing",
7370            "class": "p5",
7371            "module": "Transform",
7372            "submodule": "Transform"
7373        },
7374        {
7375            "file": "src/core/transform.js",
7376            "line": 135,
7377            "description": "<p>Replaces the current matrix with the identity matrix.</p>\n",
7378            "itemtype": "method",
7379            "name": "resetMatrix",
7380            "chainable": 1,
7381            "example": [
7382                "\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>"
7383            ],
7384            "alt": "A rotated retangle in the center with another at the top left corner",
7385            "class": "p5",
7386            "module": "Transform",
7387            "submodule": "Transform"
7388        },
7389        {
7390            "file": "src/core/transform.js",
7391            "line": 161,
7392            "description": "<p>Rotates a shape the amount specified by the angle parameter. This\nfunction accounts for angleMode, 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 draw() begins again.\n<br><br>\nTechnically, rotate() multiplies the current transformation matrix\nby a rotation matrix. This function can be further controlled by\nthe push() and pop().</p>\n",
7393            "itemtype": "method",
7394            "name": "rotate",
7395            "params": [
7396                {
7397                    "name": "angle",
7398                    "description": "<p>the angle of rotation, specified in radians\n                       or degrees, depending on current angleMode</p>\n",
7399                    "type": "Number"
7400                },
7401                {
7402                    "name": "axis",
7403                    "description": "<p>(in 3d) the axis to rotate around</p>\n",
7404                    "type": "p5.Vector|Number[]",
7405                    "optional": true
7406                }
7407            ],
7408            "chainable": 1,
7409            "example": [
7410                "\n<div>\n<code>\ntranslate(width / 2, height / 2);\nrotate(PI / 3.0);\nrect(-26, -26, 52, 52);\n</code>\n</div>"
7411            ],
7412            "alt": "white 52x52 rect with black outline at center rotated counter 45 degrees",
7413            "class": "p5",
7414            "module": "Transform",
7415            "submodule": "Transform"
7416        },
7417        {
7418            "file": "src/core/transform.js",
7419            "line": 201,
7420            "description": "<p>Rotates around X axis.</p>\n",
7421            "itemtype": "method",
7422            "name": "rotateX",
7423            "params": [
7424                {
7425                    "name": "angle",
7426                    "description": "<p>the angle of rotation, specified in radians\n                       or degrees, depending on current angleMode</p>\n",
7427                    "type": "Number"
7428                }
7429            ],
7430            "chainable": 1,
7431            "example": [
7432                "\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>"
7433            ],
7434            "alt": "3d box rotating around the x axis.",
7435            "class": "p5",
7436            "module": "Transform",
7437            "submodule": "Transform"
7438        },
7439        {
7440            "file": "src/core/transform.js",
7441            "line": 231,
7442            "description": "<p>
7442Rotates around Y axis.</p>\n",
7443            "itemtype": "method",
7444            "name": "rotateY",
7445            "params": [
7446                {
7447                    "name": "angle",
7448                    "description": "<p>the angle of rotation, specified in radians\n                       or degrees, depending on current angleMode</p>\n",
7449                    "type": "Number"
7450                }
7451            ],
7452            "chainable": 1,
7453            "example": [
7454                "\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>"
7455            ],
7456            "alt": "3d box rotating around the y axis.",
7457            "class": "p5",
7458            "module": "Transform",
7459            "submodule": "Transform"
7460        },
7461        {
7462            "file": "src/core/transform.js",
7463            "line": 261,
7464            "description": "<p>Rotates around Z axis. Webgl mode only.</p>\n",
7465            "itemtype": "method",
7466            "name": "rotateZ",
7467            "params": [
7468                {
7469                    "name": "angle",
7470                    "description": "<p>the angle of rotation, specified in radians\n                       or degrees, depending on current angleMode</p>\n",
7471                    "type": "Number"
7472                }
7473            ],
7474            "chainable": 1,
7475            "example": [
7476                "\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>"
7477            ],
7478            "alt": "3d box rotating around the z axis.",
7479            "class": "p5",
7480            "module": "Transform",
7481            "submodule": "Transform"
7482        },
7483        {
7484            "file": "src/core/transform.js",
7485            "line": 291,
7486            "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 scale() is called\nwithin draw(), 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 push() and pop().</p>\n",
7487            "itemtype": "method",
7488            "name": "scale",
7489            "chainable": 1,
7490            "example": [
7491                "\n<div>\n<code>\ntranslate(width / 2, height / 2);\nrotate(PI / 3.0);\nrect(-26, -26, 52, 52);\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>"
7492            ],
7493            "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",
7494            "class": "p5",
7495            "module": "Transform",
7496            "submodule": "Transform",
7497            "overloads": [
7498                {
7499                    "line": 291,
7500                    "params": [
7501                        {
7502                            "name": "s",
7503                            "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",
7504                            "type": "Number|p5.Vector|Number[]"
7505                        },
7506                        {
7507                            "name": "y",
7508                            "description": "<p>percent to scale the object in the y-axis</p>\n",
7509                            "type": "Number",
7510                            "optional": true
7511                        },
7512                        {
7513                            "name": "z",
7514                            "description": "<p>percent to scale the object in the z-axis (webgl only)</p>\n",
7515                            "type": "Number",
7516                            "optional": true
7517                        }
7518                    ],
7519                    "chainable": 1
7520                },
7521                {
7522                    "line": 336,
7523                    "params": [
7524                        {
7525                            "name": "scales",
7526                            "description": "<p>per-axis percents to scale the object</p>\n",
7527                            "type": "p5.Vector|Number[]"
7528                        }
7529                    ],
7530                    "chainable": 1
7531                }
7532            ]
7533        },
7534        {
7535            "file": "src/core/transform.js",
7536            "line": 366,
7537            "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 shearX() is called within the draw(), the transformation is reset when\nthe loop begins again.\n<br><br>\nTechnically, shearX() multiplies the current transformation matrix by a\nrotation matrix. This function can be further controlled by the\npush() and pop() functions.</p>\n",
7538            "itemtype": "method",
7539            "name": "shearX",
7540            "params": [
7541                {
7542                    "name": "angle",
7543                    "description": "<p>angle of shear specified in radians or degrees,\n                       depending on current angleMode</p>\n",
7544                    "type": "Number"
7545                }
7546            ],
7547            "chainable": 1,
7548            "example": [
7549                "\n<div>\n<code>\ntranslate(width / 4, height / 4);\nshearX(PI / 4.0);\nrect(0, 0, 30, 30);\n</code>\n</div>"
7550            ],
7551            "alt": "white irregular quadrilateral with black outline at top middle.",
7552            "class": "p5",
7553            "module": "Transform",
7554            "submodule": "Transform"
7555        },
7556        {
7557            "file": "src/core/transform.js",
7558            "line": 405,
7559            "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\nshearY() is called within the draw(), the transformation is reset when\nthe loop begins again.\n<br><br>\nTechnically, shearY() multiplies the current transformation matrix by a\nrotation matrix. This function can be further controlled by the\npush() and pop() functions.</p>\n",
7560            "itemtype": "method",
7561            "name": "shearY",
7562            "params": [
7563                {
7564                    "name": "angle",
7565                    "description": "<p>angle of shear specified in radians or degrees,\n                       depending on current angleMode</p>\n",
7566                    "type": "Number"
7567                }
7568            ],
7569            "chainable": 1,
7570            "example": [
7571                "\n<div>\n<code>\ntranslate(width / 4, height / 4);\nshearY(PI / 4.0);\nrect(0, 0, 30, 30);\n</code>\n</div>"
7572            ],
7573            "alt": "white irregular quadrilateral with black outline at middle bottom.",
7574            "class": "p5",
7575            "module": "Transform",
7576            "submodule": "Transform"
7577        },
7578        {
7579            "file": "src/core/transform.js",
7580            "line": 444,
7581            "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 translate() is called within draw(), the\ntransformation is reset when the loop begins again. This function can be\nfurther 
7581controlled by using push() and pop().</p>\n",
7582            "itemtype": "method",
7583            "name": "translate",
7584            "chainable": 1,
7585            "example": [
7586                "\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>"
7587            ],
7588            "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",
7589            "class": "p5",
7590            "module": "Transform",
7591            "submodule": "Transform",
7592            "overloads": [
7593                {
7594                    "line": 444,
7595                    "params": [
7596                        {
7597                            "name": "x",
7598                            "description": "<p>left/right translation</p>\n",
7599                            "type": "Number"
7600                        },
7601                        {
7602                            "name": "y",
7603                            "description": "<p>up/down translation</p>\n",
7604                            "type": "Number"
7605                        },
7606                        {
7607                            "name": "z",
7608                            "description": "<p>forward/backward translation (webgl only)</p>\n",
7609                            "type": "Number",
7610                            "optional": true
7611                        }
7612                    ],
7613                    "chainable": 1
7614                },
7615                {
7616                    "line": 498,
7617                    "params": [
7618                        {
7619                            "name": "vector",
7620                            "description": "<p>the vector to translate by</p>\n",
7621                            "type": "p5.Vector"
7622                        }
7623                    ],
7624                    "chainable": 1
7625                }
7626            ]
7627        },
7628        {
7629            "file": "src/core/vertex.js",
7630            "line": 22,
7631            "description": "<p>Use the beginContour() and endContour() functions to create negative\nshapes within shapes such as the center of the letter &#39;O&#39;. beginContour()\nbegins recording vertices for the shape and endContour() 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 beginShape()/endShape() pair and\ntransformations such as translate(), rotate(), and scale() do not work\nwithin a beginContour()/endContour() pair. It is also not possible to use\nother shapes, such as ellipse() or rect() within.</p>\n",
7632            "itemtype": "method",
7633            "name": "beginContour",
7634            "chainable": 1,
7635            "example": [
7636                "\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>"
7637            ],
7638            "alt": "white rect and smaller grey rect with red outlines in center of canvas.",
7639            "class": "p5",
7640            "module": "Shape",
7641            "submodule": "Vertex"
7642        },
7643        {
7644            "file": "src/core/vertex.js",
7645            "line": 70,
7646            "description": "<p>Using the beginShape() and endShape() functions allow creating more\ncomplex forms. beginShape() begins recording vertices for a shape and\nendShape() 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 beginShape() are POINTS, LINES, TRIANGLES,\nTRIANGLE_FAN, TRIANGLE_STRIP, QUADS, and QUAD_STRIP. After calling the\nbeginShape() function, a series of vertex() commands must follow. To stop\ndrawing the shape, call endShape(). Each shape will be outlined with the\ncurrent stroke color and filled with the fill color.\n<br><br>\nTransformations such as translate(), rotate(), and scale() do not work\nwithin beginShape(). It is also not possible to use other shapes, such as\nellipse() or rect() within beginShape().</p>\n",
7647            "itemtype": "method",
7648            "name": "beginShape",
7649            "params": [
7650                {
7651                    "name": "kind",
7652                    "description": "<p>either POINTS, LINES, TRIANGLES, TRIANGLE_FAN\n                               TRIANGLE_STRIP, QUADS, or QUAD_STRIP</p>\n",
7653                    "type": "Constant",
7654                    "optional": true
7655                }
7656            ],
7657            "chainable": 1,
7658            "example": [
7659                "\n<div>\n<code>\nbeginShape();\nvertex(30, 20);\nvertex(85, 20);
7659\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>"
7660            ],
7661            "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.",
7662            "class": "p5",
7663            "module": "Shape",
7664            "submodule": "Vertex"
7665        },
7666        {
7667            "file": "src/core/vertex.js",
7668            "line": 270,
7669            "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.\n<br><br>\nThe first time bezierVertex() is used within a\nbeginShape() call, it must be prefaced with a call to vertex()\nto set the first anchor point. This function must be used between\nbeginShape() and endShape() and only when there is no MODE\nparameter specified to beginShape().</p>\n",
7670            "itemtype": "method",
7671            "name": "bezierVertex",
7672            "params": [
7673                {
7674                    "name": "x2",
7675                    "description": "<p>x-coordinate for the first control point</p>\n",
7676                    "type": "Number"
7677                },
7678                {
7679                    "name": "y2",
7680                    "description": "<p>y-coordinate for the first control point</p>\n",
7681                    "type": "Number"
7682                },
7683                {
7684                    "name": "x3",
7685                    "description": "<p>x-coordinate for the second control point</p>\n",
7686                    "type": "Number"
7687                },
7688                {
7689                    "name": "y3",
7690                    "description": "<p>y-coordinate for the second control point</p>\n",
7691                    "type": "Number"
7692                },
7693                {
7694                    "name": "x4",
7695                    "description": "<p>
7695x-coordinate for the anchor point</p>\n",
7696                    "type": "Number"
7697                },
7698                {
7699                    "name": "y4",
7700                    "description": "<p>y-coordinate for the anchor point</p>\n",
7701                    "type": "Number"
7702                }
7703            ],
7704            "chainable": 1,
7705            "example": [
7706                "\n<div>\n<code>\nstrokeWeight(5);\npoint(30, 20);\npoint(80, 20);\npoint(80, 75);\npoint(30, 75);\n\nstrokeWeight(1);\nnoFill();\nbeginShape();\nvertex(30, 20);\nbezierVertex(80, 20, 80, 75, 30, 75);\nendShape();\n</code>\n</div>\n\n<div>\n<code>\nstrokeWeight(5);\npoint(30, 20);\npoint(80, 20);\npoint(80, 75);\npoint(30, 75);\n\nstroke(244, 122, 158);\npoint(50, 80);\npoint(60, 25);\npoint(30, 20);\n\nstroke(0);\nstrokeWeight(1);\nbeginShape();\nvertex(30, 20);\nbezierVertex(80, 20, 80, 75, 30, 75);\nbezierVertex(50, 80, 60, 25, 30, 20);\nendShape();\n</code>\n</div>"
7707            ],
7708            "alt": "crescent-shaped line in middle of canvas. Points facing left.\nwhite crescent shape in middle of canvas. Points facing left.",
7709            "class": "p5",
7710            "module": "Shape",
7711            "submodule": "Vertex"
7712        },
7713        {
7714            "file": "src/core/vertex.js",
7715            "line": 356,
7716            "description": "<p>Specifies vertex coordinates for curves. This function may only\nbe used between beginShape() and endShape() and only when there\nis no MODE parameter specified to beginShape().\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",
7717            "itemtype": "method",
7718            "name": "curveVertex",
7719            "params": [
7720                {
7721                    "name": "x",
7722                    "description": "<p>x-coordinate of the vertex</p>\n",
7723                    "type": "Number"
7724                },
7725                {
7726                    "name": "y",
7727                    "description": "<p>y-coordinate of the vertex</p>\n",
7728                    "type": "Number"
7729                }
7730            ],
7731            "chainable": 1,
7732            "example": [
7733                "\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);\ncurveVertex(68, 19);\ncurveVertex(21, 17);\ncurveVertex(32, 91);\ncurveVertex(32, 91);\nendShape();\n</code>\n</div>"
7734            ],
7735            "alt": "Upside-down u-shape line, mid canvas. left point extends beyond canvas view.",
7736            "class": "p5",
7737            "module": "Shape",
7738            "submodule": "Vertex"
7739        },
7740        {
7741            "file": "src/core/vertex.js",
7742            "line": 407,
7743            "description": "<p>Use the beginContour() and endContour() functions to create negative\nshapes within shapes such as the center of the letter &#39;O&#39;. beginContour()\nbegins recording vertices for the shape and endContour() 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 beginShape()/endShape() pair and\ntransformations such as translate(), rotate(), and scale() do not work\nwithin a beginContour()/endContour() pair. It is also not possible to use\nother shapes, such as ellipse() or rect() within.</p>\n",
7744            "itemtype": "method",
7745            "name": "endContour",
7746            "chainable": 1,
7747            "example": [
7748                "\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>"
7749            ],
7750            "alt": "white rect and smaller grey rect with red outlines in center of canvas.",
7751            "class": "p5",
7752            "module": "Shape",
7753            "submodule": "Vertex"
7754        },
7755        {
7756            "file": "src/core/vertex.js",
7757            "line": 467,
7758            "description": "<p>The endShape() function is the companion to beginShape() and may only be\ncalled after beginShape(). When endshape() is called, all of image data\ndefined since the previous call to beginShape() 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",
7759            "itemtype": "method",
7760            "name": "endShape",
7761            "params": [
7762                {
7763                    "name": "mode",
7764                    "description": "<p>use CLOSE to close the shape</p>\n",
7765                    "type": "Constant",
7766                    "optional": true
7767                }
7768            ],
7769            "chainable": 1,
7770            "example": [
7771                "\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>"
7772            ],
7773            "alt": "Triangle line shape with smallest interior angle on bottom and upside-
7773down L.",
7774            "class": "p5",
7775            "module": "Shape",
7776            "submodule": "Vertex"
7777        },
7778        {
7779            "file": "src/core/vertex.js",
7780            "line": 553,
7781            "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 beginShape() call, it\nmust be prefaced with a call to vertex() to set the first anchor point.\nThis function must be used between beginShape() and endShape() and only\nwhen there is no MODE parameter specified to beginShape().</p>\n",
7782            "itemtype": "method",
7783            "name": "quadraticVertex",
7784            "params": [
7785                {
7786                    "name": "cx",
7787                    "description": "<p>x-coordinate for the control point</p>\n",
7788                    "type": "Number"
7789                },
7790                {
7791                    "name": "cy",
7792                    "description": "<p>y-coordinate for the control point</p>\n",
7793                    "type": "Number"
7794                },
7795                {
7796                    "name": "x3",
7797                    "description": "<p>x-coordinate for the anchor point</p>\n",
7798                    "type": "Number"
7799                },
7800                {
7801                    "name": "y3",
7802                    "description": "<p>y-coordinate for the anchor point</p>\n",
7803                    "type": "Number"
7804                }
7805            ],
7806            "chainable": 1,
7807            "example": [
7808                "\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>"
7809            ],
7810            "alt": "arched-shaped black line with 4 pixel thick stroke weight.\nbackwards s-shaped black line with 4 pixel thick stroke weight.",
7811            "class": "p5",
7812            "module": "Shape",
7813            "submodule": "Vertex"
7814        },
7815        {
7816            "file": "src/core/vertex.js",
7817            "line": 645,
7818            "description": "<p>All shapes are constructed by connecting a series of vertices. vertex()\nis used to specify the vertex coordinates for points, lines, triangles,\nquads, and polygons. It is used exclusively within the beginShape() and\nendShape() functions.</p>\n",
7819            "itemtype": "method",
7820            "name": "vertex",
7821            "chainable": 1,
7822            "example": [
7823                "\n<div>\n<code>\nstrokeWeight(3);\nbeginShape(POINTS);\nvertex(30, 20);\nvertex(85, 20);\nvertex(85, 75);\nvertex(30, 75);\nendShape();\n</code>\n</div>"
7824            ],
7825            "alt": "8 points making 4 lines",
7826            "class": "p5",
7827            "module": "Shape",
7828            "submodule": "Vertex",
7829            "overloads": [
7830                {
7831                    "line": 645,
7832                    "params": [
7833                        {
7834                            "name": "x",
7835                            "description": "<p>x-coordinate of the vertex</p>\n",
7836                            "type": "Number"
7837                        },
7838                        {
7839                            "name": "y",
7840                            "description": "<p>y-coordinate of the vertex</p>\n",
7841                            "type": "Number"
7842                        }
7843                    ],
7844                    "chainable": 1
7845                },
7846                {
7847                    "line": 732,
7848                    "params": [
7849                        {
7850                            "name": "x",
7851                            "description": "",
7852                            "type": "Number"
7853                        },
7854                        {
7855                            "name": "y",
7856                            "description": "",
7857                            "type": "Number"
7858                        },
7859                        {
7860                            "name": "z",
7861                            "description": "<p>z-coordinate of the vertex</p>\n",
7862                            "type": "Number",
7863                            "optional": true
7864                        },
7865                        {
7866                            "name": "u",
7867                            "description": "<p>the vertex&#39;s texture u-coordinate</p>\n",
7868                            "type": "Number",
7869                            "optional": true
7870                        },
7871                        {
7872                            "name": "v",
7873                            "description": "<p>the vertex&#39;s texture v-coordinate</p>\n",
7874                            "type": "Number",
7875                            "optional": true
7876                        }
7877                    ]
7878                }
7879            ]
7880        },
7881        {
7882            "file": "src/data/p5.TypedDict.js",
7883            "line": 16,
7884            "description": "<p>Creates a new instance of p5.StringDict using the key, value pair\n or object you provide.</p>\n",
7885            "itemtype": "method",
7886            "name": "createStringDict",
7887            "return": {
7888                "description": "",
7889                "type": "p5.StringDict"
7890            },
7891            "example": [
7892                "\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 }\n </code></div>"
7893            ],
7894            "class": "p5",
7895            "module": "Data",
7896            "submodule": "Dictionary",
7897            "overloads": [
7898                {
7899                    "line": 16,
7900                    "params": [
7901                        {
7902                            "name": "key",
7903                            "description": "",
7904                            "type": "String"
7905                        },
7906                        {
7907                            "name": "value",
7908                            "description": "",
7909                            "type": "String"
7910                        }
7911                    ],
7912                    "return": {
7913                        "description": "",
7914                        "type": "p5.StringDict"
7915                    }
7916                },
7917                {
7918                    "line": 36,
7919                    "params": [
7920                        {
7921                            "name": "object",
7922                            "description": "<p>object</p>\n",
7923                            "type": "Object"
7924                        }
7925                    ],
7926                    "return": {
7927                        "description": "",
7928                        "type": "p5.StringDict"
7929                    }
7930                }
7931            ]
7932        },
7933        {
7934            "file": "src/data/p5.TypedDict.js",
7935            "line": 47,
7936            "description": "<p>Creates a new instance of p5.NumberDict using the key, value pair\n or object you provide.</p>\n",
7937            "itemtype": "method",
7938            "name": "createNumberDict",
7939            "return": {
7940                "description": "",
7941                "type": "p5.NumberDict"
7942            },
7943            "example": [
7944                "\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 }\n </code></div>"
7945            ],
7946            "class": "p5",
7947            "module": "Data",
7948            "submodule": "Dictionary",
7949            "overloads": [
7950                {
7951                    "line": 47,
7952                    "params": [
7953                        {
7954                            "name": "key",
7955                            "description": "",
7956                            "type": "Number"
7957                        },
7958                        {
7959                            "name": "value",
7960                            "description": "",
7961                            "type": "Number"
7962                        }
7963                    ],
7964                    "return": {
7965                        "description": "",
7966                        "type": "p5.NumberDict"
7967                    }
7968                },
7969                {
7970                    "line": 67,
7971                    "params": [
7972                        {
7973                            "name": "object",
7974                            "description": "<p>object</p>\n",
7975                            "type": "Object"
7976                        }
7977                    ],
7978                    "return": {
7979                        "description": "",
7980                        "type": "p5.NumberDict"
7981                    }
7982                }
7983            ]
7984        },
7985        {
7986            "file": "src/data/p5.TypedDict.js",
7987            "line": 97,
7988            "description": "<p>Returns the number of key-value pairs currently in Dictionary object</p>\n",
7989            "itemtype": "method",
7990            "name": "size",
7991            "return": {
7992                "description": "the number of key-value pairs in Dictionary object",
7993                "type": "Integer"
7994            },
7995            "example": [
7996                "\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()); // value of amt is 3\n}\n</code></div>\n"
7997            ],
7998            "class": "p5.TypedDict",
7999            "module": "Data",
8000            "submodule": "Dictionary"
8001        },
8002        {
8003            "file": "src/data/p5.TypedDict.js",
8004            "line": 119,
8005            "description": "<p>Returns true if key exists in Dictionary\notherwise returns false</p>\n",
8006            "itemtype": "method",
8007            "name": "hasKey",
8008            "params": [
8009                {
8010                    "name": "key",
8011                    "description": "<p>that you want to access</p>\n",
8012                    "type": "Number|String"
8013                }
8014            ],
8015            "return": {
8016                "description": "whether that key exists in Dictionary",
8017                "type": "Boolean"
8018            },
8019            "example": [
8020                "\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"
8021            ],
8022            "class": "p5.TypedDict",
8023            "module": "Data",
8024            "submodule": "Dictionary"
8025        },
8026        {
8027            "file": "src/data/p5.TypedDict.js",
8028            "line": 142,
8029            "description": "<p>Returns value stored at supplied key.</p>\n",
8030            "itemtype": "method",
8031            "name": "get",
8032            "params": [
8033                {
8034                    "name": "key",
8035                    "description": "<p>that you want to access</p>\n",
8036                    "type": "Number|String"
8037                }
8038            ],
8039            "return": {
8040                "description": "the value stored at that key",
8041                "type": "Number|String"
8042            },
8043            "example": [
8044                "\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"
8045            ],
8046            "class": "p5.TypedDict",
8047            "module": "Data",
8048            "submodule": "Dictionary"
8049        },
8050        {
8051            "file": "src/data/p5.TypedDict.js",
8052            "line": 169,
8053            "description": "<p>Changes the value of key if in it already exists in\nin the Dictionary otherwise makes a new key-value pair</p>\n",
8054            "itemtype": "method",
8055            "name": "set",
8056            "params": [
8057                {
8058                    "name": "key",
8059                    "description": "",
8060                    "type": "Number|String"
8061                },
8062                {
8063                    "name": "value",
8064                    "description": "",
8065                    "type": "Number|String"
8066                }
8067            ],
8068            "example": [
8069                "\n<div class=\"norender\">\n<code>\nfunction setup() {\n  var myDictionary = createStringDict('p5', 'js');\n  myDictionary.set('p5', 'JS');\n  myDictionary.print();\n  // above logs \"key: p5 - value: JS\" to console\n}\n</code></div>\n"
8070            ],
8071            "class": "p5.TypedDict",
8072            "module": "Data",
8073            "submodule": "Dictionary"
8074        },
8075        {
8076            "file": "src/data/p5.TypedDict.js",
8077            "line": 198,
8078            "description": "<p>private helper function to handle the user passing objects in\nduring construction or calls to create()</p>\n",
8079            "class": "p5.TypedDict",
8080            "module": "Data",
8081            "submodule": "Dictionary"
8082        },
8083        {
8084            "file": "src/data/p5.TypedDict.js",
8085            "line": 209,
8086            "description": "<p>Creates a key-value pair in the Dictionary</p>\n",
8087            "itemtype": "method",
8088            "name": "create",
8089            "example": [
8090                "\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>"
8091            ],
8092            "class": "p5.TypedDict",
8093            "module": "Data",
8094            "submodule": "Dictionary",
8095            "overloads": [
8096                {
8097                    "line": 209,
8098                    "params": [
8099                        {
8100                            "name": "key",
8101                            "description": "",
8102                            "type": "Number|String"
8103                        },
8104                        {
8105                            "name": "value",
8106                            "description": "",
8107                            "type": "Number|String"
8108                        }
8109                    ]
8110                },
8111                {
8112                    "line": 227,
8113                    "params": [
8114                        {
8115                            "name": "obj",
8116                            "description": "<p>key/value pair</p>\n",
8117                            "type": "Object"
8118                        }
8119                    ]
8120                }
8121            ]
8122        },
8123        {
8124            "file": "src/data/p5.TypedDict.js",
8125            "line": 245,
8126            "description": "<p>Empties Dictionary of all key-value pairs</p>\n",
8127            "itemtype": "method",
8128            "name": "clear",
8129            "example": [
8130                "\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>"
8131            ],
8132            "class": "p5.TypedDict",
8133            "module": "Data",
8134            "submodule": "Dictionary"
8135        },
8136        {
8137            "file": "src/data/p5.TypedDict.js",
8138            "line": 265,
8139            "description": "<p>Removes a key-value pair in the Dictionary</p>\n",
8140            "itemtype": "method",
8141            "name": "remove",
8142            "params": [
8143                {
8144                    "name": "key",
8145                    "description": "<p>for the pair to remove</p>\n",
8146                    "type": "Number|String"
8147                }
8148            ],
8149            "example": [
8150                "\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"
8151            ],
8152            "class": "p5.Typed
8152Dict",
8153            "module": "Data",
8154            "submodule": "Dictionary"
8155        },
8156        {
8157            "file": "src/data/p5.TypedDict.js",
8158            "line": 295,
8159            "description": "<p>Logs the list of items currently in the Dictionary to the console</p>\n",
8160            "itemtype": "method",
8161            "name": "print",
8162            "example": [
8163                "\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>"
8164            ],
8165            "class": "p5.TypedDict",
8166            "module": "Data",
8167            "submodule": "Dictionary"
8168        },
8169        {
8170            "file": "src/data/p5.TypedDict.js",
8171            "line": 319,
8172            "description": "<p>Converts the Dictionary into a CSV file for local\nstorage.</p>\n",
8173            "itemtype": "method",
8174            "name": "saveTable",
8175            "example": [
8176                "\n<div>\n<code>\ncreateButton('save')\n  .position(10, 10)\n  .mousePressed(function() {\n    createStringDict({\n      john: 1940,\n     paul: 1942,\n     george: 1943,\n     ringo: 1940\n    }).saveTable('beatles');\n  });\n</code>\n</div>"
8177            ],
8178            "class": "p5.TypedDict",
8179            "module": "Data",
8180            "submodule": "Dictionary"
8181        },
8182        {
8183            "file": "src/data/p5.TypedDict.js",
8184            "line": 352,
8185            "description": "<p>Converts the Dictionary into a JSON file for local\nstorage.</p>\n",
8186            "itemtype": "method",
8187            "name": "saveJSON",
8188            "example": [
8189                "\n<div>\n<code>\ncreateButton('save')\n  .position(10, 10)\n  .mousePressed(function() {\n    createStringDict({\n      john: 1940,\n     paul: 1942,\n     george: 1943,\n     ringo: 1940\n    }).saveJSON('beatles');\n  });\n</code>\n</div>"
8190            ],
8191            "class": "p5.TypedDict",
8192            "module": "Data",
8193            "submodule": "Dictionary"
8194        },
8195        {
8196            "file": "src/data/p5.TypedDict.js",
8197            "line": 378,
8198            "description": "<p>private helper function to ensure that the user passed in valid\nvalues for the Dictionary type</p>\n",
8199            "class": "p5.TypedDict",
8200            "module": "Data",
8201            "submodule": "Dictionary"
8202        },
8203        {
8204            "file": "src/data/p5.TypedDict.js",
8205            "line": 423,
8206            "description": "<p>private helper function to ensure that the user passed in valid\nvalues for the Dictionary type</p>\n",
8207            "class": "p5.NumberDict",
8208            "module": "Data",
8209            "submodule": "Dictionary"
8210        },
8211        {
8212            "file": "src/data/p5.TypedDict.js",
8213            "line": 432,
8214            "description": "<p>Add to a value stored at a certain key\nThe sum is stored in that location in the Dictionary.</p>\n",
8215            "itemtype": "method",
8216            "name": "add",
8217            "params": [
8218                {
8219                    "name": "Key",
8220                    "description": "<p>for value you wish to add to</p>\n",
8221                    "type": "Number"
8222                },
8223                {
8224                    "name": "Amount",
8225                    "description": "<p>to add to the value</p>\n",
8226                    "type": "Number"
8227                }
8228            ],
8229            "example": [
8230                "\n<div class='norender'>\n<code>\nfunction setup() {\n  var myDictionary = createNumberDict(2, 5);\n  myDictionary.add(2, 2);\n  console.log(myDictionary.get(2)); // logs 7 to console.\n}\n</code></div>\n\n"
8231            ],
8232            "class": "p5.NumberDict",
8233            "module": "Data",
8234            "submodule": "Dictionary"
8235        },
8236        {
8237            "file": "src/data/p5.TypedDict.js",
8238            "line": 460,
8239            "description": "<p>Subtract from a value stored at a certain key\nThe difference is stored in that location in the Dictionary.</p>\n",
8240            "itemtype": "method",
8241            "name": "sub",
8242            "params": [
8243                {
8244                    "name": "Key",
8245                    "description": "<p>
8245for value you wish to subtract from</p>\n",
8246                    "type": "Number"
8247                },
8248                {
8249                    "name": "Amount",
8250                    "description": "<p>to subtract from the value</p>\n",
8251                    "type": "Number"
8252                }
8253            ],
8254            "example": [
8255                "\n<div class='norender'>\n<code>\nfunction setup() {\n  var myDictionary = createNumberDict(2, 5);\n  myDictionary.sub(2, 2);\n  console.log(myDictionary.get(2)); // logs 3 to console.\n}\n</code></div>\n\n"
8256            ],
8257            "class": "p5.NumberDict",
8258            "module": "Data",
8259            "submodule": "Dictionary"
8260        },
8261        {
8262            "file": "src/data/p5.TypedDict.js",
8263            "line": 484,
8264            "description": "<p>Multiply a value stored at a certain key\nThe product is stored in that location in the Dictionary.</p>\n",
8265            "itemtype": "method",
8266            "name": "mult",
8267            "params": [
8268                {
8269                    "name": "Key",
8270                    "description": "<p>for value you wish to multiply</p>\n",
8271                    "type": "Number"
8272                },
8273                {
8274                    "name": "Amount",
8275                    "description": "<p>to multiply the value by</p>\n",
8276                    "type": "Number"
8277                }
8278            ],
8279            "example": [
8280                "\n<div class='norender'>\n<code>\nfunction setup() {\n  var myDictionary = createNumberDict(2, 4);\n  myDictionary.mult(2, 2);\n  console.log(myDictionary.get(2)); // logs 8 to console.\n}\n</code></div>\n\n"
8281            ],
8282            "class": "p5.NumberDict",
8283            "module": "Data",
8284            "submodule": "Dictionary"
8285        },
8286        {
8287            "file": "src/data/p5.TypedDict.js",
8288            "line": 512,
8289            "description": "<p>Divide a value stored at a certain key\nThe quotient is stored in that location in the Dictionary.</p>\n",
8290            "itemtype": "method",
8291            "name": "div",
8292            "params": [
8293                {
8294                    "name": "Key",
8295                    "description": "<p>for value you wish to divide</p>\n",
8296                    "type": "Number"
8297                },
8298                {
8299                    "name": "Amount",
8300                    "description": "<p>to divide the value by</p>\n",
8301                    "type": "Number"
8302                }
8303            ],
8304            "example": [
8305                "\n<div class='norender'>\n<code>\nfunction setup() {\n  var myDictionary = createNumberDict(2, 8);\n  myDictionary.div(2, 2);\n  console.log(myDictionary.get(2)); // logs 4 to console.\n}\n</code></div>\n\n"
8306            ],
8307            "class": "p5.NumberDict",
8308            "module": "Data",
8309            "submodule": "Dictionary"
8310        },
8311        {
8312            "file": "src/data/p5.TypedDict.js",
8313            "line": 540,
8314            "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",
8315            "class": "p5.NumberDict",
8316            "module": "Data",
8317            "submodule": "Dictionary"
8318        },
8319        {
8320            "file": "src/data/p5.TypedDict.js",
8321            "line": 563,
8322            "description": "<p>Return the lowest value.</p>\n",
8323            "itemtype": "method",
8324            "name": "minValue",
8325            "return": {
8326                "description": "",
8327                "type": "Number"
8328            },
8329            "example": [
8330                "\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"
8331            ],
8332            "class": "p5.NumberDict",
8333            "module": "Data",
8334            "submodule": "Dictionary"
8335        },
8336        {
8337            "file": "src/data/p5.TypedDict.js",
8338            "line": 584,
8339            "description": "<p>Return the highest value.</p>\n",
8340            "itemtype": "method",
8341            "name": "maxValue",
8342            "return": {
8343                "description": "",
8344                "type": "Number"
8345            },
8346            "example": [
8347                "\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"
8348            ],
8349            "class": "p5.NumberDict",
8350            "module": "Data",
8351            "submodule": "Dictionary"
8352        },
8353        {
8354            "file": "src/data/p5.TypedDict.js",
8355            "line": 605,
8356            "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",
8357            "class": "p5.NumberDict",
8358            "module": "Data",
8359            "submodule": "Dictionary"
8360        },
8361        {
8362            "file": "src/data/p5.TypedDict.js",
8363            "line": 628,
8364            "description": "<p>Return the lowest key.</p>\n",
8365            "itemtype": "method",
8366            "name": "minKey",
8367            "return": {
8368                "description": "",
8369                "type": "Number"
8370            },
8371            "example": [
8372                "\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"
8373            ],
8374            "class": "p5.NumberDict",
8375            "module": "Data",
8376            "submodule": "Dictionary"
8377        },
8378        {
8379            "file": "src/data/p5.TypedDict.js",
8380            "line": 649,
8381            "description": "<p>Return the highest key.</p>\n",
8382            "itemtype": "method",
8383            "name": "maxKey",
8384            "return": {
8385                "description": "",
8386                "type": "Number"
8387            },
8388            "example": [
8389                "\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"
8390            ],
8391            "class": "p5.NumberDict",
8392            "module": "Data",
8393            "submodule": "Dictionary"
8394        },
8395        {
8396            "file": "src/events/acceleration.js",
8397            "line": 12,
8398            "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;
8398\nor &#39;portrait&#39;. If no data is available it will be set to &#39;undefined&#39;.\neither LANDSCAPE or PORTRAIT.</p>\n",
8399            "itemtype": "property",
8400            "name": "deviceOrientation",
8401            "type": "Constant",
8402            "readonly": "",
8403            "class": "p5",
8404            "module": "Events",
8405            "submodule": "Acceleration"
8406        },
8407        {
8408            "file": "src/events/acceleration.js",
8409            "line": 23,
8410            "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",
8411            "itemtype": "property",
8412            "name": "accelerationX",
8413            "type": "Number",
8414            "readonly": "",
8415            "class": "p5",
8416            "module": "Events",
8417            "submodule": "Acceleration"
8418        },
8419        {
8420            "file": "src/events/acceleration.js",
8421            "line": 32,
8422            "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",
8423            "itemtype": "property",
8424            "name": "accelerationY",
8425            "type": "Number",
8426            "readonly": "",
8427            "class": "p5",
8428            "module": "Events",
8429            "submodule": "Acceleration"
8430        },
8431        {
8432            "file": "src/events/acceleration.js",
8433            "line": 41,
8434            "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",
8435            "itemtype": "property",
8436            "name": "accelerationZ",
8437            "type": "Number",
8438            "readonly": "",
8439            "class": "p5",
8440            "module": "Events",
8441            "submodule": "Acceleration"
8442        },
8443        {
8444            "file": "src/events/acceleration.js",
8445            "line": 50,
8446            "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",
8447            "itemtype": "property",
8448            "name": "pAccelerationX",
8449            "type": "Number",
8450            "readonly": "",
8451            "class": "p5",
8452            "module": "Events",
8453            "submodule": "Acceleration"
8454        },
8455        {
8456            "file": "src/events/acceleration.js",
8457            "line": 60,
8458            "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",
8459            "itemtype": "property",
8460            "name": "pAccelerationY",
8461            "type": "Number",
8462            "readonly": "",
8463            "class": "p5",
8464            "module": "Events",
8465            "submodule": "Acceleration"
8466        },
8467        {
8468            "file": "src/events/acceleration.js",
8469            "line": 70,
8470            "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",
8471            "itemtype": "property",
8472            "name": "pAccelerationZ",
8473            "type": "Number",
8474            "readonly": "",
8475            "class": "p5",
8476            "module": "Events",
8477            "submodule": "Acceleration"
8478        },
8479        {
8480            "file": "src/events/acceleration.js",
8481            "line": 91,
8482            "description": "<p>The system variable rotationX always contains the rotation of the\ndevice along the x axis. Value 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",
8483            "example": [
8484                "\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>"
8485            ],
8486            "itemtype": "property",
8487            "name": "rotationX",
8488            "type": "Number",
8489            "readonly": "",
8490            "alt": "red horizontal line right, green vertical line bottom. black background.",
8491            "class": "p5",
8492            "module": "Events",
8493            "submodule": "Acceleration"
8494        },
8495        {
8496            "file": "src/events/acceleration.js",
8497            "line": 125,
8498            "description": "<p>The system variable rotationY always contains the rotation of the\ndevice along the y axis. V
8498alue 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",
8499            "example": [
8500                "\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>"
8501            ],
8502            "itemtype": "property",
8503            "name": "rotationY",
8504            "type": "Number",
8505            "readonly": "",
8506            "alt": "red horizontal line right, green vertical line bottom. black background.",
8507            "class": "p5",
8508            "module": "Events",
8509            "submodule": "Acceleration"
8510        },
8511        {
8512            "file": "src/events/acceleration.js",
8513            "line": 158,
8514            "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",
8515            "example": [
8516                "\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>"
8517            ],
8518            "itemtype": "property",
8519            "name": "rotationZ",
8520            "type": "Number",
8521            "readonly": "",
8522            "alt": "red horizontal line right, green vertical line bottom. black background.",
8523            "class": "p5",
8524            "module": "Events",
8525            "submodule": "Acceleration"
8526        },
8527        {
8528            "file": "src/events/acceleration.js",
8529            "line": 194,
8530            "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",
8531            "example": [
8532                "\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.\nvar 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\nvar rX = rotationX + 180;\nvar 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>"
8533            ],
8534            "alt": "no image to display.",
8535            "itemtype": "property",
8536            "name": "pRotationX",
8537            "type": "Number",
8538            "readonly": "",
8539            "class": "p5",
8540            "module": "Events",
8541            "submodule": "Acceleration"
8542        },
8543        {
8544            "file": "src/events/acceleration.js",
8545            "line": 239,
8546            "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",
8547            "example": [
8548                "\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.\nvar 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\nvar rY = rotationY + 180;\nvar 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>"
8549            ],
8550            "alt": "no image to display.",
8551            "itemtype": "property",
8552            "name": "pRotationY",
8553            "type": "Number",
8554            "readonly": "",
8555            "class": "p5",
8556            "module": "Events",
8557            "submodule": "Acceleration"
8558        },
8559        {
8560            "file": "src/events/acceleration.js",
8561            "line": 283,
8562            "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",
8563            "example": [
8564                "\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.\nvar 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>"
8565            ],
8566            "alt": "no image to display.",
8567            "itemtype": "property",
8568            "name": "pRotationZ",
8569            "type": "Number",
8570            "readonly": "",
8571            "class": "p5",
8572            "module": "Events",
8573            "submodule": "Acceleration"
8574        },
8575        {
8576            "file": "src/events/acceleration.js",
8577            "line": 341,
8578            "itemtype": "property",
8579            "name": "turnAxis",
8580            "type": "String",
8581            "readonly": "",
8582            "class": "p5",
8583            "module": "Events",
8584            "submodule": "Acceleration"
8585        },
8586        {
8587            "file": "src/events/acceleration.js",
8588            "line": 350,
8589            "description": "<p>The setMoveThreshold() function is used to set the movement threshold for\nthe deviceMoved() function. The default threshold is set to 0.5.</p>\n",
8590            "itemtype": "method",
8591            "name": "setMoveThreshold",
8592            "params": [
8593                {
8594                    "name": "value",
8595                    "description": "<p>The threshold value</p>\n",
8596                    "type": "Number"
8597                }
8598            ],
8599            "class": "p5",
8600            "module": "Events",
8601            "submodule": "Acceleration"
8602        },
8603        {
8604            "file": "src/events/acceleration.js",
8605            "line": 362,
8606            "description": "<p>The setShakeThreshold() function is used to set the movement threshold for\nthe deviceShaken() function. The default threshold is set to 30.</p>\n",
8607            "itemtype": "method",
8608            "name": "setShakeThreshold",
8609            "params": [
8610                {
8611                    "name": "value",
8612                    "description": "<p>The threshold value</p>\n",
8613                    "type": "Number"
8614                }
8615            ],
8616            "class": "p5",
8617            "module": "Events",
8618            "submodule": "Acceleration"
8619        },
8620        {
8621            "file": "src/events/acceleration.js",
8622            "line": 374,
8623            "description": "<p>The deviceMoved() 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\n0.5.</p>\n",
8624            "itemtype": "method",
8625            "name": "deviceMoved",
8626            "example": [
8627                "\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\nvar value = 0;\nfunction draw() {\n  fill(value);\n  rect(25, 25, 50, 50);\n}
8627\nfunction deviceMoved() {\n  value = value + 5;\n  if (value > 255) {\n    value = 0;\n  }\n}\n</code>\n</div>"
8628            ],
8629            "alt": "50x50 black rect in center of canvas. turns white on mobile when device moves",
8630            "class": "p5",
8631            "module": "Events",
8632            "submodule": "Acceleration"
8633        },
8634        {
8635            "file": "src/events/acceleration.js",
8636            "line": 405,
8637            "description": "<p>The deviceTurned() function is called when the device rotates by\nmore than 90 degrees continuously.\n<br><br>\nThe axis that triggers the deviceTurned() method is stored in the turnAxis\nvariable. The deviceTurned() 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",
8638            "itemtype": "method",
8639            "name": "deviceTurned",
8640            "example": [
8641                "\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\nvar value = 0;\nfunction draw() {\n  fill(value);\n  rect(25, 25, 50, 50);\n}\nfunction deviceTurned() {\n  if (value === 0) {\n    value = 255;\n  } 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\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    } else if (value === 255) {\n      value = 0;\n    }\n  }\n}\n</code>\n</div>"
8642            ],
8643            "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",
8644            "class": "p5",
8645            "module": "Events",
8646            "submodule": "Acceleration"
8647        },
8648        {
8649            "file": "src/events/acceleration.js",
8650            "line": 464,
8651            "description": "<p>The deviceShaken() 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.</p>\n",
8652            "itemtype": "method",
8653            "name": "deviceShaken",
8654            "example": [
8655                "\n<div class=\"norender\">\n<code>\n// Run this example on a mobile device\n// Shake the device to change the value.\n\nvar 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>"
8656            ],
8657            "alt": "50x50 black rect in center of canvas. turns white on mobile when device shakes",
8658            "class": "p5",
8659            "module": "Events",
8660            "submodule": "Acceleration"
8661        },
8662        {
8663            "file": "src/events/keyboard.js",
8664            "line": 18,
8665            "description": "<p>The boolean system variable keyIsPressed is true if any key is pressed\nand false if no keys are pressed.</p>\n",
8666            "itemtype": "property",
8667            "name": "keyIsPressed",
8668            "type": "Boolean",
8669            "readonly": "",
8670            "example": [
8671                "\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>"
8672            ],
8673            "alt": "50x50 white rect that turns black on keypress.",
8674            "class": "p5",
8675            "module": "Events",
8676            "submodule": "Keyboard"
8677        },
8678        {
8679            "file": "src/events/keyboard.js",
8680            "line": 45,
8681            "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 keyTyped(). For non-ASCII keys, use the keyCode\nvariable.</p>\n",
8682            "itemtype": "property",
8683            "name": "key",
8684            "type": "String",
8685            "readonly": "",
8686            "example": [
8687                "\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>"
8688            ],
8689            "alt": "canvas displays any key value that is pressed in pink font.",
8690            "class": "p5",
8691            "module": "Events",
8692            "submodule": "Keyboard"
8693        },
8694        {
8695            "file": "src/events/keyboard.js",
8696            "line": 74,
8697            "description": "<p>The variable keyCode is used to detect special keys such as BACKSPACE,\nDELETE, ENTE
8697R, 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",
8698            "itemtype": "property",
8699            "name": "keyCode",
8700            "type": "Integer",
8701            "readonly": "",
8702            "example": [
8703                "\n<div><code>\nvar 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>"
8704            ],
8705            "alt": "Grey rect center. turns white when up arrow pressed and black when down",
8706            "class": "p5",
8707            "module": "Events",
8708            "submodule": "Keyboard"
8709        },
8710        {
8711            "file": "src/events/keyboard.js",
8712            "line": 107,
8713            "description": "<p>The keyPressed() function is called once every time a key is pressed. The\nkeyCode for the key that was pressed is stored in the keyCode variable.\n<br><br>\nFor non-ASCII keys, use the keyCode variable. You can check if the keyCode\nequals BACKSPACE, DELETE, ENTER, RETURN, TAB, ESCAPE, SHIFT, CONTROL,\nOPTION, ALT, UP_ARROW, DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW.\n<br><br>\nFor ASCII keys 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 keyTyped() 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 keyTyped() (and keyReleased() 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",
8714            "itemtype": "method",
8715            "name": "keyPressed",
8716            "example": [
8717                "\n<div>\n<code>\nvar 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>\nvar 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>"
8718            ],
8719            "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.",
8720            "class": "p5",
8721            "module": "Events",
8722            "submodule": "Keyboard"
8723        },
8724        {
8725            "file": "src/events/keyboard.js",
8726            "line": 198,
8727            "description": "<p>The keyReleased() function is called once every time a key is released.\nSee key and keyCode 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",
8728            "itemtype": "method",
8729            "name": "keyReleased",
8730            "example": [
8731                "\n<div>\n<code>\nvar 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>"
8732            ],
8733            "alt": "black rect center. turns white when key pressed and black when pressed again",
8734            "class": "p5",
8735            "module": "Events",
8736            "submodule": "Keyboard"
8737        },
8738        {
8739            "file": "src/events/keyboard.js",
8740            "line": 254,
8741            "description": "<p>The keyTyped() 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 keyTyped() (and keyReleased() 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",
8742            "itemtype": "method",
8743            "name": "keyTyped",
8744            "example": [
8745                "\n<div>\n<code>\nvar 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>"
8746            ],
8747            "alt": "black rect center. turns white when 'a' key typed and black when 'b' pressed",
8748            "class": "p5",
8749            "module": "Events",
8750            "submodule": "Keyboard"
8751        },
8752        {
8753            "file": "src/events/keyboard.js",
8754            "line": 308,
8755            "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",
8756            "class": "p5",
8757            "module": "Events",
8758            "submodule": "Keyboard"
8759        },
8760        {
8761            "file": "src/events/keyboard.js",
8762            "line": 318,
8763            "description": "<p>The keyIsDown() 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 keyCode names listed\n<a href=\"http://p5js.org/reference/#p5/keyCode\">here</a>.</p>\n",
8764            "itemtype": "method",
8765            "name": "keyIsDown",
8766            "params": [
8767                {
8768                    "name": "code",
8769                    "description": "<p>The key to check for.</p>\n",
8770                    "type": "Number"
8771                }
8772            ],
8773            "return": {
8774                "description": "whether key is down or not",
8775                "type": "Boolean"
8776            },
8777            "example": [
8778                "\n<div><code>\nvar x = 100;\nvar 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>"
8779            ],
8780            "alt": "50x50 red ellipse moves left, right, up and down with arrow presses.",
8781            "class": "p5",
8782            "module": "Events",
8783            "submodule": "Keyboard"
8784        },
8785        {
8786            "file": "src/events/mouse.js",
8787            "line": 22,
8788            "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, mou
8788seX will hold the x value of the most\nrecent touch point.</p>\n",
8789            "itemtype": "property",
8790            "name": "mouseX",
8791            "type": "Number",
8792            "readonly": "",
8793            "example": [
8794                "\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>"
8795            ],
8796            "alt": "horizontal black line moves left and right with mouse x-position",
8797            "class": "p5",
8798            "module": "Events",
8799            "submodule": "Mouse"
8800        },
8801        {
8802            "file": "src/events/mouse.js",
8803            "line": 48,
8804            "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",
8805            "itemtype": "property",
8806            "name": "mouseY",
8807            "type": "Number",
8808            "readonly": "",
8809            "example": [
8810                "\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>"
8811            ],
8812            "alt": "vertical black line moves up and down with mouse y-position",
8813            "class": "p5",
8814            "module": "Events",
8815            "submodule": "Mouse"
8816        },
8817        {
8818            "file": "src/events/mouse.js",
8819            "line": 74,
8820            "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.</p>\n",
8821            "itemtype": "property",
8822            "name": "pmouseX",
8823            "type": "Number",
8824            "readonly": "",
8825            "example": [
8826                "\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>"
8827            ],
8828            "alt": "line trail is created from cursor movements. faster movement make longer line.",
8829            "class": "p5",
8830            "module": "Events",
8831            "submodule": "Mouse"
8832        },
8833        {
8834            "file": "src/events/mouse.js",
8835            "line": 105,
8836            "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.</p>\n",
8837            "itemtype": "property",
8838            "name": "pmouseY",
8839            "type": "Number",
8840            "readonly": "",
8841            "example": [
8842                "\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>"
8843            ],
8844            "alt": "60x60 black rect center, fuschia background. rect flickers on mouse movement",
8845            "class": "p5",
8846            "module": "Events",
8847            "submodule": "Mouse"
8848        },
8849        {
8850            "file": "src/events/mouse.js",
8851            "line": 135,
8852            "description": "<p>The system variable winMouseX always contains the current horizontal\nposition of the mouse, relative to (0, 0) of the window.</p>\n",
8853            "itemtype": "property",
8854            "name": "winMouseX",
8855            "type": "Number",
8856            "readonly": "",
8857            "example": [
8858                "\n<div>\n<code>\nvar 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>"
8859            ],
8860            "alt": "60x60 black rect y moves with mouse y and fuschia canvas moves with mouse x",
8861            "class": "p5",
8862            "module": "Events",
8863            "submodule": "Mouse"
8864        },
8865        {
8866            "file": "src/events/mouse.js",
8867            "line": 172,
8868            "description": "<p>The system variable winMouseY always contains the current vertical\nposition of the mouse, relative to (0, 0) of the window.</p>\n",
8869            "itemtype": "property",
8870            "name": "winMouseY",
8871            "type": "Number",
8872            "readonly": "",
8873            "example": [
8874                "\n<div>\n<code>\nvar 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 
8874+ 1);\n\n  //the x of the square is relative to the canvas\n  rect(mouseX, 20, 60, 60);\n}\n</code>\n</div>"
8875            ],
8876            "alt": "60x60 black rect x moves with mouse x and fuschia canvas y moves with mouse y",
8877            "class": "p5",
8878            "module": "Events",
8879            "submodule": "Mouse"
8880        },
8881        {
8882            "file": "src/events/mouse.js",
8883            "line": 209,
8884            "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.</p>\n",
8885            "itemtype": "property",
8886            "name": "pwinMouseX",
8887            "type": "Number",
8888            "readonly": "",
8889            "example": [
8890                "\n<div>\n<code>\nvar 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  var 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>"
8891            ],
8892            "alt": "fuschia ellipse moves with mouse x and y. Grows and shrinks with mouse speed",
8893            "class": "p5",
8894            "module": "Events",
8895            "submodule": "Mouse"
8896        },
8897        {
8898            "file": "src/events/mouse.js",
8899            "line": 249,
8900            "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.</p>\n",
8901            "itemtype": "property",
8902            "name": "pwinMouseY",
8903            "type": "Number",
8904            "readonly": "",
8905            "example": [
8906                "\n<div>\n<code>\nvar 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  var 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>"
8907            ],
8908            "alt": "fuschia ellipse moves with mouse x and y. Grows and shrinks with mouse speed",
8909            "class": "p5",
8910            "module": "Events",
8911            "submodule": "Mouse"
8912        },
8913        {
8914            "file": "src/events/mouse.js",
8915            "line": 290,
8916            "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",
8917            "itemtype": "property",
8918            "name": "mouseButton",
8919            "type": "Constant",
8920            "readonly": "",
8921            "example": [
8922                "\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>"
8923            ],
8924            "alt": "50x50 black ellipse appears on center of fuschia canvas on mouse click/press.",
8925            "class": "p5",
8926            "module": "Events",
8927            "submodule": "Mouse"
8928        },
8929        {
8930            "file": "src/events/mouse.js",
8931            "line": 329,
8932            "description": "<p>The boolean system variable mouseIsPressed is true if the mouse is pressed\nand false if not.</p>\n",
8933            "itemtype": "property",
8934            "name": "mouseIsPressed",
8935            "type": "Boolean",
8936            "readonly": "",
8937            "example": [
8938                "\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>"
8939            ],
8940            "alt": "black 50x50 rect becomes ellipse with mouse click/press. fuschia background.",
8941            "class": "p5",
8942            "module": "Events",
8943            "submodule": "Mouse"
8944        },
8945        {
8946            "file": "src/events/mouse.js",
8947            "line": 418,
8948            "description": "<p>The mouseMoved() 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",
8949            "itemtype": "method",
8950            "name": "mouseMoved",
8951            "example": [
8952                "\n<div>\n<code>\n// Move the mouse across the page\n// to change its value\n\nvar 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>"
8953            ],
8954            "alt": "black 50x50 rect becomes lighter with mouse movements until white then resets\nno image displayed",
8955            "class": "p5",
8956            "module": "Events",
8957            "submodule": "Mouse"
8958        },
8959        {
8960            "file": "src/events/mouse.js",
8961            "line": 462,
8962            "description": "<p>The mouseDragged() function is called once every time the mouse moves and\na mouse button is pressed. If no mouseDragged() function is defined, the\ntouchMoved() 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",
8963            "itemtype": "method",
8964            "name": "mouseDragged",
8965            "example": [
8966                "\n<div>\n<code>\n// Drag the mouse across the page\n// to change its value\n\nvar 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>"
8967            ],
8968            "alt": "black 50x50 rect turns lighter with mouse click and drag until white, resets\nno image displayed",
8969            "class": "p5",
8970            "module": "Events",
8971            "submodule": "Mouse"
8972        },
8973        {
8974            "file": "src/events/mouse.js",
8975            "line": 532,
8976            "description": "<p>The mousePressed() 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\nmousePressed() function is defined, the touchStarted() 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",
8977            "itemtype": "method",
8978            "name": "mousePressed",
8979            "example": [
8980                "\n<div>\n<code>\n// Click within the image to change\n// the value of the rectangle\n\nvar 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>"
8981            ],
8982            "alt": "black 50x50 rect turns white with mouse click/press.\nno image displayed",
8983            "class": "p5",
8984            "module": "Events",
8985            "submodule": "Mouse"
8986        },
8987        {
8988            "file": "src/events/mouse.js",
8989            "line": 598,
8990            "description": "<p>The mouseReleased() function is called every time a mouse button is\nreleased. If no mouseReleased() function is defined, the touchEnded()\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",
8991            "itemtype": "method",
8992            "name": "mouseReleased",
8993            "example": [
8994                "\n<div>\n<code>\n// Click within the image to change\n// the value of the rectangle\n/
8994/ after the mouse has been clicked\n\nvar 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>"
8995            ],
8996            "alt": "black 50x50 rect turns white with mouse click/press.\nno image displayed",
8997            "class": "p5",
8998            "module": "Events",
8999            "submodule": "Mouse"
9000        },
9001        {
9002            "file": "src/events/mouse.js",
9003            "line": 665,
9004            "description": "<p>The mouseClicked() 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 mousePressed() or mouseReleased().<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",
9005            "itemtype": "method",
9006            "name": "mouseClicked",
9007            "example": [
9008                "\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\nvar 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>"
9009            ],
9010            "alt": "black 50x50 rect turns white with mouse click/press.\nno image displayed",
9011            "class": "p5",
9012            "module": "Events",
9013            "submodule": "Mouse"
9014        },
9015        {
9016            "file": "src/events/mouse.js",
9017            "line": 724,
9018            "description": "<p>The doubleClicked() 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",
9019            "itemtype": "method",
9020            "name": "doubleClicked",
9021            "example": [
9022                "\n<div>\n<code>\n// Click within the image to change\n// the value of the rectangle\n// after the mouse has been double clicked\n\nvar 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>"
9023            ],
9024            "alt": "black 50x50 rect turns white with mouse doubleClick/press.\nno image displayed",
9025            "class": "p5",
9026            "module": "Events",
9027            "submodule": "Mouse"
9028        },
9029        {
9030            "file": "src/events/mouse.js",
9031            "line": 782,
9032            "description": "<p>The function mouseWheel() 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",
9033            "itemtype": "method",
9034            "name": "mouseWheel",
9035            "example": [
9036                "\n<div>\n<code>\nvar 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>"
9037            ],
9038            "alt": "black 50x50 rect moves up and down with vertical scroll. fuschia background",
9039            "class": "p5",
9040            "module": "Events",
9041            "submodule": "Mouse"
9042        },
9043        {
9044            "file": "src/events/touch.js",
9045            "line": 12,
9046            "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",
9047            "itemtype": "property",
9048            "name": "touches",
9049            "type": "Object[]",
9050            "readonly": "",
9051            "class": "p5",
9052            "module": "Events",
9053            "submodule": "Touch"
9054        },
9055        {
9056            "file": "src/events/touch.js",
9057            "line": 57,
9058            "description": "<p>The touchStarted() function is called once after every time a touch is\nregistered. If no touchStarted() function is defined, the mousePressed()\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",
9059            "itemtype": "method",
9060            "name": "touchStarted",
9061            "example": [
9062                "\n<div>\n<code>\n// Touch within the image to change\n// the value of the rectangle\n\nvar value = 0;\nfunction draw() {\n  fill(value);\n  rect(25, 25, 50, 50);\n}\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>"
9063            ],
9064            "alt": "50x50 black rect turns white with touch event.\nno image displayed",
9065            "class": "p5",
9066            "module": "Events",
9067            "submodule": "Touch"
9068        },
9069        {
9070            "file": "src/events/touch.js",
9071            "line": 120,
9072            "description": "<p>The touchMoved() function is called every time a touch move is registered.\nIf no touchMoved() function is defined, the mouseDragged() 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",
9073            "itemtype": "method",
9074            "name": "touchMoved",
9075            "example": [
9076                "\n<div>\n<code>\n// Move your finger across the page\n// to change its value\n\nvar 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>"
9077            ],
9078            "alt": "50x50 black rect turns lighter with touch until white. resets\nno image displayed",
9079            "class": "p5",
9080            "module": "Events",
9081            "submodule": "Touch"
9082        },
9083        {
9084            "file": "src/events/touch.js",
9085            "line": 182,
9086            "description": "<p>The touchEnded() function is called every time a touch ends. If no\ntouchEnded() function is defined, the mouseReleased() 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",
9087            "itemtype": "method",
9088            "name": "touchEnded",
9089            "example": [
9090                "\n<div>\n<code>\n// Release touch within the image to\n// change the value of the rectangle\n\nvar 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>"
9091            ],
9092            "alt": "50x50 black rect turns white with touch.\nno image displayed",
9093            "class": "p5",
9094            "module": "Events",
9095            "submodule": "Touch"
9096        },
9097        {
9098            "file": "src/image/filters.js",
9099            "line": 3,
9100            "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",
9101            "class": "p5",
9102            "module": "Events"
9103        },
9104        {
9105            "file": "src/image/image.js",
9106            "line": 8,
9107            "description": "<p>This module defines the p5 methods for the p5.Image class\nfor drawing images to the main display canvas.</p>\n",
9108            "class": "p5",
9109            "module": "Image",
9110            "submodule": "Image"
9111        },
9112        {
9113            "file": "src/image/image.js",
9114            "line": 18,
9115            "description": "<p>Creates a new p5.Image (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.pixels 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 pixelDensity) of the display window x4,\nrepresenting the R, G, B, A values in order for each pixel, mov
9115ing from\nleft to right across each row, then down each column. See .pixels for\nmore info. It may also be simpler to use set() or get().\n<br><br>\nBefore accessing the pixels of an image, the data must loaded with the\nloadPixels() function. After the array data has been modified, the\nupdatePixels() function must be run to update the changes.</p>\n",
9116            "itemtype": "method",
9117            "name": "createImage",
9118            "params": [
9119                {
9120                    "name": "width",
9121                    "description": "<p>width in pixels</p>\n",
9122                    "type": "Integer"
9123                },
9124                {
9125                    "name": "height",
9126                    "description": "<p>height in pixels</p>\n",
9127                    "type": "Integer"
9128                }
9129            ],
9130            "return": {
9131                "description": "the p5.Image object",
9132                "type": "p5.Image"
9133            },
9134            "example": [
9135                "\n<div>\n<code>\nvar img = createImage(66, 66);\nimg.loadPixels();\nfor (var i = 0; i < img.width; i++) {\n  for (var 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>\nvar img = createImage(66, 66);\nimg.loadPixels();\nfor (var i = 0; i < img.width; i++) {\n  for (var 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>\nvar pink = color(255, 102, 204);\nvar img = createImage(66, 66);\nimg.loadPixels();\nvar d = pixelDensity();\nvar halfImage = 4 * (width * d) * (height / 2 * d);\nfor (var 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>"
9136            ],
9137            "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",
9138            "class": "p5",
9139            "module": "Image",
9140            "submodule": "Image"
9141        },
9142        {
9143            "file": "src/image/image.js",
9144            "line": 98,
9145            "description": "<p>Save the current canvas as an image. In Safari, this will open the\nimage in the window and the user must provide their own\nfilename on save-as. Other browsers will either save the\nfile immediately, or prompt the user with a dialogue window.</p>\n",
9146            "itemtype": "method",
9147            "name": "saveCanvas",
9148            "example": [
9149                "\n <div class='norender notest'><code>\n function setup() {\n var 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 var 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>"
9150            ],
9151            "alt": "no image displayed\n no image displayed\n no image displayed",
9152            "class": "p5",
9153            "module": "Image",
9154            "submodule": "Image",
9155            "overloads": [
9156                {
9157                    "line": 98,
9158                    "params": [
9159                        {
9160                            "name": "selectedCanvas",
9161                            "description": "<p>a variable\n                                representing a specific html5 canvas (optional)</p>\n",
9162                            "type": "p5.Element|HTMLCanvasElement"
9163                        },
9164                        {
9165                            "name": "filename",
9166                            "description": "",
9167                            "type": "String",
9168                            "optional": true
9169                        },
9170                        {
9171                            "name": "extension",
9172                            "description": "<p>&#39;jpg&#39; or &#39;png&#39;</p>\n",
9173                            "type": "String",
9174                            "optional": true
9175                        }
9176                    ]
9177                },
9178                {
9179                    "line": 142,
9180                    "params": [
9181                        {
9182                            "name": "filename",
9183                            "description": "",
9184                            "type": "String",
9185                            "optional": true
9186                        },
9187                        {
9188                            "name": "extension",
9189                            "description": "",
9190                            "type": "String",
9191                            "optional": true
9192                        }
9193                    ]
9194                }
9195            ]
9196        },
9197        {
9198            "file": "src/image/image.js",
9199            "line": 193,
9200            "description": "<p>Capture a sequence of frames that can be used to create a movie.\nAccepts a callback. For example, you may wish to 
9200send 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 saveFrames() 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",
9201            "itemtype": "method",
9202            "name": "saveFrames",
9203            "params": [
9204                {
9205                    "name": "filename",
9206                    "description": "",
9207                    "type": "String"
9208                },
9209                {
9210                    "name": "extension",
9211                    "description": "<p>&#39;jpg&#39; or &#39;png&#39;</p>\n",
9212                    "type": "String"
9213                },
9214                {
9215                    "name": "duration",
9216                    "description": "<p>Duration in seconds to save the frames for.</p>\n",
9217                    "type": "Number"
9218                },
9219                {
9220                    "name": "framerate",
9221                    "description": "<p>Framerate to save the frames in.</p>\n",
9222                    "type": "Number"
9223                },
9224                {
9225                    "name": "callback",
9226                    "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",
9227                    "type": "Function(Array)",
9228                    "optional": true
9229                }
9230            ],
9231            "example": [
9232                "\n<div><code>\n function draw() {\n background(mouseX);\n }\n\n function mousePressed() {\n saveFrames('out', 'png', 1, 25, function(data) {\n   print(data);\n });\n }\n</code></div>"
9233            ],
9234            "alt": "canvas background goes from light to dark with mouse x.",
9235            "class": "p5",
9236            "module": "Image",
9237            "submodule": "Image"
9238        },
9239        {
9240            "file": "src/image/loading_displaying.js",
9241            "line": 17,
9242            "description": "<p>Loads an image from a path and creates a p5.Image 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 loadImage() call in preload().\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",
9243            "itemtype": "method",
9244            "name": "loadImage",
9245            "params": [
9246                {
9247                    "name": "path",
9248                    "description": "<p>Path of the image to be loaded</p>\n",
9249                    "type": "String"
9250                },
9251                {
9252                    "name": "successCallback",
9253                    "description": "<p>Function to be called once\n                               the image is loaded. Will be passed the\n                               p5.Image.</p>\n",
9254                    "type": "function(p5.Image)",
9255                    "optional": true
9256                },
9257                {
9258                    "name": "failureCallback",
9259                    "description": "<p>called with event error if\n                               the image fails to load.</p>\n",
9260                    "type": "Function(Event)",
9261                    "optional": true
9262                }
9263            ],
9264            "return": {
9265                "description": "the p5.Image object",
9266                "type": "p5.Image"
9267            },
9268            "example": [
9269                "\n<div>\n<code>\nvar 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', function(img) {\n    image(img, 0, 0);\n  });\n}\n</code>\n</div>"
9270            ],
9271            "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",
9272            "class": "p5",
9273            "module": "Image",
9274            "submodule": "Loading & Displaying"
9275        },
9276        {
9277            "file": "src/image/loading_displaying.js",
9278            "line": 125,
9279            "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 
9279y—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",
9280            "itemtype": "method",
9281            "name": "image",
9282            "example": [
9283                "\n<div>\n<code>\nvar 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>\nvar 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', function(img) {\n    image(img, 0, 0);\n  });\n}\n</code>\n</div>\n<div>\n<code>\nvar 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>"
9284            ],
9285            "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",
9286            "class": "p5",
9287            "module": "Image",
9288            "submodule": "Loading & Displaying",
9289            "overloads": [
9290                {
9291                    "line": 125,
9292                    "params": [
9293                        {
9294                            "name": "img",
9295                            "description": "<p>the image to display</p>\n",
9296                            "type": "p5.Image|p5.Element"
9297                        },
9298                        {
9299                            "name": "x",
9300                            "description": "<p>the x-coordinate of the top-left corner of the image</p>\n",
9301                            "type": "Number"
9302                        },
9303                        {
9304                            "name": "y",
9305                            "description": "<p>the y-coordinate of the top-left corner of the image</p>\n",
9306                            "type": "Number"
9307                        },
9308                        {
9309                            "name": "width",
9310                            "description": "<p>the width to draw the image</p>\n",
9311                            "type": "Number",
9312                            "optional": true
9313                        },
9314                        {
9315                            "name": "height",
9316                            "description": "<p>the height to draw the image</p>\n",
9317                            "type": "Number",
9318                            "optional": true
9319                        }
9320                    ]
9321                },
9322                {
9323                    "line": 213,
9324                    "params": [
9325                        {
9326                            "name": "img",
9327                            "description": "",
9328                            "type": "p5.Image|p5.Element"
9329                        },
9330                        {
9331                            "name": "dx",
9332                            "description": "<p>the x-coordinate of the destination\n                          rectangle in which to draw the source image</p>\n",
9333                            "type": "Number"
9334                        },
9335                        {
9336                            "name": "dy",
9337                            "description": "<p>the y-coordinate of the destination\n                          rectangle in which to draw the source image</p>\n",
9338                            "type": "Number"
9339                        },
9340                        {
9341                            "name": "dWidth",
9342                            "description": "<p>the width of the destination rectangle</p>\n",
9343                            "type": "Number"
9344                        },
9345                        {
9346                            "name": "dHeight",
9347                            "description": "<p>the height of the destination rectangle</p>\n",
9348                            "type": "Number"
9349                        },
9350                        {
9351                            "name": "sx",
9352                            "description": "<p>the x-coordinate of the subsection of the source\nimage to draw into the destination rectangle</p>\n",
9353                            "type": "Number"
9354                        },
9355                        {
9356                            "name": "sy",
9357                            "description": "<p>the y-coordinate of the subsection of the source\nimage to draw into the destination rectangle</p>\n",
9358                            "type": "Number"
9359                        },
9360                        {
9361                            "name": "sWidth",
9362                            "description": "<p>the width of the subsection of the\n                          source image to draw into the destination\n                          rectangle</p>\n",
9363                            "type": "Number",
9364                            "optional": true
9365                        },
9366                        {
9367                            "name": "sHeight",
9368                            "description": "<p>the height of the subsection of the\n                           source image to draw into the destination rectangle</p>\n",
9369                            "type": "Number",
9370                            "optional": true
9371                        }
9372                    ]
9373                }
9374            ]
9375        },
9376        {
9377            "file": "src/image/loading_displaying.js",
9378            "line": 296,
9379            "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 colorMode()).\n<br><br>\nThe value for the gray parameter must be less than or equal to the current\nmaximum value as specified by colorMode(). The default maximum value is\n255.</p>\n",
9380            "itemtype": "method",
9381            "name": "tint",
9382            "example": [
9383                "\n<div>\n<code>\nvar 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>\nvar 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>\nvar 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>"
9384            ],
9385            "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",
9386            "class": "p5",
9387            "module": "Image",
9388            "submodule": "Loading & Displaying",
9389            "overloads": [
9390                {
9391                    "line": 296,
9392                    "params": [
9393                        {
9394                            "name": "v1",
9395                            "description": "<p>red or hue value relative to\n                                the current color range</p>\n",
9396                            "type": "Number"
9397                        },
9398                        {
9399                            "name": "v2",
9400                            "description": "<p>
9400green or saturation value\n                                relative to the current color range</p>\n",
9401                            "type": "Number"
9402                        },
9403                        {
9404                            "name": "v3",
9405                            "description": "<p>blue or brightness value\n                                relative to the current color range</p>\n",
9406                            "type": "Number"
9407                        },
9408                        {
9409                            "name": "alpha",
9410                            "description": "",
9411                            "type": "Number",
9412                            "optional": true
9413                        }
9414                    ]
9415                },
9416                {
9417                    "line": 369,
9418                    "params": [
9419                        {
9420                            "name": "value",
9421                            "description": "<p>a color string</p>\n",
9422                            "type": "String"
9423                        }
9424                    ]
9425                },
9426                {
9427                    "line": 374,
9428                    "params": [
9429                        {
9430                            "name": "gray",
9431                            "description": "<p>a gray value</p>\n",
9432                            "type": "Number"
9433                        },
9434                        {
9435                            "name": "alpha",
9436                            "description": "",
9437                            "type": "Number",
9438                            "optional": true
9439                        }
9440                    ]
9441                },
9442                {
9443                    "line": 380,
9444                    "params": [
9445                        {
9446                            "name": "values",
9447                            "description": "<p>an array containing the red,green,blue &amp;\n                                and alpha components of the color</p>\n",
9448                            "type": "Number[]"
9449                        }
9450                    ]
9451                },
9452                {
9453                    "line": 386,
9454                    "params": [
9455                        {
9456                            "name": "color",
9457                            "description": "<p>the tint color</p>\n",
9458                            "type": "p5.Color"
9459                        }
9460                    ]
9461                }
9462            ]
9463        },
9464        {
9465            "file": "src/image/loading_displaying.js",
9466            "line": 396,
9467            "description": "<p>Removes the current fill value for displaying images and reverts to\ndisplaying images with their original hues.</p>\n",
9468            "itemtype": "method",
9469            "name": "noTint",
9470            "example": [
9471                "\n<div>\n<code>\nvar 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>"
9472            ],
9473            "alt": "2 side by side images of bricks, left image with blue tint",
9474            "class": "p5",
9475            "module": "Image",
9476            "submodule": "Loading & Displaying"
9477        },
9478        {
9479            "file": "src/image/loading_displaying.js",
9480            "line": 462,
9481            "description": "<p>Set image mode. Modifies the location from which images are drawn by\nchanging the way in which parameters given to image() are interpreted.\nThe default mode is imageMode(CORNER), which interprets the second and\nthird parameters of image() 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 image()\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 image()\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",
9482            "itemtype": "method",
9483            "name": "imageMode",
9484            "params": [
9485                {
9486                    "name": "mode",
9487                    "description": "<p>either CORNER, CORNERS, or CENTER</p>\n",
9488                    "type": "Constant"
9489                }
9490            ],
9491            "example": [
9492                "\n\n<div>\n<code>\nvar img;\nfunction preload() {\n  img = loadImage('assets/bricks.jpg');\n}\nfunction setup() {\n  imageMode(CORNER);
9492\n  image(img, 10, 10, 50, 50);\n}\n</code>\n</div>\n\n<div>\n<code>\nvar 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>\nvar 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>"
9493            ],
9494            "alt": "small square image of bricks\nhorizontal rectangle image of bricks\nlarge square image of bricks",
9495            "class": "p5",
9496            "module": "Image",
9497            "submodule": "Loading & Displaying"
9498        },
9499        {
9500            "file": "src/image/p5.Image.js",
9501            "line": 9,
9502            "description": "<p>This module defines the p5.Image class and P5 methods for\ndrawing images to the main display canvas.</p>\n",
9503            "class": "p5.Image",
9504            "module": "Image",
9505            "submodule": "Image"
9506        },
9507        {
9508            "file": "src/image/p5.Image.js",
9509            "line": 90,
9510            "description": "<p>Image width.</p>\n",
9511            "itemtype": "property",
9512            "name": "width",
9513            "type": "Number",
9514            "readonly": "",
9515            "example": [
9516                "\n<div><code>\nvar img;\nfunction preload() {\n  img = loadImage('assets/rockies.jpg');\n}\n\nfunction setup() {\n  createCanvas(100, 100);\n  image(img, 0, 0);\n  for (var i = 0; i < img.width; i++) {\n    var c = img.get(i, img.height / 2);\n    stroke(c);\n    line(i, height / 2, i, height);\n  }\n}\n</code></div>"
9517            ],
9518            "alt": "rocky mountains in top and horizontal lines in corresponding colors in bottom.",
9519            "class": "p5.Image",
9520            "module": "Image",
9521            "submodule": "Image"
9522        },
9523        {
9524            "file": "src/image/p5.Image.js",
9525            "line": 117,
9526            "description": "<p>Image height.</p>\n",
9527            "itemtype": "property",
9528            "name": "height",
9529            "type": "Number",
9530            "readonly": "",
9531            "example": [
9532                "\n<div><code>\nvar img;\nfunction preload() {\n  img = loadImage('assets/rockies.jpg');\n}\n\nfunction setup() {\n  createCanvas(100, 100);\n  image(img, 0, 0);\n  for (var i = 0; i < img.height; i++) {\n    var c = img.get(img.width / 2, i);\n    stroke(c);\n    line(0, i, width / 2, i);\n  }\n}\n</code></div>"
9533            ],
9534            "alt": "rocky mountains on right and vertical lines in corresponding colors on left.",
9535            "class": "p5.Image",
9536            "module": "Image",
9537            "submodule": "Image"
9538        },
9539        {
9540            "file": "src/image/p5.Image.js",
9541            "line": 151,
9542            "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\">var d = pixelDensity();\nfor (var i = 0; i &lt; d; i++) {\n  for (var j = 0; j &lt; d; j++) {\n    // loop over\n    idx = 4 * ((y * d + j) * width * d + (x * d + i
9542));\n    pixels[idx] = r;\n    pixels[idx+1] = g;\n    pixels[idx+2] = b;\n    pixels[idx+3] = a;\n  }\n}\n</code></pre>\n<p><br><br>\nBefore accessing this array, the data must loaded with the loadPixels()\nfunction. After the array data has been modified, the updatePixels()\nfunction must be run to update the changes.</p>\n",
9543            "itemtype": "property",
9544            "name": "pixels",
9545            "type": "Number[]",
9546            "example": [
9547                "\n<div>\n<code>\nvar img = createImage(66, 66);\nimg.loadPixels();\nfor (var i = 0; i < img.width; i++) {\n  for (var 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>\nvar pink = color(255, 102, 204);\nvar img = createImage(66, 66);\nimg.loadPixels();\nfor (var 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>"
9548            ],
9549            "alt": "66x66 turquoise rect in center of canvas\n66x66 pink rect in center of canvas",
9550            "class": "p5.Image",
9551            "module": "Image",
9552            "submodule": "Image"
9553        },
9554        {
9555            "file": "src/image/p5.Image.js",
9556            "line": 221,
9557            "description": "<p>Helper fxn for sharing pixel methods</p>\n",
9558            "class": "p5.Image",
9559            "module": "Image",
9560            "submodule": "Image"
9561        },
9562        {
9563            "file": "src/image/p5.Image.js",
9564            "line": 230,
9565            "description": "<p>Loads the pixels data for this image into the [pixels] attribute.</p>\n",
9566            "itemtype": "method",
9567            "name": "loadPixels",
9568            "example": [
9569                "\n<div><code>\nvar myImage;\nvar 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 (var 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>"
9570            ],
9571            "alt": "2 images of rocky mountains vertically stacked",
9572            "class": "p5.Image",
9573            "module": "Image",
9574            "submodule": "Image"
9575        },
9576        {
9577            "file": "src/image/p5.Image.js",
9578            "line": 266,
9579            "description": "<p>Updates the backing canvas for this image with the contents of\nthe [pixels] array.</p>\n",
9580            "itemtype": "method",
9581            "name": "updatePixels",
9582            "example": [
9583                "\n<div><code>\nvar myImage;\nvar 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 (var 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>"
9584            ],
9585            "alt": "2 images of rocky mountains vertically stacked",
9586            "class": "p5.Image",
9587            "module": "Image",
9588            "submodule": "Image",
9589            "overloads": [
9590                {
9591                    "line": 266,
9592                    "params": [
9593                        {
9594                            "name": "x",
9595                            "description": "<p>x-offset of the target update area for the\n                             underlying canvas</p>\n",
9596                            "type": "Integer"
9597                        },
9598                        {
9599                            "name": "y",
9600                            "description": "<p>y-offset of the target update area for the\n                             underlying canvas</p>\n",
9601                            "type": "Integer"
9602                        },
9603                        {
9604                            "name": "w",
9605                            "description": "<p>height of the target update area for the\n                             underlying canvas</p>\n",
9606                            "type": "Integer"
9607                        },
9608                        {
9609                            "name": "h",
9610                            "description": "<p>height of the target update area for the\n                             underlying canvas</p>\n",
9611                            "type": "Integer"
9612                        }
9613                    ]
9614                },
9615                {
9616                    "line": 306,
9617                    "params": []
9618                }
9619            ]
9620        },
9621        {
9622            "file": "src/image/p5.Image.js",
9623            "line": 314,
9624            "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 p5.Image\nis returned.</p>\n<p>Returns undefined if the region is outside the bounds of the image</p>\n",
9625            "itemtype": "method",
9626            "name": "get",
9627            "params": [
9628                {
9629                    "name": "x",
9630                    "description": "<p>x-coordinate of the pixel</p>\n",
9631                    "type": "Number",
9632                    "optional": true
9633                },
9634                {
9635                    "name": "y",
9636                    "description": "<p>y-coordinate of the pixel</p>\n",
9637                    "type": "Number",
9638                    "optional": true
9639                },
9640                {
9641                    "name": "w",
9642                    "description": "<p>width</p>\n",
9643                    "type": "Number",
9644                    "optional": true
9645                },
9646                {
9647                    "name": "h",
9648                    "description": "<p>height</p>\n",
9649                    "type": "Number",
9650                    "optional": true
9651                }
9652            ],
9653            "return": {
9654                "description": "color of pixel at x,y in array format\n                                   [R, G, B, A] or p5.Image",
9655                "type": "Number[]|Color|p5.Image"
9656            },
9657            "example": [
9658                "\n<div><code>\nvar myImage;\nvar 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>"
9659            ],
9660            "alt": "image of rocky mountains with 50x50 green rect in front",
9661            "class": "p5.Image",
9662            "module": "Image",
9663            "submodule": "Image"
9664        },
9665        {
9666            "file": "src/image/p5.Image.js",
9667            "line": 359,
9668            "description": "<p>Set the color of a single pixel or write an image into\nthis p5.Image.</p>\n<p>Note that for a large number of pixels this will\nbe slower than directly manipulating the pixels array\nand then calling updatePixels().</p>\n",
9669            "itemtype": "method",
9670            "name": "set",
9671            "params": [
9672                {
9673                    "name": "x",
9674                    "description": "<p>x-coordinate of the pixel</p>\n",
9675                    "type": "Number"
9676                },
9677                {
9678                    "name": "y",
9679                    "description": "<p>y-coordinate of the pixel</p>\n",
9680                    "type": "Number"
9681                },
9682                {
9683                    "name": "a",
9684                    "description": "<p>grayscale value | pixel array |\n                               a p5.Color | image to copy</p>\n",
9685                    "type": "Number|Number[]|Object"
9686                }
9687            ],
9688            "example": [
9689                "\n<div>\n<code>\nvar img = createImage(66, 66);\nimg.loadPixels();\nfor (var i = 0; i < img.width;
9689 i++) {\n  for (var 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>"
9690            ],
9691            "alt": "2 gradated dark turquoise rects fade left. 1 center 1 bottom right of canvas",
9692            "class": "p5.Image",
9693            "module": "Image",
9694            "submodule": "Image"
9695        },
9696        {
9697            "file": "src/image/p5.Image.js",
9698            "line": 397,
9699            "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",
9700            "itemtype": "method",
9701            "name": "resize",
9702            "params": [
9703                {
9704                    "name": "width",
9705                    "description": "<p>the resized image width</p>\n",
9706                    "type": "Number"
9707                },
9708                {
9709                    "name": "height",
9710                    "description": "<p>the resized image height</p>\n",
9711                    "type": "Number"
9712                }
9713            ],
9714            "example": [
9715                "\n<div><code>\nvar 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>"
9716            ],
9717            "alt": "image of rocky mountains. zoomed in",
9718            "class": "p5.Image",
9719            "module": "Image",
9720            "submodule": "Image"
9721        },
9722        {
9723            "file": "src/image/p5.Image.js",
9724            "line": 481,
9725            "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",
9726            "itemtype": "method",
9727            "name": "copy",
9728            "example": [
9729                "\n<div><code>\nvar photo;\nvar bricks;\nvar x;\nvar 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>"
9730            ],
9731            "alt": "image of rocky mountains and smaller image on top of bricks at top left",
9732            "class": "p5.Image",
9733            "module": "Image",
9734            "submodule": "Image",
9735            "overloads": [
9736                {
9737                    "line": 481,
9738                    "params": [
9739                        {
9740                            "name": "srcImage",
9741                            "description": "<p>source image</p>\n",
9742                            "type": "p5.Image|p5.Element"
9743                        },
9744                        {
9745                            "name": "sx",
9746                            "description": "<p>X coordinate of the source&#39;s upper left corner</p>\n",
9747                            "type": "Integer"
9748                        },
9749                        {
9750                            "name": "sy",
9751                            "description": "<p>Y coordinate of the source&#39;s upper left corner</p>\n",
9752                            "type": "Integer"
9753                        },
9754                        {
9755                            "name": "sw",
9756                            "description": "<p>source image width</p>\n",
9757                            "type": "Integer"
9758                        },
9759                        {
9760                            "name": "sh",
9761                            "description": "<p>source image height</p>\n",
9762                            "type": "Integer"
9763                        },
9764                        {
9765                            "name": "dx",
9766                            "description": "<p>X coordinate of the destination&#39;s upper left corner</p>\n",
9767                            "type": "Integer"
9768                        },
9769                        {
9770                            "name": "dy",
9771                            "description": "<p>Y coordinate of the destination&#39;s upper left corner</p>\n",
9772                            "type": "Integer"
9773                        },
9774                        {
9775                            "name": "dw",
9776                            "description": "<p>destination image width</p>\n",
9777                            "type": "Integer"
9778                        },
9779                        {
9780                            "name": "dh",
9781                            "description": "<p>destination image height</p>\n",
9782                            "type": "Integer"
9783                        }
9784                    ]
9785                },
9786                {
9787                    "line": 522,
9788                    "params": [
9789                        {
9790                            "name": "sx",
9791                            "description": "",
9792                            "type": "Integer"
9793                        },
9794                        {
9795                            "name": "sy",
9796                            "description": "",
9797                            "type": "Integer"
9798                        },
9799                        {
9800                            "name": "sw",
9801                            "description": "",
9802                            "type": "Integer"
9803                        },
9804                        {
9805                            "name": "sh",
9806                            "description": "",
9807                            "type": "Integer"
9808                        },
9809                        {
9810                            "name": "dx",
9811                            "description": "",
9812                            "type": "Integer"
9813                        },
9814                        {
9815                            "name": "dy",
9816                            "description": "",
9817                            "type": "Integer"
9818                        },
9819                        {
9820                            "name": "dw",
9821                            "description": "",
9822                            "type": "Integer"
9823                        },
9824                        {
9825                            "name": "dh",
9826                            "description": "",
9827                            "type": "Integer"
9828                        }
9829                    ]
9830                }
9831            ]
9832        },
9833        {
9834            "file": "src/image/p5.Image.js",
9835            "line": 561,
9836            "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",
9837            "itemtype": "method",
9838            "name": "mask",
9839            "params": [
9840                {
9841                    "name": "srcImage",
9842                    "description": "<p>source image</p>\n",
9843                    "type": "p5.Image"
9844                }
9845            ],
9846            "example": [
9847                "\n<div><code>\nvar 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>"
9848            ],
9849            "alt": "image of rocky mountains with white at right\n\n\nhttp://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/",
9850            "class": "p5.Image",
9851            "module": "Image",
9852            "submodule": "Image"
9853        },
9854        {
9855            "file": "src/image/p5.Image.js",
9856            "line": 624,
9857            "description": "<p>Applies an image filter to a p5.Image</p>\n",
9858            "itemtype": "method",
9859            "name": "filter",
9860            "params": [
9861                {
9862                    "name": "filterType",
9863                    "description": "<p>either THRESHOLD, GRAY, OPAQUE, INVERT,\n                               POSTERIZE, BLUR, ERODE, DILATE or BLUR.\
9863n                               See Filters.js for docs on\n                               each available filter</p>\n",
9864                    "type": "Constant"
9865                },
9866                {
9867                    "name": "filterParam",
9868                    "description": "<p>an optional parameter unique\n                               to each filter, see above</p>\n",
9869                    "type": "Number",
9870                    "optional": true
9871                }
9872            ],
9873            "example": [
9874                "\n<div><code>\nvar photo1;\nvar 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>"
9875            ],
9876            "alt": "2 images of rocky mountains left one in color, right in black and white",
9877            "class": "p5.Image",
9878            "module": "Image",
9879            "submodule": "Image"
9880        },
9881        {
9882            "file": "src/image/p5.Image.js",
9883            "line": 660,
9884            "description": "<p>Copies a region of pixels from one image to another, using a specified\nblend mode to do the operation.</p>\n",
9885            "itemtype": "method",
9886            "name": "blend",
9887            "example": [
9888                "\n<div><code>\nvar mountains;\nvar 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>\nvar mountains;\nvar 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>\nvar mountains;\nvar 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>"
9889            ],
9890            "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",
9891            "class": "p5.Image",
9892            "module": "Image",
9893            "submodule": "Image",
9894            "overloads": [
9895                {
9896                    "line": 660,
9897                    "params": [
9898                        {
9899                            "name": "srcImage",
9900                            "description": "<p>source image</p>\n",
9901                            "type": "p5.Image"
9902                        },
9903                        {
9904                            "name": "sx",
9905                            "description": "<p>X coordinate of the source&#39;s upper left corner</p>\n",
9906                            "type": "Integer"
9907                        },
9908                        {
9909                            "name": "sy",
9910                            "description": "<p>Y coordinate of the source&#39;s upper left corner</p>\n",
9911                            "type": "Integer"
9912                        },
9913                        {
9914                            "name": "sw",
9915                            "description": "<p>source image width</p>\n",
9916                            "type": "Integer"
9917                        },
9918                        {
9919                            "name": "sh",
9920                            "description": "<p>source image height</p>\n",
9921                            "type": "Integer"
9922                        },
9923                        {
9924                            "name": "dx",
9925                            "description": "<p>X coordinate of the destination&#39;s upper left corner</p>\n",
9926                            "type": "Integer"
9927                        },
9928                        {
9929                            "name": "dy",
9930                            "description": "<p>Y coordinate of the destination&#39;s upper left corner</p>\n",
9931                            "type": "Integer"
9932                        },
9933                        {
9934                            "name": "dw",
9935                            "description": "<p>destination image width</p>\n",
9936                            "type": "Integer"
9937                        },
9938                        {
9939                            "name": "dh",
9940                            "description": "<p>destination image height</p>\n",
9941                            "type": "Integer"
9942                        },
9943                        {
9944                            "name": "blendMode",
9945                            "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",
9946                            "type": "Constant"
9947                        }
9948                    ]
9949                },
9950                {
9951                    "line": 739,
9952                    "params": [
9953                        {
9954                            "name": "sx",
9955                            "description": "",
9956                            "type": "Integer"
9957                        },
9958                        {
9959                            "name": "sy",
9960                            "description": "",
9961                            "type": "Integer"
9962                        },
9963                        {
9964                            "name": "sw",
9965                            "description": "",
9966                            "type": "Integer"
9967                        },
9968                        {
9969                            "name": "sh",
9970                            "description": "",
9971                            "type": "Integer"
9972                        },
9973                        {
9974                            "name": "dx",
9975                            "description": "",
9976                            "type": "Integer"
9977                        },
9978                        {
9979                            "name": "dy",
9980                            "description": "",
9981                            "type": "Integer"
9982                        },
9983                        {
9984                            "name": "dw",
9985                            "description": "",
9986                            "type": "Integer"
9987                        },
9988                        {
9989                            "name": "dh",
9990                            "description": "",
9991                            "type": "Integer"
9992                        },
9993                        {
9994                            "name": "blendMode",
9995                            "description": "",
9996                            "type": "Constant"
9997                        }
9998                    ]
9999                }
10000            ]
10001        },
10002        {
10003            "file": "src/image/p5.Image.js",
10004            "line": 782,
10005            "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",
10006            "itemtype": "method",
10007            "name": "save",
10008            "params": [
10009                {
10010                    "name": "filename",
10011                    "description": "<p>give your file a name</p>\n",
10012                    "type": "String"
10013                },
10014                {
10015                    "name": "extension",
10016                    "description": "<p>&#39;png&#39; or &#39;jpg&#39;</p>\n",
10017                    "type": "String"
10018                }
10019            ],
10020            "example": [
10021                "\n<div><code>\nvar 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>"
10022            ],
10023            "alt": "image of rocky mountains.",
10024            "class": "p5.Image",
10025            "module": "Image",
10026            "submodule": "Image"
10027        },
10028        {
10029            "file": "src/image/pixels.js",
10030            "line": 14,
10031            "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 pixelDensity) of the display window x4,\nrepresenting the R, G, B, A values in order for each pixel, mov
10031ing 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\">var d = pixelDensity();\nfor (var i = 0; i &lt; d; i++) {\n  for (var j = 0; j &lt; d; j++) {\n    // loop over\n    idx = 4 * ((y * d + j) * width * d + (x * d + i));\n    pixels[idx] = r;\n    pixels[idx+1] = g;\n    pixels[idx+2] = b;\n    pixels[idx+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 set() will automatically take care of\nsetting all the appropriate values in pixels[] 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 loadPixels()\nfunction. After the array data has been modified, the updatePixels()\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 <code>slice()</code> or\n<code>arrayCopy()</code> do not\nwork.</p>",
10032            "itemtype": "property",
10033            "name": "pixels",
10034            "type": "Number[]",
10035            "example": [
10036                "\n<div>\n<code>\nvar pink = color(255, 102, 204);\nloadPixels();\nvar d = pixelDensity();\nvar halfImage = 4 * (width * d) * (height / 2 * d);\nfor (var 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>"
10037            ],
10038            "alt": "top half of canvas pink, bottom grey",
10039            "class": "p5",
10040            "module": "Image",
10041            "submodule": "Pixels"
10042        },
10043        {
10044            "file": "src/image/pixels.js",
10045            "line": 83,
10046            "description": "<p>Copies a region of pixels from one image to another, using a specified\nblend mode to do the operation.</p>\n",
10047            "itemtype": "method",
10048            "name": "blend",
10049            "example": [
10050                "\n<div><code>\nvar img0;\nvar 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>\nvar img0;\nvar 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>\nvar img0;\nvar 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>"
10051            ],
10052            "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",
10053            "class": "p5",
10054            "module": "Image",
10055            "submodule": "Pixels",
10056            "overloads": [
10057                {
10058                    "line": 83,
10059                    "params": [
10060                        {
10061                            "name": "srcImage",
10062                            "description": "<p>source image</p>\n",
10063                            "type": "p5.Image"
10064                        },
10065                        {
10066                            "name": "sx",
10067                            "description": "<p>X coordinate of the source&#39;s upper left corner</p>\n",
10068                            "type": "Integer"
10069                        },
10070                        {
10071                            "name": "sy",
10072                            "description": "<p>Y coordinate of the source&#39;s upper left corner</p>\n",
10073                            "type": "Integer"
10074                        },
10075                        {
10076                            "name": "sw",
10077                            "description": "<p>source image width</p>\n",
10078                            "type": "Integer"
10079                        },
10080                        {
10081                            "name": "sh",
10082                            "description": "<p>source image height</p>\n",
10083                            "type": "Integer"
10084                        },
10085                        {
10086                            "name": "dx",
10087                            "description": "<p>X coordinate of the destination&#39;s upper left corner</p>\n",
10088                            "type": "Integer"
10089                        },
10090                        {
10091                            "name": "dy",
10092                            "description": "<p>Y coordinate of the destination&#39;s upper left corner</p>\n",
10093                            "type": "Integer"
10094                        },
10095                        {
10096                            "name": "dw",
10097                            "description": "<p>destination image width</p>\n",
10098                            "type": "Integer"
10099                        },
10100                        {
10101                            "name": "dh",
10102                            "description": "<p>destination image height</p>\n",
10103                            "type": "Integer"
10104                        },
10105                        {
10106                            "name": "blendMode",
10107                            "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",
10108                            "type": "Constant"
10109                        }
10110                    ]
10111                },
10112                {
10113                    "line": 156,
10114                    "params": [
10115                        {
10116                            "name": "sx",
10117                            "description": "",
10118                            "type": "Integer"
10119                        },
10120                        {
10121                            "name": "sy",
10122                            "description": "",
10123                            "type": "Integer"
10124                        },
10125                        {
10126                            "name": "sw",
10127                            "description": "",
10128                            "type": "Integer"
10129                        },
10130                        {
10131                            "name": "sh",
10132                            "description": "",
10133                            "type": "Integer"
10134                        },
10135                        {
10136                            "name": "dx",
10137                            "description": "",
10138                            "type": "Integer"
10139                        },
10140                        {
10141                            "name": "dy",
10142                            "description": "",
10143                            "type": "Integer"
10144                        },
10145                        {
10146                            "name": "dw",
10147                            "description": "",
10148                            "type": "Integer"
10149                        },
10150                        {
10151                            "name": "dh",
10152                            "description": "",
10153                            "type": "Integer"
10154                        },
10155                        {
10156                            "name": "blendMode",
10157                            "description": "",
10158                            "type": "Constant"
10159                        }
10160                    ]
10161                }
10162            ]
10163        },
10164        {
10165            "file": "src/image/pixels.js",
10166            "line": 177,
10167            "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",
10168            "itemtype": "method",
10169            "name": "copy",
10170            "example": [
10171                "\n<div><code>\nvar 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);
10171\n  stroke(255);\n  noFill();\n  // Rectangle shows area being copied\n  rect(7, 22, 10, 10);\n}\n</code></div>"
10172            ],
10173            "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",
10174            "class": "p5",
10175            "module": "Image",
10176            "submodule": "Pixels",
10177            "overloads": [
10178                {
10179                    "line": 177,
10180                    "params": [
10181                        {
10182                            "name": "srcImage",
10183                            "description": "<p>source image</p>\n",
10184                            "type": "p5.Image|p5.Element"
10185                        },
10186                        {
10187                            "name": "sx",
10188                            "description": "<p>X coordinate of the source&#39;s upper left corner</p>\n",
10189                            "type": "Integer"
10190                        },
10191                        {
10192                            "name": "sy",
10193                            "description": "<p>Y coordinate of the source&#39;s upper left corner</p>\n",
10194                            "type": "Integer"
10195                        },
10196                        {
10197                            "name": "sw",
10198                            "description": "<p>source image width</p>\n",
10199                            "type": "Integer"
10200                        },
10201                        {
10202                            "name": "sh",
10203                            "description": "<p>source image height</p>\n",
10204                            "type": "Integer"
10205                        },
10206                        {
10207                            "name": "dx",
10208                            "description": "<p>X coordinate of the destination&#39;s upper left corner</p>\n",
10209                            "type": "Integer"
10210                        },
10211                        {
10212                            "name": "dy",
10213                            "description": "<p>Y coordinate of the destination&#39;s upper left corner</p>\n",
10214                            "type": "Integer"
10215                        },
10216                        {
10217                            "name": "dw",
10218                            "description": "<p>destination image width</p>\n",
10219                            "type": "Integer"
10220                        },
10221                        {
10222                            "name": "dh",
10223                            "description": "<p>destination image height</p>\n",
10224                            "type": "Integer"
10225                        }
10226                    ]
10227                },
10228                {
10229                    "line": 220,
10230                    "params": [
10231                        {
10232                            "name": "sx",
10233                            "description": "",
10234                            "type": "Integer"
10235                        },
10236                        {
10237                            "name": "sy",
10238                            "description": "",
10239                            "type": "Integer"
10240                        },
10241                        {
10242                            "name": "sw",
10243                            "description": "",
10244                            "type": "Integer"
10245                        },
10246                        {
10247                            "name": "sh",
10248                            "description": "",
10249                            "type": "Integer"
10250                        },
10251                        {
10252                            "name": "dx",
10253                            "description": "",
10254                            "type": "Integer"
10255                        },
10256                        {
10257                            "name": "dy",
10258                            "description": "",
10259                            "type": "Integer"
10260                        },
10261                        {
10262                            "name": "dw",
10263                            "description": "",
10264                            "type": "Integer"
10265                        },
10266                        {
10267                            "name": "dh",
10268                            "description": "",
10269                            "type": "Integer"
10270                        }
10271                    ]
10272                }
10273            ]
10274        },
10275        {
10276            "file": "src/image/pixels.js",
10277            "line": 236,
10278            "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",
10279            "itemtype": "method",
10280            "name": "filter",
10281            "params": [
10282                {
10283                    "name": "filterType",
10284                    "description": "<p>either THRESHOLD, GRAY, OPAQUE, INVERT,\n                               POSTERIZE, BLUR, ERODE, DILATE or BLUR.\
10284n                               See Filters.js for docs on\n                               each available filter</p>\n",
10285                    "type": "Constant"
10286                },
10287                {
10288                    "name": "filterParam",
10289                    "description": "<p>an optional parameter unique\n                               to each filter, see above</p>\n",
10290                    "type": "Number",
10291                    "optional": true
10292                }
10293            ],
10294            "example": [
10295                "\n<div>\n<code>\nvar 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>\nvar 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>\nvar 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>\nvar 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>\nvar 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>\nvar 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>\nvar img;\nfunction preload() {\n  img = loadImage('assets/bricks.jpg');\n}\nfunction setup() {\n  image(img, 0, 0);
10295\n  filter(BLUR, 3);\n}\n</code>\n</div>\n\n<div>\n<code>\nvar 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>"
10296            ],
10297            "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",
10298            "class": "p5",
10299            "module": "Image",
10300            "submodule": "Pixels"
10301        },
10302        {
10303            "file": "src/image/pixels.js",
10304            "line": 415,
10305            "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 imageMode().\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 colorMode, use getColor 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 pixels[]. The equivalent statement to\nget(x, y) using pixels[] with pixel density d is\n<code>\nvar x, y, d; // set these to the coordinates\nvar off = (y <em> width + x) </em> d * 4;\nvar components = [\n  pixels[off],\n  pixels[off + 1],\n  pixels[off + 2],\n  pixels[off + 3]\n];\nprint(components);\n</code>\n<br><br>\nSee the reference for pixels[] for more information.</p>\n",
10306            "itemtype": "method",
10307            "name": "get",
10308            "params": [
10309                {
10310                    "name": "x",
10311                    "description": "<p>x-coordinate of the pixel</p>\n",
10312                    "type": "Number",
10313                    "optional": true
10314                },
10315                {
10316                    "name": "y",
10317                    "description": "<p>y-coordinate of the pixel</p>\n",
10318                    "type": "Number",
10319                    "optional": true
10320                },
10321                {
10322                    "name": "w",
10323                    "description": "<p>width</p>\n",
10324                    "type": "Number",
10325                    "optional": true
10326                },
10327                {
10328                    "name": "h",
10329                    "description": "<p>height</p>\n",
10330                    "type": "Number",
10331                    "optional": true
10332                }
10333            ],
10334            "return": {
10335                "description": "values of pixel at x,y in array format\n                             [R, G, B, A] or p5.Image",
10336                "type": "Number[]|p5.Image"
10337            },
10338            "example": [
10339                "\n<div>\n<code>\nvar img;\nfunction preload() {\n  img = loadImage('assets/rockies.jpg');\n}\nfunction setup() {\n  image(img, 0, 0);\n  var c = get();\n  image(c, width / 2, 0);\n}\n</code>\n</div>\n\n<div>\n<code>\nvar img;\nfunction preload() {\n  img = loadImage('assets/rockies.jpg');\n}\nfunction setup() {\n  image(img, 0, 0);\n  var c = get(50, 90);\n  fill(c);\n  noStroke();\n  rect(25, 25, 50, 50);\n}\n</code>\n</div>"
10340            ],
10341            "alt": "2 images of the rocky mountains, side-by-side\nImage of the rocky mountains with 50x50 green rect in center of canvas",
10342            "class": "p5",
10343            "module": "Image",
10344            "submodule": "Pixels"
10345        },
10346        {
10347            "file": "src/image/pixels.js",
10348            "line": 491,
10349            "description": "<p>Loads the pixel data for the display window into the pixels[] array. This\nfunction must always be called before reading from or writing to pixels[].\nNote that only changes made with set() or direct manipulation of pixels[]\nwill occur.</p>\n",
10350            "itemtype": "method",
10351            "name": "loadPixels",
10352            "example": [
10353                "\n<div>\n<code>\nvar img;\nfunction preload() {\n  img = loadImage('assets/rockies.jpg');\n}\n\nfunction setup() {\n  image(img, 0, 0);\n  var d = pixelDensity();\n  var halfImage = 4 * (img.width * d) * (img.height * d / 2);\n  loadPixels();\n  for (var i = 0; i < halfImage;
10353 i++) {\n    pixels[i + halfImage] = pixels[i];\n  }\n  updatePixels();\n}\n</code>\n</div>"
10354            ],
10355            "alt": "two images of the rocky mountains. one on top, one on bottom of canvas.",
10356            "class": "p5",
10357            "module": "Image",
10358            "submodule": "Pixels"
10359        },
10360        {
10361            "file": "src/image/pixels.js",
10362            "line": 528,
10363            "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 p5.Color 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 imageMode().\n</p>\n<p>\nAfter using set(), you must call updatePixels() for your changes to appear.\nThis should be called once all pixels have been set, and must be called before\ncalling .get() 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 pixels[]. Setting the pixels[]\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 pixels[] for more information.</p>",
10364            "itemtype": "method",
10365            "name": "set",
10366            "params": [
10367                {
10368                    "name": "x",
10369                    "description": "<p>x-coordinate of the pixel</p>\n",
10370                    "type": "Number"
10371                },
10372                {
10373                    "name": "y",
10374                    "description": "<p>y-coordinate of the pixel</p>\n",
10375                    "type": "Number"
10376                },
10377                {
10378                    "name": "c",
10379                    "description": "<p>insert a grayscale value | a pixel array |\n                               a p5.Color object | a p5.Image to copy</p>\n",
10380                    "type": "Number|Number[]|Object"
10381                }
10382            ],
10383            "example": [
10384                "\n<div>\n<code>\nvar 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 (var i = 30; i < width - 15; i++) {\n  for (var j = 20; j < height - 25; j++) {\n    var c = color(204 - j, 153 - i, 0);\n    set(i, j, c);\n  }\n}\nupdatePixels();\n</code>\n</div>\n\n<div>\n<code>\nvar 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>"
10385            ],
10386            "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.",
10387            "class": "p5",
10388            "module": "Image",
10389            "submodule": "Pixels"
10390        },
10391        {
10392            "file": "src/image/pixels.js",
10393            "line": 602,
10394            "description": "<p>Updates the display window with the data in the pixels[] array.\nUse in conjunction with loadPixels(). If you&#39;re only reading pixels from\nthe array, there&#39;s no need to call updatePixels() — updating is only\nnecessary to apply changes. updatePixels() should be called anytime the\npixels array is manipulated or set() is called, and only changes made with\nset() or direct changes to pixels[] will occur.</p>\n",
10395            "itemtype": "method",
10396            "name": "updatePixels",
10397            "params": [
10398                {
10399                    "name": "x",
10400                    "description": "<p>x-coordinate of the upper-left corner of region\n                        to update</p>\n",
10401                    "type": "Number",
10402                    "optional": true
10403                },
10404                {
10405                    "name": "y",
10406                    "description": "<p>y-coordinate of the upper-left corner of region\n                        to update</p>\n",
10407                    "type": "Number",
10408                    "optional": true
10409                },
10410                {
10411                    "name": "w",
10412                    "description": "<p>width of region to update</p>\n",
10413                    "type": "Number",
10414                    "optional": true
10415                },
10416                {
10417                    "name": "h",
10418                    "description": "<p>height of region to update</p>\n",
10419                    "type": "Number",
10420                    "optional": true
10421                }
10422            ],
10423            "example": [
10424                "\n<div>\n<code>\nvar img;\nfunction preload() {\n  img = loadImage('assets/rockies.jpg');\n}\n\nfunction setup() {\n  image(img, 0, 0);\n  var d = pixelDensity();\n  var halfImage = 4 * (img.width * d) * (img.height * d / 2);\n  loadPixels();\n  for (var i = 0; i < halfImage;
10424 i++) {\n    pixels[i + halfImage] = pixels[i];\n  }\n  updatePixels();\n}\n</code>\n</div>"
10425            ],
10426            "alt": "two images of the rocky mountains. one on top, one on bottom of canvas.",
10427            "class": "p5",
10428            "module": "Image",
10429            "submodule": "Pixels"
10430        },
10431        {
10432            "file": "src/io/files.js",
10433            "line": 19,
10434            "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",
10435            "itemtype": "method",
10436            "name": "loadJSON",
10437            "return": {
10438                "description": "JSON data",
10439                "type": "Object|Array"
10440            },
10441            "example": [
10442                "\n\n<p>Calling loadJSON() inside preload() guarantees to complete the\noperation before setup() and draw() are called.</p>\n\n<div><code>\n// Examples use USGS Earthquake API:\n//   https://earthquake.usgs.gov/fdsnws/event/1/#methods\nvar earthquakes;\nfunction preload() {\n  // Get the most recent earthquake in the database\n  var 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  var earthquakeMag = earthquakes.features[0].properties.mag;\n  var 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  var 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  var earthquakeMag = earthquakes.features[0].properties.mag;\n  var 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>"
10443            ],
10444            "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",
10445            "class": "p5",
10446            "module": "IO",
10447            "submodule": "Input",
10448            "overloads": [
10449                {
10450                    "line": 19,
10451                    "params": [
10452                        {
10453                            "name": "path",
10454                            "description": "<p>name of the file or url to load</p>\n",
10455                            "type": "String"
10456                        },
10457                        {
10458                            "name": "jsonpOptions",
10459                            "description": "<p>options object for jsonp related settings</p>\n",
10460                            "type": "Object",
10461                            "optional": true
10462                        },
10463                        {
10464                            "name": "datatype",
10465                            "description": "<p>&quot;json&quot; or &quot;jsonp&quot;</p>\n",
10466                            "type": "String",
10467                            "optional": true
10468                        },
10469                        {
10470                            "name": "callback",
10471                            "description": "<p>function to be executed after\n                                   loadJSON() completes, data is passed\n                                   in as first argument</p>\n",
10472                            "type": "Function",
10473                            "optional": true
10474                        },
10475                        {
10476                            "name": "errorCallback",
10477                            "description": "<p>function to be executed if\n                                   there is an error, response is passed\n                                   in as first argument</p>\n",
10478                            "type": "Function",
10479                            "optional": true
10480                        }
10481                    ],
10482                    "return": {
10483                        "description": "JSON data",
10484                        "type": "Object|Array"
10485                    }
10486                },
10487                {
10488                    "line": 104,
10489                    "params": [
10490                        {
10491                            "name": "path",
10492                            "description": "",
10493                            "type": "String"
10494                        },
10495                        {
10496                            "name": "datatype",
10497                            "description": "",
10498                            "type": "String"
10499                        },
10500                        {
10501                            "name": "callback",
10502                            "description": "",
10503                            "type": "Function",
10504                            "optional": true
10505                        },
10506                        {
10507                            "name": "errorCallback",
10508                            "description": "",
10509                            "type": "Function",
10510                            "optional": true
10511                        }
10512                    ],
10513                    "return": {
10514                        "description": "",
10515                        "type": "Object|Array"
10516                    }
10517                },
10518                {
10519                    "line": 112,
10520                    "params": [
10521                        {
10522                            "name": "path",
10523                            "description": "",
10524                            "type": "String"
10525                        },
10526                        {
10527                            "name": "callback",
10528                            "description": "",
10529                            "type": "Function"
10530                        },
10531                        {
10532                            "name": "errorCallback",
10533                            "description": "",
10534                            "type": "Function",
10535                            "optional": true
10536                        }
10537                    ],
10538                    "return": {
10539                        "description": "",
10540                        "type": "Object|Array"
10541                    }
10542                }
10543            ]
10544        },
10545        {
10546            "file": "src/io/files.js",
10547            "line": 170,
10548            "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",
10549            "itemtype": "method",
10550            "name": "loadStrings",
10551            "params": [
10552                {
10553                    "name": "filename",
10554                    "description": "<p>name of the file or url to load</p>\n",
10555                    "type": "String"
10556                },
10557                {
10558                    "name": "callback",
10559                    "description": "<p>function to be executed after loadStrings()\n                              completes, Array is passed in as first\n                              argument</p>\n",
10560                    "type": "Function",
10561                    "optional": true
10562                },
10563                {
10564                    "name": "errorCallback",
10565                    "description": "<p>function to be executed if\n                              there is an error, response is passed\n                              in as first argument</p>\n",
10566                    "type": "Function",
10567                    "optional": true
10568                }
10569            ],
10570            "return": {
10571                "description": "Array of Strings",
10572                "type": "String[]"
10573            },
10574            "example": [
10575                "\n\n<p>Calling loadStrings() inside preload() guarantees to complete the\noperation before setup() and draw() are called.</p>\n\n<div><code>\nvar result;\nfunction preload() {\n  result = loadStrings('assets/test.txt');\n}\n\nfunction setup() {\n  background(200);\n  var 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  var ind = floor(random(result.length));\n  text(result[ind], 10, 10, 80, 80);\n}\n</code></div>"
10576            ],
10577            "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\"",
10578            "class": "p5",
10579            "module": "IO",
10580            "submodule": "Input"
10581        },
10582        {
10583            "file": "src/io/files.js",
10584            "line": 271,
10585            "description": "<p>Reads the contents of a file or URL and creates a p5.Table 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 loadTable() inside preload()\nguarantees to complete the operation before setup() and draw() are called.\n<p>Outside of preload(), you may supply a callback function to handle the\nobject:</p>\n</p>",
10586            "itemtype": "method",
10587            "name": "loadTable",
10588            "return": {
10589                "description": "Table object containing data",
10590                "type": "Object"
10591            },
10592            "example": [
10593                "\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\nvar 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 (var r = 0; r < table.getRowCount(); r++)\n    for (var c = 0; c < table.getColumnCount(); c++) {\n      print(table.getString(r, c));\n    }\n}\n</code>\n</div>"
10594            ],
10595            "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\"",
10596            "class": "p5",
10597            "module": "IO",
10598            "submodule": "Input",
10599            "overloads": [
10600                {
10601                    "line": 271,
10602                    "params": [
10603                        {
10604                            "name": "filename",
10605                            "description": "<p>name of the file or URL to load</p>\n",
10606                            "type": "String"
10607                        },
10608                        {
10609                            "name": "options",
10610                            "description": "<p>&quot;header&quot; &quot;csv&quot; &quot;tsv&quot;</p>\n",
10611                            "type": "String"
10612                        },
10613                        {
10614                            "name": "callback",
10615                            "description": "<p>function to be executed after\n                                    loadTable() completes. On success, the\n                                    Table object is passed in as the\n                                    first argument.</p>\n",
10616                            "type": "Function",
10617                            "optional": true
10618                        },
10619                        {
10620                            "name": "errorCallback",
10621                            "description": "<p>function to be executed if\n                                    there is an error, response is passed\n                                    in as first argument</p>\n",
10622                            "type": "Function",
10623                            "optional": true
10624                        }
10625                    ],
10626                    "return": {
10627                        "description": "Table object containing data",
10628                        "type": "Object"
10629                    }
10630                },
10631                {
10632                    "line": 360,
10633                    "params": [
10634                        {
10635                            "name": "filename",
10636                            "description": "",
10637                            "type": "String"
10638                        },
10639                        {
10640                            "name": "callback",
10641                            "description": "",
10642                            "type": "Function",
10643                            "optional": true
10644                        },
10645                        {
10646                            "name": "errorCallback",
10647                            "description": "",
10648                            "type": "Function",
10649                            "optional": true
10650                        }
10651                    ],
10652                    "return": {
10653                        "description": "",
10654                        "type": "Object"
10655                    }
10656                }
10657            ]
10658        },
10659        {
10660            "file": "src/io/files.js",
10661            "line": 603,
10662            "description": "<p>
10662Reads 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 loadXML() inside preload()\nguarantees to complete the operation before setup() and draw() are called.</p>\n<p>Outside of preload(), you may supply a callback function to handle the\nobject.</p>\n",
10663            "itemtype": "method",
10664            "name": "loadXML",
10665            "params": [
10666                {
10667                    "name": "filename",
10668                    "description": "<p>name of the file or URL to load</p>\n",
10669                    "type": "String"
10670                },
10671                {
10672                    "name": "callback",
10673                    "description": "<p>function to be executed after loadXML()\n                              completes, XML object is passed in as\n                              first argument</p>\n",
10674                    "type": "Function",
10675                    "optional": true
10676                },
10677                {
10678                    "name": "errorCallback",
10679                    "description": "<p>function to be executed if\n                              there is an error, response is passed\n                              in as first argument</p>\n",
10680                    "type": "Function",
10681                    "optional": true
10682                }
10683            ],
10684            "return": {
10685                "description": "XML object containing data",
10686                "type": "Object"
10687            },
10688            "example": [
10689                "\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\nvar xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  var children = xml.getChildren('animal');\n\n  for (var i = 0; i < children.length; i++) {\n    var id = children[i].getNum('id');\n    var coloring = children[i].getString('species');\n    var 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>"
10690            ],
10691            "alt": "no image displayed",
10692            "class": "p5",
10693            "module": "IO",
10694            "submodule": "Input"
10695        },
10696        {
10697            "file": "src/io/files.js",
10698            "line": 704,
10699            "itemtype": "method",
10700            "name": "loadBytes",
10701            "params": [
10702                {
10703                    "name": "file",
10704                    "description": "<p>name of the file or URL to load</p>\n",
10705                    "type": "String"
10706                },
10707                {
10708                    "name": "callback",
10709                    "description": "<p>function to be executed after loadBytes()\n                                   completes</p>\n",
10710                    "type": "Function",
10711                    "optional": true
10712                },
10713                {
10714                    "name": "errorCallback",
10715                    "description": "<p>function to be executed if there\n                                   is an error</p>\n",
10716                    "type": "Function",
10717                    "optional": true
10718                }
10719            ],
10720            "return": {
10721                "description": "an object whose 'bytes' property will be the loaded buffer",
10722                "type": "Object"
10723            },
10724            "example": [
10725                "\n<div class='norender'><code>\nvar data;\n\nfunction preload() {\n  data = loadBytes('assets/mammals.xml');\n}\n\nfunction setup() {\n  for (var i = 0; i < 5;
10725 i++) {\n    console.log(data.bytes[i].toString(16));\n  }\n}\n</code></div>"
10726            ],
10727            "alt": "no image displayed",
10728            "class": "p5",
10729            "module": "IO",
10730            "submodule": "Input"
10731        },
10732        {
10733            "file": "src/io/files.js",
10734            "line": 754,
10735            "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",
10736            "itemtype": "method",
10737            "name": "httpGet",
10738            "example": [
10739                "\n<div class='norender'><code>\n// Examples use USGS Earthquake API:\n//   https://earthquake.usgs.gov/fdsnws/event/1/#methods\nvar earthquakes;\nfunction preload() {\n  // Get the most recent earthquake in the database\n  var 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  var earthquakeMag = earthquakes.features[0].properties.mag;\n  var 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  noLoop();\n}\n</code></div>"
10740            ],
10741            "class": "p5",
10742            "module": "IO",
10743            "submodule": "Input",
10744            "overloads": [
10745                {
10746                    "line": 754,
10747                    "params": [
10748                        {
10749                            "name": "path",
10750                            "description": "<p>name of the file or url to load</p>\n",
10751                            "type": "String"
10752                        },
10753                        {
10754                            "name": "datatype",
10755                            "description": "<p>&quot;json&quot;, &quot;jsonp&quot;, &quot;binary&quot;, &quot;arrayBuffer&quot;,\n                                   &quot;xml&quot;, or &quot;text&quot;</p>\n",
10756                            "type": "String",
10757                            "optional": true
10758                        },
10759                        {
10760                            "name": "data",
10761                            "description": "<p>param data passed sent with request</p>\n",
10762                            "type": "Object|Boolean",
10763                            "optional": true
10764                        },
10765                        {
10766                            "name": "callback",
10767                            "description": "<p>function to be executed after\n                                   httpGet() completes, data is passed in\n                                   as first argument</p>\n",
10768                            "type": "Function",
10769                            "optional": true
10770                        },
10771                        {
10772                            "name": "errorCallback",
10773                            "description": "<p>function to be executed if\n                                   there is an error, response is passed\n                                   in as first argument</p>\n",
10774                            "type": "Function",
10775                            "optional": true
10776                        }
10777                    ]
10778                },
10779                {
10780                    "line": 805,
10781                    "params": [
10782                        {
10783                            "name": "path",
10784                            "description": "",
10785                            "type": "String"
10786                        },
10787                        {
10788                            "name": "data",
10789                            "description": "",
10790                            "type": "Object|Boolean"
10791                        },
10792                        {
10793                            "name": "callback",
10794                            "description": "",
10795                            "type": "Function",
10796                            "optional": true
10797                        },
10798                        {
10799                            "name": "errorCallback",
10800                            "description": "",
10801                            "type": "Function",
10802                            "optional": true
10803                        }
10804                    ]
10805                },
10806                {
10807                    "line": 812,
10808                    "params": [
10809                        {
10810                            "name": "path",
10811                            "description": "",
10812                            "type": "String"
10813                        },
10814                        {
10815                            "name": "callback",
10816                            "description": "",
10817                            "type": "Function"
10818                        },
10819                        {
10820                            "name": "errorCallback",
10821                            "description": "",
10822                            "type": "Function",
10823                            "optional": true
10824                        }
10825                    ]
10826                }
10827            ]
10828        },
10829        {
10830            "file": "src/io/files.js",
10831            "line": 826,
10832            "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",
10833            "itemtype": "method",
10834            "name": "httpPost",
10835            "example": [
10836                "\n<div>\n<code>\n// Examples use jsonplaceholder.typicode.com for a Mock Data API\n\nvar url = 'https://jsonplaceholder.typicode.com/posts';\nvar 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  var r = random(255);\n  var g = random(255);\n  var 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>\nvar url = 'https://invalidURL'; // A bad URL that will cause errors\nvar 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  var r = random(255);\n  var g = random(255);\n  var 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"
10837            ],
10838            "class": "p5",
10839            "module": "IO",
10840            "submodule": "Input",
10841            "overloads": [
10842                {
10843                    "line": 826,
10844                    "params": [
10845                        {
10846                            "name": "path",
10847                            "description": "<p>name of the file or url to load</p>\n",
10848                            "type": "String"
10849                        },
10850                        {
10851                            "name": "datatype",
10852                            "description": "<p>&quot;json&quot;, &quot;jsonp&quot;, &quot;xml&quot;, or &quot;text&quot;.\n                                   If omitted, httpPost() will guess.</p>\n",
10853                            "type": "String",
10854                            "optional": true
10855                        },
10856                        {
10857                            "name": "data",
10858                            "description": "<p>param data passed sent with request</p>\n",
10859                            "type": "Object|Boolean",
10860                            "optional": true
10861                        },
10862                        {
10863                            "name": "callback",
10864                            "description": "<p>function to be executed after\n                                   httpPost() completes, data is passed in\n                                   as first argument</p>\n",
10865                            "type": "Function",
10866                            "optional": true
10867                        },
10868                        {
10869                            "name": "errorCallback",
10870                            "description": "<p>function to be executed if\n                                   there is an error, response is passed\n                                   in as first argument</p>\n",
10871                            "type": "Function",
10872                            "optional": true
10873                        }
10874                    ]
10875                },
10876                {
10877                    "line": 905,
10878                    "params": [
10879                        {
10880                            "name": "path",
10881                            "description": "",
10882                            "type": "String"
10883                        },
10884                        {
10885                            "name": "data",
10886                            "description": "",
10887                            "type": "Object|Boolean"
10888                        },
10889                        {
10890                            "name": "callback",
10891                            "description": "",
10892                            "type": "Function",
10893                            "optional": true
10894                        },
10895                        {
10896                            "name": "errorCallback",
10897                            "description": "",
10898                            "type": "Function",
10899                            "optional": true
10900                        }
10901                    ]
10902                },
10903                {
10904                    "line": 912,
10905                    "params": [
10906                        {
10907                            "name": "path",
10908                            "description": "",
10909                            "type": "String"
10910                        },
10911                        {
10912                            "name": "callback",
10913                            "description": "",
10914                            "type": "Function"
10915                        },
10916                        {
10917                            "name": "errorCallback",
10918                            "description": "",
10919                            "type": "Function",
10920                            "optional": true
10921                        }
10922                    ]
10923                }
10924            ]
10925        },
10926        {
10927            "file": "src/io/files.js",
10928            "line": 926,
10929            "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.</p>\n",
10930            "itemtype": "method",
10931            "name": "httpDo",
10932            "example": [
10933                "\n<div>\n<code>\n// Examples use USGS Earthquake API:\n// https://earthquake.usgs.gov/fdsnws/event/1/#methods\n\n// dis
10933plays an animation of all USGS earthquakes\nvar earthquakes;\nvar eqFeatureIndex = 0;\n\nfunction preload() {\n  var 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  var feature = earthquakes.features[eqFeatureIndex];\n  var mag = feature.properties.mag;\n  var 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>"
10934            ],
10935            "class": "p5",
10936            "module": "IO",
10937            "submodule": "Input",
10938            "overloads": [
10939                {
10940                    "line": 926,
10941                    "params": [
10942                        {
10943                            "name": "path",
10944                            "description": "<p>name of the file or url to load</p>\n",
10945                            "type": "String"
10946                        },
10947                        {
10948                            "name": "method",
10949                            "description": "<p>either &quot;GET&quot;, &quot;POST&quot;, or &quot;PUT&quot;,\n                                   defaults to &quot;GET&quot;</p>\n",
10950                            "type": "String",
10951                            "optional": true
10952                        },
10953                        {
10954                            "name": "datatype",
10955                            "description": "<p>&quot;json&quot;, &quot;jsonp&quot;, &quot;xml&quot;, or &quot;text&quot;</p>\n",
10956                            "type": "String",
10957                            "optional": true
10958                        },
10959                        {
10960                            "name": "data",
10961                            "description": "<p>param data passed sent with request</p>\n",
10962                            "type": "Object",
10963                            "optional": true
10964                        },
10965                        {
10966                            "name": "callback",
10967                            "description": "<p>function to be executed after\n                                   httpGet() completes, data is passed in\n                                   as first argument</p>\n",
10968                            "type": "Function",
10969                            "optional": true
10970                        },
10971                        {
10972                            "name": "errorCallback",
10973                            "description": "<p>function to be executed if\n                                   there is an error, response is passed\n                                   in as first argument</p>\n",
10974                            "type": "Function",
10975                            "optional": true
10976                        }
10977                    ]
10978                },
10979                {
10980                    "line": 994,
10981                    "params": [
10982                        {
10983                            "name": "path",
10984                            "description": "",
10985                            "type": "String"
10986                        },
10987                        {
10988                            "name": "options",
10989                            "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",
10990                            "type": "Object"
10991                        },
10992                        {
10993                            "name": "callback",
10994                            "description": "",
10995                            "type": "Function",
10996                            "optional": true
10997                        },
10998                        {
10999                            "name": "errorCallback",
11000                            "description": "",
11001                            "type": "Function",
11002                            "optional": true
11003                        }
11004                    ]
11005                }
11006            ]
11007        },
11008        {
11009            "file": "src/io/files.js",
11010            "line": 1130,
11011            "itemtype": "method",
11012            "name": "createWriter",
11013            "params": [
11014                {
11015                    "name": "name",
11016                    "description": "<p>name of the file to be created</p>\n",
11017                    "type": "String"
11018                },
11019                {
11020                    "name": "extension",
11021                    "description": "",
11022                    "type": "String",
11023                    "optional": true
11024                }
11025            ],
11026            "return": {
11027                "description": "",
11028                "type": "p5.PrintWriter"
11029            },
11030            "example": [
11031                "\n<div>\n<code>\ncreateButton('save')\n  .position(10, 10)\n  .mousePressed(function() {\
11031n    var writer = createWriter('squares.txt');\n    for (var i = 0; i < 10; i++) {\n      writer.print(i * i);\n    }\n    writer.close();\n    writer.clear();\n  });\n</code>\n</div>"
11032            ],
11033            "class": "p5",
11034            "module": "IO",
11035            "submodule": "Output"
11036        },
11037        {
11038            "file": "src/io/files.js",
11039            "line": 1179,
11040            "description": "<p>Writes data to the PrintWriter stream</p>\n",
11041            "itemtype": "method",
11042            "name": "write",
11043            "params": [
11044                {
11045                    "name": "data",
11046                    "description": "<p>all data to be written by the PrintWriter</p>\n",
11047                    "type": "Array"
11048                }
11049            ],
11050            "example": [
11051                "\n<div class=\"norender notest\">\n<code>\n// creates a file called 'newFile.txt'\nvar 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'\nvar 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'\nvar 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>"
11052            ],
11053            "class": "p5.PrintWriter",
11054            "module": "IO",
11055            "submodule": "Output"
11056        },
11057        {
11058            "file": "src/io/files.js",
11059            "line": 1219,
11060            "description": "<p>Writes data to the PrintWriter stream, and adds a new line at the end</p>\n",
11061            "itemtype": "method",
11062            "name": "print",
11063            "params": [
11064                {
11065                    "name": "data",
11066                    "description": "<p>all data to be printed by the PrintWriter</p>\n",
11067                    "type": "Array"
11068                }
11069            ],
11070            "example": [
11071                "\n<div class='norender notest'>\n<code>\n// creates a file called 'newFile.txt'\nvar 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>\nvar 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>"
11072            ],
11073            "class": "p5.PrintWriter",
11074            "module": "IO",
11075            "submodule": "Output"
11076        },
11077        {
11078            "file": "src/io/files.js",
11079            "line": 1262,
11080            "description": "<p>Clears the data already written to the PrintWriter object</p>\n",
11081            "itemtype": "method",
11082            "name": "clear",
11083            "example": [
11084                "\n<div class =\"norender notest\"><code>\n// create writer object\nvar writer = createWriter('newFile.txt');\nwriter.write(['clear me']);\n// clear writer object here\nwriter.clear();\n// close writer\nwriter.close();\n</code></div>\n"
11085            ],
11086            "class": "p5.PrintWriter",
11087            "module": "IO",
11088            "submodule": "Output"
11089        },
11090        {
11091            "file": "src/io/files.js",
11092            "line": 1280,
11093            "description": "<p>Closes the PrintWriter</p>\n",
11094            "itemtype": "method",
11095            "name": "close",
11096            "example": [
11097                "\n<div class=\"norender notest\">\n<code>\n// create a file called 'newFile.txt'\nvar 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'\nvar 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>"
11098            ],
11099            "class": "p5.PrintWriter",
11100            "module": "IO",
11101            "submodule": "Output"
11102        },
11103        {
11104            "file": "src/io/files.js",
11105            "line": 1329,
11106            "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 save()\nwithin draw if it&#39;s looping, as the save() 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();
11106\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\np5.Element, an Array of Strings,\nan Array of JSON, a JSON object, a p5.Table, a p5.Image, 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 paramaters. 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 var img = createImage(10, 10);\n save(img, 'my.png');\n\n // Saves canvas as an image\n var cnv = createCanvas(100, 100);\n save(cnv, 'myCanvas.jpg');\n\n // Saves p5.Renderer object as an image\n var gb = createGraphics(100, 100);\n save(gb, 'myGraphics.jpg');\n\n var 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 var 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 var arrayOfStrings = ['a', 'b'];\n save(arrayOfStrings, 'my.txt');\n </code></pre>",
11107            "itemtype": "method",
11108            "name": "save",
11109            "params": [
11110                {
11111                    "name": "objectOrFilename",
11112                    "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",
11113                    "type": "Object|String",
11114                    "optional": true
11115                },
11116                {
11117                    "name": "filename",
11118                    "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",
11119                    "type": "String",
11120                    "optional": true
11121                },
11122                {
11123                    "name": "options",
11124                    "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",
11125                    "type": "Boolean|String",
11126                    "optional": true
11127                }
11128            ],
11129            "class": "p5",
11130            "module": "IO",
11131            "submodule": "Output"
11132        },
11133        {
11134            "file": "src/io/files.js",
11135            "line": 1457,
11136            "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",
11137            "itemtype": "method",
11138            "name": "saveJSON",
11139            "params": [
11140                {
11141                    "name": "json",
11142                    "description": "",
11143                    "type": "Array|Object"
11144                },
11145                {
11146                    "name": "filename",
11147                    "description": "",
11148                    "type": "String"
11149                },
11150                {
11151                    "name": "optimize",
11152                    "description": "<p>If true, removes line breaks\n                               and spaces from the output\n                               file to optimize filesize\n                               (but not readability).</p>\n",
11153                    "type": "Boolean",
11154                    "optional": true
11155                }
11156            ],
11157            "example": [
11158                "\n <div><code>\n var json = {}; // new  JSON Object\n\n json.id = 0;\n json.species = 'Panthera leo';\n json.name = 'Lion';\n\n createButton('save')\n .position(10, 10)\n .mousePressed(function() {\
11158n   saveJSON(json, 'lion.json');\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>"
11159            ],
11160            "alt": "no image displayed",
11161            "class": "p5",
11162            "module": "IO",
11163            "submodule": "Output"
11164        },
11165        {
11166            "file": "src/io/files.js",
11167            "line": 1509,
11168            "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",
11169            "itemtype": "method",
11170            "name": "saveStrings",
11171            "params": [
11172                {
11173                    "name": "list",
11174                    "description": "<p>string array to be written</p>\n",
11175                    "type": "String[]"
11176                },
11177                {
11178                    "name": "filename",
11179                    "description": "<p>filename for output</p>\n",
11180                    "type": "String"
11181                },
11182                {
11183                    "name": "extension",
11184                    "description": "<p>the filename&#39;s extension</p>\n",
11185                    "type": "String",
11186                    "optional": true
11187                }
11188            ],
11189            "example": [
11190                "\n <div><code>\n var words = 'apple bear cat dog';\n\n // .split() outputs an Array\n var list = split(words, ' ');\n\n createButton('save')\n .position(10, 10)\n .mousePressed(function() {\n   saveStrings(list, 'nouns.txt');\n });\n\n // Saves the following to a file called 'nouns.txt':\n //\n // apple\n // bear\n // cat\n // dog\n </code></div>"
11191            ],
11192            "alt": "no image displayed",
11193            "class": "p5",
11194            "module": "IO",
11195            "submodule": "Output"
11196        },
11197        {
11198            "file": "src/io/files.js",
11199            "line": 1571,
11200            "description": "<p>Writes the contents of a Table 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",
11201            "itemtype": "method",
11202            "name": "saveTable",
11203            "params": [
11204                {
11205                    "name": "Table",
11206                    "description": "<p>the Table object to save to a file</p>\n",
11207                    "type": "p5.Table"
11208                },
11209                {
11210                    "name": "filename",
11211                    "description": "<p>the filename to which the Table should be saved</p>\n",
11212                    "type": "String"
11213                },
11214                {
11215                    "name": "options",
11216                    "description": "<p>can be one of &quot;tsv&quot;, &quot;csv&quot;, or &quot;html&quot;</p>\n",
11217                    "type": "String",
11218                    "optional": true
11219                }
11220            ],
11221            "example": [
11222                "\n<div><code>\n var 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 var 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>"
11223            ],
11224            "alt": "no image displayed",
11225            "class": "p5",
11226            "module": "IO",
11227            "submodule": "Output"
11228        },
11229        {
11230            "file": "src/io/p5.Table.js",
11231            "line": 11,
11232            "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 loadTable method.</p>\n<p>To save tables to your computer, use the save method\n or the saveTable 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>",
11233            "class": "p5.Table",
11234            "module": "IO",
11235            "submodule": "Table"
11236        },
11237        {
11238            "file": "src/io/p5.Table.js",
11239            "line": 45,
11240            "itemtype": "property",
11241            "name": "columns",
11242            "type": "String[]",
11243            "class": "p5.Table",
11244            "module": "IO",
11245            "submodule": "Table"
11246        },
11247        {
11248            "file": "src/io/p5.Table.js",
11249            "line": 50,
11250            "itemtype": "property",
11251            "name": "rows",
11252            "type": "p5.TableRow[]",
11253            "class": "p5.Table",
11254            "module": "IO",
11255            "submodule": "Table"
11256        },
11257        {
11258            "file": "src/io/p5.Table.js",
11259            "line": 56,
11260            "description": "<p>Use addRow() to add a new row of data to a p5.Table 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 set().</p>\n<p>If a p5.TableRow object is included as a parameter, then that row is\nduplicated and added to the table.</p>\n",
11261            "itemtype": "method",
11262            "name": "addRow",
11263            "params": [
11264                {
11265                    "name": "row",
11266                    "description": "<p>row to be added to the table</p>\n",
11267                    "type": "p5.TableRow",
11268                    "optional": true
11269                }
11270            ],
11271            "example": [
11272                "\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 var 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 var 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 (var r = 0; r < table.getRowCount(); r++)\n   for (var c = 0; c < table.getColumnCount(); c++)\n     print(table.getString(r, c));\n }\n </code>\n </div>"
11273            ],
11274            "alt": "no image displayed",
11275            "class": "p5.Table",
11276            "module": "IO",
11277            "submodule": "Table"
11278        },
11279        {
11280            "file": "src/io/p5.Table.js",
11281            "line": 119,
11282            "description": "<p>Removes a row from the table object.</p>\n",
11283            "itemtype": "method",
11284            "name": "removeRow",
11285            "params": [
11286                {
11287                    "name": "id",
11288                    "description": "<p>ID number of the row to remove</p>\n",
11289                    "type": "Integer"
11290                }
11291            ],
11292            "example": [
11293                "\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\nvar 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 (var r = 0; r < table.getRowCount(); r++)\n    for (var c = 0; c < table.getColumnCount(); c++)\n      print(table.getString(r, c));\n}\n</code>\n</div>"
11294            ],
11295            "alt": "no image displayed",
11296            "class": "p5.Table",
11297            "module": "IO",
11298            "submodule": "Table"
11299        },
11300        {
11301            "file": "src/io/p5.Table.js",
11302            "line": 167,
11303            "description": "<p>Returns a reference to the specified p5.TableRow. The reference\ncan then be used to get and set values of the selected row.</p>\n",
11304            "itemtype": "method",
11305            "name": "getRow",
11306            "params": [
11307                {
11308                    "name": "rowID",
11309                    "description": "<p>ID number of the row to get</p>\n",
11310                    "type": "Integer"
11311                }
11312            ],
11313            "return": {
11314                "description": "p5.TableRow object",
11315                "type": "p5.TableRow"
11316            },
11317            "example": [
11318                "\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\nvar 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  var row = table.getRow(1);\n  //print it column by column\n  //note: a row is an object, not an array\n  for (var c = 0; c < table.getColumnCount(); c++) {\n    print(row.getString(c));\n  }\n}\n</code>\n</div>"
11319            ],
11320            "alt": "no image displayed",
11321            "class": "p5.Table",
11322            "module": "IO",
11323            "submodule": "Table"
11324        },
11325        {
11326            "file": "src/io/p5.Table.js",
11327            "line": 213,
11328            "description": "<p>Gets all rows from the table. Returns an array of p5.TableRows.</p>\n",
11329            "itemtype": "method",
11330            "name": "getRows",
11331            "return": {
11332                "description": "Array of p5.TableRows",
11333                "type": "p5.TableRow[]"
11334            },
11335            "example": [
11336                "\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 var 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 var rows = table.getRows();\n\n //warning: rows is an array of objects\n for (var r = 0; r < rows.length; r++) {\n   rows[r].set('name', 'Unicorn');\n }\n\n //print the results\n for (r = 0; r < table.getRowCount(); r++)\n   for (var c = 0; c < table.getColumnCount(); c++)\n     print(table.getString(r, c));\n }\n </code>\n </div>"
11337            ],
11338            "alt": "no image displayed",
11339            "class": "p5.Table",
11340            "module": "IO",
11341            "submodule": "Table"
11342        },
11343        {
11344            "file": "src/io/p5.Table.js",
11345            "line": 262,
11346            "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",
11347            "itemtype": "method",
11348            "name": "findRow",
11349            "params": [
11350                {
11351                    "name": "value",
11352                    "description": "<p>The value to match</p>\n",
11353                    "type": "String"
11354                },
11355                {
11356                    "name": "column",
11357                    "description": "<p>ID number or title of the\n                               column to search</p>\n",
11358                    "type": "Integer|String"
11359                }
11360            ],
11361            "return": {
11362                "description": "",
11363                "type": "p5.TableRow"
11364            },
11365            "example": [
11366                "\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 var 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 var row = table.findRow('Zebra', 'name');\n //find the corresponding species\n print(row.getString('species'));\n }\n </code>\n </div>"
11367            ],
11368            "alt": "no image displayed",
11369            "class": "p5.Table",
11370            "module": "IO",
11371            "submodule": "Table"
11372        },
11373        {
11374            "file": "src/io/p5.Table.js",
11375            "line": 327,
11376            "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",
11377            "itemtype": "method",
11378            "name": "findRows",
11379            "params": [
11380                {
11381                    "name": "value",
11382                    "description": "<p>The value to match</p>\n",
11383                    "type": "String"
11384                },
11385                {
11386                    "name": "column",
11387                    "description": "<p>ID number or title of the\n                               column to search</p>\n",
11388                    "type": "Integer|String"
11389                }
11390            ],
11391            "return": {
11392                "description": "An Array of TableRow objects",
11393                "type": "p5.TableRow[]"
11394            },
11395            "example": [
11396                "\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 var 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 var 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 var rows = table.findRows('Goat', 'name');\n print(rows.length + ' Goats found');\n }\n </code>\n </div>"
11397            ],
11398            "alt": "no image displayed",
11399            "class": "p5.Table",
11400            "module": "IO",
11401            "submodule": "Table"
11402        },
11403        {
11404            "file": "src/io/p5.Table.js",
11405            "line": 396,
11406            "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",
11407            "itemtype": "method",
11408            "name": "matchRow",
11409            "params": [
11410                {
11411                    "name": "regexp",
11412                    "description": "<p>The regular expression to match</p>\n",
11413                    "type": "String|RegExp"
11414                },
11415                {
11416                    "name": "column",
11417                    "description": "<p>The column ID (number) or\n                                 title (string)</p>\n",
11418                    "type": "String|Integer"
11419                }
11420            ],
11421            "return": {
11422                "description": "TableRow object",
11423    
11423            "type": "p5.TableRow"
11424            },
11425            "example": [
11426                "\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\nvar 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  var mammal = table.matchRow(new RegExp('ant'), 1);\n  print(mammal.getString(1));\n  //Output \"Panthera pardus\"\n}\n</code>\n</div>\n"
11427            ],
11428            "class": "p5.Table",
11429            "module": "IO",
11430            "submodule": "Table"
11431        },
11432        {
11433            "file": "src/io/p5.Table.js",
11434            "line": 455,
11435            "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",
11436            "itemtype": "method",
11437            "name": "matchRows",
11438            "params": [
11439                {
11440                    "name": "regexp",
11441                    "description": "<p>The regular expression to match</p>\n",
11442                    "type": "String"
11443                },
11444                {
11445                    "name": "column",
11446                    "description": "<p>The column ID (number) or\n                                 title (string)</p>\n",
11447                    "type": "String|Integer",
11448                    "optional": true
11449                }
11450            ],
11451            "return": {
11452                "description": "An Array of TableRow objects",
11453                "type": "p5.TableRow[]"
11454            },
11455            "example": [
11456                "\n<div class=\"norender\">\n<code>\nvar table;\n\nfunction setup() {\n  table = new p5.Table();\n\n  table.addColumn('name');\n  table.addColumn('type');\n\n  var 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  var rows = table.matchRows('R.*', 'type');\n  for (var i = 0; i < rows.length; 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>"
11457            ],
11458            "class": "p5.Table",
11459            "module": "IO",
11460            "submodule": "Table"
11461        },
11462        {
11463            "file": "src/io/p5.Table.js",
11464            "line": 522,
11465            "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",
11466            "itemtype": "method",
11467            "name": "getColumn",
11468            "params": [
11469                {
11470                    "name": "column",
11471                    "description": "<p>String or Number of the column to return</p>\n",
11472                    "type": "String|Number"
11473                }
11474            ],
11475            "return": {
11476                "description": "Array of column values",
11477                "type": "Array"
11478            },
11479            "example": [
11480                "\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 var 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>"
11481            ],
11482            "alt": "no image displayed",
11483            "class": "p5.Table",
11484            "module": "IO",
11485            "submodule": "Table"
11486        },
11487        {
11488            "file": "src/io/p5.Table.js",
11489            "line": 575,
11490            "description": "<p>Removes all rows from a Table. While all rows are removed,\ncolumns and column titles are maintained.</p>\n",
11491            "itemtype": "method",
11492            "name": "clearRows",
11493            "example": [
11494                "\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 var 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>"
11495            ],
11496            "alt": "no image displayed",
11497            "class": "p5.Table",
11498            "module": "IO",
11499            "submodule": "Table"
11500        },
11501        {
11502            "file": "src/io/p5.Table.js",
11503            "line": 617,
11504            "description": "<p>Use addColumn() to add a new column to a Table 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",
11505            "itemtype": "method",
11506            "name": "addColumn",
11507            "params": [
11508                {
11509                    "name": "title",
11510                    "description": "<p>title of the given column</p>\n",
11511                    "type": "String",
11512                    "optional": true
11513                }
11514            ],
11515            "example": [
11516                "\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 var 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 (var r = 0; r < table.getRowCount(); r++)\n   for (var c = 0; c < table.getColumnCount(); c++)\n     print(table.getString(r, c));\n }\n </code>\n </div>"
11517            ],
11518            "alt": "no image displayed",
11519            "class": "p5.Table",
11520            "module": "IO",
11521            "submodule": "Table"
11522        },
11523        {
11524            "file": "src/io/p5.Table.js",
11525            "line": 668,
11526            "description": "<p>Returns the total number of columns in a Table.</p>\n",
11527            "itemtype": "method",
11528            "name": "getColumnCount",
11529            "return": {
11530                "description": "Number of columns in this table",
11531                "type": "Integer"
11532            },
11533            "example": [
11534                "\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 var 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 var numOfColumn = table.getColumnCount();\n text('There are ' + numOfColumn + ' columns in the table.', 100, 50);\n }\n </code>\n </div>"
11535            ],
11536            "class": "p5.Table",
11537            "module": "IO",
11538            "submodule": "Table"
11539        },
11540        {
11541            "file": "src/io/p5.Table.js",
11542            "line": 704,
11543            "description": "<p>Returns the total number of rows in a Table.</p>\n",
11544            "itemtype": "method",
11545            "name": "getRowCount",
11546            "return": {
11547                "description": "Number of rows in this table",
11548                "type": "Integer"
11549            },
11550            "example": [
11551                "\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 var 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>"
11552            ],
11553            "class": "p5.Table",
11554            "module": "IO",
11555            "submodule": "Table"
11556        },
11557        {
11558            "file": "src/io/p5.Table.js",
11559            "line": 740,
11560            "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>",
11561            "itemtype": "method",
11562            "name": "removeTokens",
11563            "params": [
11564                {
11565                    "name": "chars",
11566                    "description": "<p>String listing characters to be removed</p>\n",
11567                    "type": "String"
11568                },
11569                {
11570                    "name": "column",
11571                    "description": "<p>Column ID (number)\n                                 or name (string)</p>\n",
11572                    "type": "String|Integer",
11573                    "optional": true
11574                }
11575            ],
11576            "example": [
11577                "\n <div class=\"norender\"><code>\n function setup() {\n var table = new p5.Table();\n\n table.addColumn('name');\n table.addColumn('type');\n\n var 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>"
11578            ],
11579            "class": "p5.Table",
11580            "module": "IO",
11581            "submodule": "Table"
11582        },
11583        {
11584            "file": "src/io/p5.Table.js",
11585            "line": 814,
11586            "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",
11587            "itemtype": "method",
11588            "name": "trim",
11589            "params": [
11590                {
11591                    "name": "column",
11592                    "description": "<p>Column ID (number)\n                                 or name (string)</p>\n",
11593                    "type": "String|Integer",
11594                    "optional": true
11595                }
11596            ],
11597            "example": [
11598                "\n <div class=\"norender\"><code>\n function setup() {\n var table = new p5.Table();\n\n table.addColumn('name');\n table.addColumn('type');\n\n var 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>"
11599            ],
11600            "class": "p5.Table",
11601            "module": "IO",
11602            "submodule": "Table"
11603        },
11604        {
11605            "file": "src/io/p5.Table.js",
11606            "line": 878,
11607            "description": "<p>Use removeColumn() 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).\nremoveC
11607olumn(0) would remove the first column, removeColumn(1)\nwould remove the second column, and so on.</p>\n",
11608            "itemtype": "method",
11609            "name": "removeColumn",
11610            "params": [
11611                {
11612                    "name": "column",
11613                    "description": "<p>columnName (string) or ID (number)</p>\n",
11614                    "type": "String|Integer"
11615                }
11616            ],
11617            "example": [
11618                "\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 var 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>"
11619            ],
11620            "alt": "no image displayed",
11621            "class": "p5.Table",
11622            "module": "IO",
11623            "submodule": "Table"
11624        },
11625        {
11626            "file": "src/io/p5.Table.js",
11627            "line": 944,
11628            "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",
11629            "itemtype": "method",
11630            "name": "set",
11631            "params": [
11632                {
11633                    "name": "row",
11634                    "description": "<p>row ID</p>\n",
11635                    "type": "Integer"
11636                },
11637                {
11638                    "name": "column",
11639                    "description": "<p>column ID (Number)\n                              or title (String)</p>\n",
11640                    "type": "String|Integer"
11641                },
11642                {
11643                    "name": "value",
11644                    "description": "<p>value to assign</p>\n",
11645                    "type": "String|Number"
11646                }
11647            ],
11648            "example": [
11649                "\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\nvar 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 (var r = 0; r < table.getRowCount(); r++)\n    for (var c = 0; c < table.getColumnCount(); c++)\n      print(table.getString(r, c));\n}\n</code>\n</div>"
11650            ],
11651            "alt": "no image displayed",
11652            "class": "p5.Table",
11653            "module": "IO",
11654            "submodule": "Table"
11655        },
11656        {
11657            "file": "src/io/p5.Table.js",
11658            "line": 994,
11659            "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",
11660            "itemtype": "method",
11661            "name": "setNum",
11662            "params": [
11663                {
11664                    "name": "row",
11665                    "description": "<p>row ID</p>\n",
11666                    "type": "Integer"
11667                },
11668                {
11669                    "name": "column",
11670                    "description": "<p>column ID (Number)\n                              or title (String)</p>\n",
11671                    "type": "String|Integer"
11672                },
11673                {
11674                    "name": "value",
11675                    "description": "<p>value to assign</p>\n",
11676                    "type": "Number"
11677                }
11678            ],
11679            "example": [
11680                "\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\nvar 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>"
11681            ],
11682            "alt": "no image displayed",
11683            "class": "p5.Table",
11684            "module": "IO",
11685            "submodule": "Table"
11686        },
11687        {
11688            "file": "src/io/p5.Table.js",
11689            "line": 1040,
11690            "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",
11691            "itemtype": "method",
11692            "name": "setString",
11693            "params": [
11694                {
11695                    "name": "row",
11696                    "description": "<p>row ID</p>\n",
11697                    "type": "Integer"
11698                },
11699                {
11700                    "name": "column",
11701                    "description": "<p>column ID (Number)\n                              or title (String)</p>\n",
11702                    "type": "String|Integer"
11703                },
11704                {
11705                    "name": "value",
11706                    "description": "<p>value to assign</p>\n",
11707                    "type": "String"
11708                }
11709            ],
11710            "example": [
11711                "\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\nvar 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  var 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>"
11712            ],
11713            "alt": "no image displayed",
11714            "class": "p5.Table",
11715            "module": "IO",
11716            "submodule": "Table"
11717        },
11718        {
11719            "file": "src/io/p5.Table.js",
11720            "line": 1085,
11721            "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",
11722            "itemtype": "method",
11723            "name": "get",
11724            "params": [
11725                {
11726                    "name": "row",
11727                    "description": "<p>row ID</p>\n",
11728                    "type": "Integer"
11729                },
11730                {
11731                    "name": "column",
11732                    "description": "<p>columnName (string) or\n                                  ID (number)</p>\n",
11733                    "type": "String|Integer"
11734                }
11735            ],
11736            "return": {
11737                "description": "",
11738                "type": "String|Number"
11739            },
11740            "example": [
11741                "\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\nvar 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>"
11742            ],
11743            "alt": "no image displayed",
11744            "class": "p5.Table",
11745            "module": "IO",
11746            "submodule": "Table"
11747        },
11748        {
11749            "file": "src/io/p5.Table.js",
11750            "line": 1132,
11751            "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",
11752            "itemtype": "method",
11753            "name": "getNum",
11754            "params": [
11755                {
11756                    "name": "row",
11757                    "description": "<p>row ID</p>\n",
11758                    "type": "Integer"
11759                },
11760                {
11761                    "name": "column",
11762                    "description": "<p>columnName (string) or\n                                  ID (number)</p>\n",
11763                    "type": "String|Integer"
11764                }
11765            ],
11766            "return": {
11767                "description": "",
11768                "type": "Number"
11769            },
11770            "example": [
11771                "\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\nvar 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>"
11772            ],
11773            "alt": "no image displayed",
11774            "class": "p5.Table",
11775            "module": "IO",
11776            "submodule": "Table"
11777        },
11778        {
11779            "file": "src/io/p5.Table.js",
11780            "line": 1177,
11781            "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",
11782            "itemtype": "method",
11783            "name": "getString",
11784            "params": [
11785                {
11786                    "name": "row",
11787                    "description": "<p>row ID</p>\n",
11788                    "type": "Integer"
11789                },
11790                {
11791                    "name": "column",
11792                    "description": "<p>columnName (string) or\n                                  ID (number)</p>\n",
11793                    "type": "String|Integer"
11794                }
11795            ],
11796            "return": {
11797                "description": "",
11798                "type": "String"
11799            },
11800            "example": [
11801                "\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\nvar 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>"
11802            ],
11803            "alt": "no image displayed",
11804            "class": "p5.Table",
11805            "module": "IO",
11806            "submodule": "Table"
11807        },
11808        {
11809            "file": "src/io/p5.Table.js",
11810            "line": 1230,
11811            "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",
11812            "itemtype": "method",
11813            "name": "getObject",
11814            "params": [
11815                {
11816                    "name": "headerColumn",
11817                    "description": "<p>Name of the column which should be used to\n                             title each row object (optional)</p>\n",
11818                    "type": "String",
11819                    "optional": true
11820                }
11821            ],
11822            "return": {
11823                "description": "",
11824                "type": "Object"
11825            },
11826            "example": [
11827                "\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\nvar 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  var tableObject = table.getObject();\n\n  print(tableObject);\n  //outputs an object\n}\n</code>\n</div>"
11828            ],
11829            "alt": "no image displayed",
11830            "class": "p5.Table",
11831            "module": "IO",
11832            "submodule": "Table"
11833        },
11834        {
11835            "file": "src/io/p5.Table.js",
11836            "line": 1294,
11837            "description": "<p>Retrieves all table data and returns it as a multidimensional array.</p>\n",
11838            "itemtype": "method",
11839            "name": "getArray",
11840            "return": {
11841                "description": "",
11842                "type": "Array"
11843            },
11844            "example": [
11845                "\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\nvar 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  var tableArray = table.getArray();\n  for (var i = 0; i < tableArray.length;
11845 i++) {\n    print(tableArray[i]);\n  }\n}\n</code>\n</div>"
11846            ],
11847            "alt": "no image displayed",
11848            "class": "p5.Table",
11849            "module": "IO",
11850            "submodule": "Table"
11851        },
11852        {
11853            "file": "src/io/p5.TableRow.js",
11854            "line": 42,
11855            "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",
11856            "itemtype": "method",
11857            "name": "set",
11858            "params": [
11859                {
11860                    "name": "column",
11861                    "description": "<p>Column ID (Number)\n                              or Title (String)</p>\n",
11862                    "type": "String|Integer"
11863                },
11864                {
11865                    "name": "value",
11866                    "description": "<p>The value to be stored</p>\n",
11867                    "type": "String|Number"
11868                }
11869            ],
11870            "example": [
11871                "\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 var 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 var rows = table.getRows();\n for (var 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>"
11872            ],
11873            "alt": "no image displayed",
11874            "class": "p5.TableRow",
11875            "module": "IO",
11876            "submodule": "Table"
11877        },
11878        {
11879            "file": "src/io/p5.TableRow.js",
11880            "line": 104,
11881            "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",
11882            "itemtype": "method",
11883            "name": "setNum",
11884            "params": [
11885                {
11886                    "name": "column",
11887                    "description": "<p>Column ID (Number)\n                              or Title (String)</p>\n",
11888                    "type": "String|Integer"
11889                },
11890                {
11891                    "name": "value",
11892                    "description": "<p>The value to be stored\n                              as a Float</p>\n",
11893                    "type": "Number|String"
11894                }
11895            ],
11896            "example": [
11897                "\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 var 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 var rows = table.getRows();\n for (var r = 0; r < rows.length; r++) {\n   rows[r].setNum('id', r + 10);\n }\n\n print(table.getArray());\n }\n </code></div>"
11898            ],
11899            "alt": "no image displayed",
11900            "class": "p5.TableRow",
11901            "module": "IO",
11902            "submodule": "Table"
11903        },
11904        {
11905            "file": "src/io/p5.TableRow.js",
11906            "line": 148,
11907            "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",
11908            "itemtype": "method",
11909            "name": "setString",
11910            "params": [
11911                {
11912                    "name": "column",
11913                    "description": "<p>Column ID (Number)\n                              or Title (String)</p>\n",
11914                    "type": "String|Integer"
11915                },
11916                {
11917                    "name": "value",
11918                    "description": "<p>The value to be stored\n                              as a String</p>\n",
11919                    "type": "String|Number|Boolean|Object"
11920                }
11921            ],
11922            "example": [
11923                "\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 var 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 var rows = table.getRows();\n for (var r = 0; r < rows.length; r++) {\n   var name = rows[r].getString('name');\n   rows[r].setString('name', 'A ' + name + ' named George');\n }\n\n print(table.getArray());\n }\n </code></div>"
11924            ],
11925            "alt": "no image displayed",
11926            "class": "p5.TableRow",
11927            "module": "IO",
11928            "submodule": "Table"
11929        },
11930        {
11931            "file": "src/io/p5.TableRow.js",
11932            "line": 193,
11933            "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",
11934            "itemtype": "method",
11935            "name": "get",
11936            "params": [
11937                {
11938                    "name": "column",
11939                    "description": "<p>columnName (string) or\n                                 ID (number)</p>\n",
11940                    "type": "String|Integer"
11941                }
11942            ],
11943            "return": {
11944                "description": "",
11945                "type": "String|Number"
11946            },
11947            "example": [
11948                "\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 var 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 var names = [];\n var rows = table.getRows();\n for (var r = 0; r < rows.length; r++) {\n   names.push(rows[r].get('name'));\n }\n\n print(names);\n }\n </code></div>"
11949            ],
11950            "alt": "no image displayed",
11951            "class": "p5.TableRow",
11952            "module": "IO",
11953            "submodule": "Table"
11954        },
11955        {
11956            "file": "src/io/p5.TableRow.js",
11957            "line": 241,
11958            "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",
11959            "itemtype": "method",
11960            "name": "getNum",
11961            "params": [
11962                {
11963                    "name": "column",
11964                    "description": "<p>columnName (string) or\n                                 ID (number)</p>\n",
11965                    "type": "String|Integer"
11966                }
11967            ],
11968            "return": {
11969                "description": "Float Floating point number",
11970                "type": "Number"
11971            },
11972            "example": [
11973                "\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 var 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 var rows = table.getRows();\n var minId = Infinity;\n var maxId = -Infinity;\n for (var r = 0; r < rows.length; r++) {\n   var 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>"
11974            ],
11975            "alt": "no image displayed",
11976            "class": "p5.TableRow",
11977            "module": "IO",
11978            "submodule": "Table"
11979        },
11980        {
11981            "file": "src/io/p5.TableRow.js",
11982            "line": 297,
11983            "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",
11984            "itemtype": "method",
11985            "name": "getString",
11986            "params": [
11987                {
11988                    "name": "column",
11989                    "description": "<p>columnName (string) or\n                                 ID (number)</p>\n",
11990                    "type": "String|Integer"
11991                }
11992            ],
11993            "return": {
11994                "description": "String",
11995                "type": "String"
11996            },
11997            "example": [
11998                "\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 var 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 var rows = table.getRows();\n var longest = '';\n for (var r = 0; r < rows.length; r++) {\n   var 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>"
11999            ],
12000            "alt": "no image displayed",
12001            "class": "p5.TableRow",
12002            "module": "IO",
12003            "submodule": "Table"
12004        },
12005        {
12006            "file": "src/io/p5.XML.js",
12007            "line": 64,
12008            "description": "<p>Gets a copy of the element&#39;s parent. Returns the parent as another\np5.XML object.</p>\n",
12009            "itemtype": "method",
12010            "name": "getParent",
12011            "return": {
12012                "description": "element parent",
12013                "type": "p5.XML"
12014            },
12015            "example": [
12016                "\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\nvar xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  var children = xml.getChildren('animal');\n  var parent = children[1].getParent();\n  print(parent.getName());\n}\n\n// Sketch prints:\n// mammals\n</code></div>"
12017            ],
12018            "class": "p5.XML",
12019            "module": "IO",
12020            "submodule": "XML"
12021        },
12022        {
12023            "file": "src/io/p5.XML.js",
12024            "line": 102,
12025            "description": "<p>Gets the element&#39;s full name, which is returned as a String.</p>\n",
12026            "itemtype": "method",
12027            "name": "getName",
12028            "return": {
12029                "description": "the name of the node",
12030                "type": "String"
12031            },
12032            "example": [
12033                "&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 var 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>"
12034            ],
12035            "class": "p5.XML",
12036            "module": "IO",
12037            "submodule": "XML"
12038        },
12039        {
12040            "file": "src/io/p5.XML.js",
12041            "line": 137,
12042            "description": "<p>Sets the element&#39;s name, which is specified as a String.</p>\n",
12043            "itemtype": "method",
12044            "name": "setName",
12045            "params": [
12046                {
12047                    "name": "the",
12048                    "description": "<p>new name of the node</p>\n",
12049                    "type": "String"
12050                }
12051            ],
12052            "example": [
12053                "&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\nvar 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>"
12054            ],
12055            "class": "p5.XML",
12056            "module": "IO",
12057            "submodule": "XML"
12058        },
12059        {
12060            "file": "src/io/p5.XML.js",
12061            "line": 175,
12062            "description": "<p>Checks whether or not the element has any children, and returns the result\nas a boolean.</p>\n",
12063            "itemtype": "method",
12064            "name": "hasChildren",
12065            "return": {
12066                "description": "",
12067                "type": "Boolean"
12068            },
12069            "example": [
12070                "&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\nvar 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>"
12071            ],
12072            "class": "p5.XML",
12073            "module": "IO",
12074            "submodule": "XML"
12075        },
12076        {
12077            "file": "src/io/p5.XML.js",
12078            "line": 211,
12079            "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 getName()\non each child element individually.</p>\n",
12080            "itemtype": "method",
12081            "name": "listChildren",
12082            "return": {
12083                "description": "names of the children of the element",
12084                "type": "String[]"
12085            },
12086            "example": [
12087                "&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\nvar 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>"
12088            ],
12089            "class": "p5.XML",
12090            "module": "IO",
12091            "submodule": "XML"
12092        },
12093        {
12094            "file": "src/io/p5.XML.js",
12095            "line": 250,
12096            "description": "<p>Returns all of the element&#39;s children as an array of p5.XML objects. When\nthe name parameter is specified, then it will return all children that match\nthat name.</p>\n",
12097            "itemtype": "method",
12098            "name": "getChildren",
12099            "params": [
12100                {
12101  
12101                  "name": "name",
12102                    "description": "<p>element name</p>\n",
12103                    "type": "String",
12104                    "optional": true
12105                }
12106            ],
12107            "return": {
12108                "description": "children of the element",
12109                "type": "p5.XML[]"
12110            },
12111            "example": [
12112                "&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\nvar xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  var animals = xml.getChildren('animal');\n\n  for (var i = 0; i < animals.length; i++) {\n    print(animals[i].getContent());\n  }\n}\n\n// Sketch prints:\n// \"Goat\"\n// \"Leopard\"\n// \"Zebra\"\n</code></div>"
12113            ],
12114            "class": "p5.XML",
12115            "module": "IO",
12116            "submodule": "XML"
12117        },
12118        {
12119            "file": "src/io/p5.XML.js",
12120            "line": 300,
12121            "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",
12122            "itemtype": "method",
12123            "name": "getChild",
12124            "params": [
12125                {
12126                    "name": "name",
12127                    "description": "<p>element name or index</p>\n",
12128                    "type": "String|Integer"
12129                }
12130            ],
12131            "return": {
12132                "description": "",
12133                "type": "p5.XML"
12134            },
12135            "example": [
12136                "&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\nvar xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  var firstChild = xml.getChild('animal');\n  print(firstChild.getContent());\n}\n\n// Sketch prints:\n// \"Goat\"\n</code></div>\n<div class='norender'><code>\nvar xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  var secondChild = xml.getChild(1);\n  print(secondChild.getContent());\n}\n\n// Sketch prints:\n// \"Leopard\"\n</code></div>"
12137            ],
12138            "class": "p5.XML",
12139            "module": "IO",
12140            "submodule": "XML"
12141        },
12142        {
12143            "file": "src/io/p5.XML.js",
12144            "line": 361,
12145            "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 p5.XML object.\nA reference to the newly created child is returned as an p5.XML object.</p>\n",
12146            "itemtype": "method",
12147            "name": "addChild",
12148            "params": [
12149                {
12150                    "name": "node",
12151                    "description": "<p>a p5.XML Object which will be the child to be added</p>\n",
12152                    "type": "p5.XML"
12153                }
12154            ],
12155            "example": [
12156                "\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\nvar xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  var child = new p5.XML();\n  child.setAttribute('id', '3');
12156\n  child.setAttribute('species', 'Ornithorhynchus anatinus');\n  child.setContent('Platypus');\n  xml.addChild(child);\n\n  var 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>"
12157            ],
12158            "class": "p5.XML",
12159            "module": "IO",
12160            "submodule": "XML"
12161        },
12162        {
12163            "file": "src/io/p5.XML.js",
12164            "line": 412,
12165            "description": "<p>Removes the element specified by name or index.</p>\n",
12166            "itemtype": "method",
12167            "name": "removeChild",
12168            "params": [
12169                {
12170                    "name": "name",
12171                    "description": "<p>element name or index</p>\n",
12172                    "type": "String|Integer"
12173                }
12174            ],
12175            "example": [
12176                "\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\nvar xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  xml.removeChild('animal');\n  var children = xml.getChildren();\n  for (var i = 0; i < children.length; i++) {\n    print(children[i].getContent());\n  }\n}\n\n// Sketch prints:\n// \"Leopard\"\n// \"Zebra\"\n</code></div>\n<div class='norender'><code>\nvar xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  xml.removeChild(1);\n  var children = xml.getChildren();\n  for (var i = 0; i < children.length; i++) {\n    print(children[i].getContent());\n  }\n}\n\n// Sketch prints:\n// \"Goat\"\n// \"Zebra\"\n</code></div>"
12177            ],
12178            "class": "p5.XML",
12179            "module": "IO",
12180            "submodule": "XML"
12181        },
12182        {
12183            "file": "src/io/p5.XML.js",
12184            "line": 484,
12185            "description": "<p>Counts the specified element&#39;s number of attributes, returned as an Number.</p>\n",
12186            "itemtype": "method",
12187            "name": "getAttributeCount",
12188            "return": {
12189                "description": "",
12190                "type": "Integer"
12191            },
12192            "example": [
12193                "\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\nvar xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  var firstChild = xml.getChild('animal');\n  print(firstChild.getAttributeCount());\n}\n\n// Sketch prints:\n// 2\n</code></div>"
12194            ],
12195            "class": "p5.XML",
12196            "module": "IO",
12197            "submodule": "XML"
12198        },
12199        {
12200            "file": "src/io/p5.XML.js",
12201            "line": 520,
12202            "description": "<p>Gets all of the specified element&#39;s attributes, and returns them as an\narray of Strings.</p>\n",
12203            "itemtype": "method",
12204            "name": "listAttributes",
12205            "return": {
12206                "description": "an array of strings containing the names of attributes",
12207                "type": "String[]"
12208            },
12209            "example": [
12210                "\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\nvar xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  var firstChild = xml.getChild('animal');\n  print(firstChild.listAttributes());\n}\n\n// Sketch prints:\n// [\"id\", \"species\"]\n</code></div>"
12211            ],
12212            "class": "p5.XML",
12213            "module": "IO",
12214            "submodule": "XML"
12215        },
12216        {
12217            "file": "src/io/p5.XML.js",
12218            "line": 557,
12219            "description": "<p>Checks whether or not an element has the specified attribute.</p>\n",
12220            "itemtype": "method",
12221            "name": "hasAttribute",
12222            "params": [
12223                {
12224                    "name": "the",
12225                    "description": "<p>attribute to be checked</p>\n",
12226                    "type": "String"
12227                }
12228            ],
12229            "return": {
12230                "description": "true if attribute found else false",
12231                "type": "Boolean"
12232            },
12233            "example": [
12234                "\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 var xml;\n\n function preload() {\n xml = loadXML('assets/mammals.xml');\n }\n\n function setup() {\n var 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>"
12235            ],
12236            "class": "p5.XML",
12237            "module": "IO",
12238            "submodule": "XML"
12239        },
12240        {
12241            "file": "src/io/p5.XML.js",
12242            "line": 596,
12243            "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",
12244            "itemtype": "method",
12245            "name": "getNum",
12246            "params": [
12247                {
12248                    "name": "name",
12249                    "description": "<p>the non-null full name of the attribute</p>\n",
12250                    "type": "String"
12251                },
12252                {
12253                    "name": "defaultValue",
12254                    "description": "<p>the default value of the attribute</p>\n",
12255                    "type": "Number",
12256                    "optional": true
12257                }
12258            ],
12259            "return": {
12260                "description": "",
12261                "type": "Number"
12262            },
12263            "example": [
12264                "\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\nvar xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  var firstChild = xml.getChild('animal');\n  print(firstChild.getNum('id'));\n}\n\n// Sketch prints:\n// 0\n</code></div>"
12265            ],
12266            "class": "p5.XML",
12267            "module": "IO",
12268            "submodule": "XML"
12269        },
12270        {
12271            "file": "src/io/p5.XML.js",
12272            "line": 637,
12273            "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",
12274            "itemtype": "method",
12275            "name": "getString",
12276            "params": [
12277                {
12278                    "name": "name",
12279                    "description": "<p>the non-null full name of the attribute</p>\n",
12280                    "type": "String"
12281                },
12282                {
12283                    "name": "defaultValue",
12284                    "description": "<p>the default value of the attribute</p>\n",
12285                    "type": "Number",
12286                    "optional": true
12287                }
12288            ],
12289            "return": {
12290                "description": "",
12291                "type": "String"
12292            },
12293            "example": [
12294                "\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\nvar xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  var firstChild = xml.getChild('animal');
12294\n  print(firstChild.getString('species'));\n}\n\n// Sketch prints:\n// \"Capra hircus\"\n</code></div>"
12295            ],
12296            "class": "p5.XML",
12297            "module": "IO",
12298            "submodule": "XML"
12299        },
12300        {
12301            "file": "src/io/p5.XML.js",
12302            "line": 678,
12303            "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",
12304            "itemtype": "method",
12305            "name": "setAttribute",
12306            "params": [
12307                {
12308                    "name": "name",
12309                    "description": "<p>the full name of the attribute</p>\n",
12310                    "type": "String"
12311                },
12312                {
12313                    "name": "value",
12314                    "description": "<p>the value of the attribute</p>\n",
12315                    "type": "Number|String|Boolean"
12316                }
12317            ],
12318            "example": [
12319                "\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\nvar xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  var 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>"
12320            ],
12321            "class": "p5.XML",
12322            "module": "IO",
12323            "submodule": "XML"
12324        },
12325        {
12326            "file": "src/io/p5.XML.js",
12327            "line": 721,
12328            "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",
12329            "itemtype": "method",
12330            "name": "getContent",
12331            "params": [
12332                {
12333                    "name": "defaultValue",
12334                    "description": "<p>value returned if no content is found</p>\n",
12335                    "type": "String",
12336                    "optional": true
12337                }
12338            ],
12339            "return": {
12340                "description": "",
12341                "type": "String"
12342            },
12343            "example": [
12344                "\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\nvar xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  var firstChild = xml.getChild('animal');\n  print(firstChild.getContent());\n}\n\n// Sketch prints:\n// \"Goat\"\n</code></div>"
12345            ],
12346            "class": "p5.XML",
12347            "module": "IO",
12348            "submodule": "XML"
12349        },
12350        {
12351            "file": "src/io/p5.XML.js",
12352            "line": 759,
12353            "description": "<p>Sets the element&#39;s content.</p>\n",
12354            "itemtype": "method",
12355            "name": "setContent",
12356            "params": [
12357                {
12358                    "name": "text",
12359                    "description": "<p>the new content</p>\n",
12360                    "type": "String"
12361                }
12362            ],
12363            "example": [
12364                "\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\nvar xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  var 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>"
12365            ],
12366            "class": "p5.XML",
12367            "module": "IO",
12368            "submodule": "XML"
12369        },
12370        {
12371            "file": "src/io/p5.XML.js",
12372            "line": 801,
12373            "description": "<p>This method is called while the parsing of XML (when loadXML() is\ncalled). The difference between this method and the setContent()\nmethod defined later is that this one is used to set the content\nwhen the node in question has more nodes under it and so on and\nnot directly text content. While in the other one is used when\nthe node in question directly has text inside it.</p>\n",
12374            "class": "p5.XML",
12375            "module": "IO",
12376            "submodule": "XML"
12377        },
12378        {
12379            "file": "src/io/p5.XML.js",
12380            "line": 818,
12381            "description": "<p>This method is called while the parsing of XML (when loadXML() is\ncalled). The XML node is passed and its attributes are stored in the\np5.XML&#39;s attribute Object.</p>\n",
12382            "class": "p5.XML",
12383            "module": "IO",
12384            "submodule": "XML"
12385        },
12386        {
12387            "file": "src/math/calculation.js",
12388            "line": 12,
12389            "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",
12390            "itemtype": "method",
12391            "name": "abs",
12392            "params": [
12393                {
12394                    "name": "n",
12395                    "description": "<p>number to compute</p>\n",
12396                    "type": "Number"
12397                }
12398            ],
12399            "return": {
12400                "description": "absolute value of given number",
12401                "type": "Number"
12402            },
12403            "example": [
12404                "\n<div class = \"norender\"><code>\nfunction setup() {\n  var x = -3;\n  var y = abs(x);\n\n  print(x); // -3\n  print(y); // 3\n}\n</code></div>"
12405            ],
12406            "alt": "no image displayed",
12407            "class": "p5",
12408            "module": "Math",
12409            "submodule": "Calculation"
12410        },
12411        {
12412            "file": "src/math/calculation.js",
12413            "line": 36,
12414            "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",
12415            "itemtype": "method",
12416            "name": "ceil",
12417            "params": [
12418                {
12419                    "name": "n",
12420                    "description": "<p>number to round up</p>\n",
12421                    "type": "Number"
12422                }
12423            ],
12424            "return": {
12425                "description": "rounded up number",
12426                "type": "Integer"
12427            },
12428            "example": [
12429                "\n<div><code>\nfunction draw() {\n  background(200);\n  // map, mouseX between 0 and 5.\n  var ax = map(mouseX, 0, 100, 0, 5);\n  var ay = 66;\n\n  //Get the ceiling of the mapped number.\n  var bx = ceil(map(mouseX, 0, 100, 0, 5));\n  var 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>"
12430            ],
12431            "alt": "2 horizontal lines & number sets. increase with mouse x. bottom to 2 decimals",
12432            "class": "p5",
12433            "module": "Math",
12434            "submodule": "Calculation"
12435        },
12436        {
12437            "file": "src/math/calculation.js",
12438            "line": 76,
12439            "description": "<p>Constrains a value between a minimum and maximum value.</p>\n",
12440            "itemtype": "method",
12441            "name": "constrain",
12442            "params": [
12443                {
12444                    "name": "n",
12445                    "description": "<p>number to constrain</p>\n",
12446                    "type": "Number"
12447                },
12448                {
12449                    "name": "low",
12450                    "description": "<p>minimum limit</p>\n",
12451                    "type": "Number"
12452                },
12453                {
12454                    "name": "high",
12455                    "description": "<p>maximum limit</p>\n",
12456                    "type": "Number"
12457                }
12458            ],
12459            "return": {
12460                "description": "constrained number",
12461                "type": "Number"
12462            },
12463            "example": [
12464                "\n<div><code>\nfunction draw() {\n  background(200);\n\n  var leftWall = 25;\n  var rightWall = 75;\n\n  // xm is just the mouseX, while\n  // xc is the mouseX, but constrained\n  // between the leftWall and rightWall!\n  var xm = mouseX;\n  var 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>"
12465            ],
12466            "alt": "2 vertical lines. 2 ellipses move with mouse X 1 does not move passed lines",
12467            "class": "p5",
12468            "module": "Math",
12469            "submodule": "Calculation"
12470        },
12471        {
12472            "file": "src/math/calculation.js",
12473            "line": 121,
12474            "description": "<p>Calculates the distance between two points.</p>\n",
12475            "itemtype": "method",
12476            "name": "dist",
12477            "return": {
12478                "description": "distance between the two points",
12479                "type": "Number"
12480            },
12481            "example": [
12482                "\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  var x1 = 10;\n  var y1 = 90;\n  var x2 = mouseX;\n  var 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  var 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));
12482\n  text(nfc(d, 1), 0, -5);\n  pop();\n  // Fancy!\n}\n</code></div>"
12483            ],
12484            "alt": "2 ellipses joined by line. 1 ellipse moves with mouse X&Y. Distance displayed.",
12485            "class": "p5",
12486            "module": "Math",
12487            "submodule": "Calculation",
12488            "overloads": [
12489                {
12490                    "line": 121,
12491                    "params": [
12492                        {
12493                            "name": "x1",
12494                            "description": "<p>x-coordinate of the first point</p>\n",
12495                            "type": "Number"
12496                        },
12497                        {
12498                            "name": "y1",
12499                            "description": "<p>y-coordinate of the first point</p>\n",
12500                            "type": "Number"
12501                        },
12502                        {
12503                            "name": "x2",
12504                            "description": "<p>x-coordinate of the second point</p>\n",
12505                            "type": "Number"
12506                        },
12507                        {
12508                            "name": "y2",
12509                            "description": "<p>y-coordinate of the second point</p>\n",
12510                            "type": "Number"
12511                        }
12512                    ],
12513                    "return": {
12514                        "description": "distance between the two points",
12515                        "type": "Number"
12516                    }
12517                },
12518                {
12519                    "line": 165,
12520                    "params": [
12521                        {
12522                            "name": "x1",
12523                            "description": "",
12524                            "type": "Number"
12525                        },
12526                        {
12527                            "name": "y1",
12528                            "description": "",
12529                            "type": "Number"
12530                        },
12531                        {
12532                            "name": "z1",
12533                            "description": "<p>z-coordinate of the first point</p>\n",
12534                            "type": "Number"
12535                        },
12536                        {
12537                            "name": "x2",
12538                            "description": "",
12539                            "type": "Number"
12540                        },
12541                        {
12542                            "name": "y2",
12543                            "description": "",
12544                            "type": "Number"
12545                        },
12546                        {
12547                            "name": "z2",
12548                            "description": "<p>z-coordinate of the second point</p>\n",
12549                            "type": "Number"
12550                        }
12551                    ],
12552                    "return": {
12553                        "description": "distance between the two points",
12554                        "type": "Number"
12555                    }
12556                }
12557            ]
12558        },
12559        {
12560            "file": "src/math/calculation.js",
12561            "line": 190,
12562            "description": "<p>Returns Euler&#39;s number e (2.71828...) raised to the power of the n\nparameter. Maps to Math.exp().</p>\n",
12563            "itemtype": "method",
12564            "name": "exp",
12565            "params": [
12566                {
12567                    "name": "n",
12568                    "description": "<p>exponent to raise</p>\n",
12569                    "type": "Number"
12570                }
12571            ],
12572            "return": {
12573                "description": "e^n",
12574                "type": "Number"
12575            },
12576            "example": [
12577                "\n<div><code>\nfunction draw() {\n  background(200);\n\n  // Compute the exp() function with a value between 0 and 2\n  var xValue = map(mouseX, 0, width, 0, 2);\n  var yValue = exp(xValue);\n\n  var y = map(yValue, 0, 8, height, 0);\n\n  var 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 (var 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>"
12578            ],
12579            "alt": "ellipse moves along a curve with mouse x. e^n displayed.",
12580            "class": "p5",
12581            "module": "Math",
12582            "submodule": "Calculation"
12583        },
12584        {
12585            "file": "src/math/calculation.js",
12586            "line": 240,
12587            "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",
12588            "itemtype": "method",
12589            "name": "floor",
12590            "params": [
12591                {
12592                    "name": "n",
12593                    "description": "<p>number to round down</p>\n",
12594                    "type": "Number"
12595                }
12596            ],
12597            "return": {
12598                "description": "rounded down number",
12599                "type": "Integer"
12600            },
12601            "example": [
12602                "\n<div><code>\nfunction draw() {\n  background(200);\n  //map, mouseX between 0 and 5.\n  var ax = map(mouseX, 0, 100, 0, 5);\n  var ay = 66;\n\n  //Get the floor of the mapped number.\n  var bx = floor(map(mouseX, 0, 100, 0, 5));\n  var 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>"
12603            ],
12604            "alt": "2 horizontal lines & number sets. increase with mouse x. bottom to 2 decimals",
12605            "class": "p5",
12606            "module": "Math",
12607            "submodule": "Calculation"
12608        },
12609        {
12610            "file": "src/math/calculation.js",
12611            "line": 279,
12612            "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, etc. The lerp function is convenient for creating\
12612nmotion along a straight path and for drawing dotted lines.</p>\n",
12613            "itemtype": "method",
12614            "name": "lerp",
12615            "params": [
12616                {
12617                    "name": "start",
12618                    "description": "<p>first value</p>\n",
12619                    "type": "Number"
12620                },
12621                {
12622                    "name": "stop",
12623                    "description": "<p>second value</p>\n",
12624                    "type": "Number"
12625                },
12626                {
12627                    "name": "amt",
12628                    "description": "<p>number between 0.0 and 1.0</p>\n",
12629                    "type": "Number"
12630                }
12631            ],
12632            "return": {
12633                "description": "lerped value",
12634                "type": "Number"
12635            },
12636            "example": [
12637                "\n<div><code>\nfunction setup() {\n  background(200);\n  var a = 20;\n  var b = 80;\n  var c = lerp(a, b, 0.2);\n  var d = lerp(a, b, 0.5);\n  var e = lerp(a, b, 0.8);\n\n  var 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>"
12638            ],
12639            "alt": "5 points horizontally staggered mid-canvas. mid 3 are grey, outer black",
12640            "class": "p5",
12641            "module": "Math",
12642            "submodule": "Calculation"
12643        },
12644        {
12645            "file": "src/math/calculation.js",
12646            "line": 324,
12647            "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",
12648            "itemtype": "method",
12649            "name": "log",
12650            "params": [
12651                {
12652                    "name": "n",
12653                    "description": "<p>number greater than 0</p>\n",
12654                    "type": "Number"
12655                }
12656            ],
12657            "return": {
12658                "description": "natural logarithm of n",
12659                "type": "Number"
12660            },
12661            "example": [
12662                "\n<div><code>\nfunction draw() {\n  background(200);\n  var maxX = 2.8;\n  var maxY = 1.5;\n\n  // Compute the natural log of a value between 0 and maxX\n  var xValue = map(mouseX, 0, width, 0, maxX);\n  if (xValue > 0) {\n   // Cannot take the log of a negative number.\n    var yValue = log(xValue);\n    var y = map(yValue, -maxY, maxY, height, 0);\n\n    // Display the calculation occurring.\n    var 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 (var 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>"
12663            ],
12664            "alt": "ellipse moves along a curve with mouse x. natural logarithm of n displayed.",
12665            "class": "p5",
12666            "module": "Math",
12667            "submodule": "Calculation"
12668        },
12669        {
12670            "file": "src/math/calculation.js",
12671            "line": 379,
12672            "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, mag() is\na shortcut for writing dist(0, 0, x, y).</p>\n",
12673            "itemtype": "method",
12674            "name": "mag",
12675            "params": [
12676                {
12677                    "name": "a",
12678                    "description": "<p>first value</p>\n",
12679                    "type": "Number"
12680                },
12681                {
12682                    "name": "b",
12683                    "description": "<p>second value</p>\n",
12684                    "type": "Number"
12685                }
12686            ],
12687            "return": {
12688                "description": "magnitude of vector from (0,0) to (a,b)",
12689                "type": "Number"
12690            },
12691            "example": [
12692                "\n<div><code>\nfunction setup() {\n  var x1 = 20;\n  var x2 = 80;\n  var y1 = 30;\n  var 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>"
12693            ],
12694            "alt": "4 lines of different length radiate from top left of canvas.",
12695            "class": "p5",
12696            "module": "Math",
12697            "submodule": "Calculation"
12698        },
12699        {
12700            "file": "src/math/calculation.js",
12701            "line": 418,
12702            "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",
12703            "itemtype": "method",
12704            "name": "map",
12705            "params": [
12706                {
12707                    "name": "value",
12708                    "description": "<p>the incoming value to be converted</p>\n",
12709                    "type": "Number"
12710                },
12711                {
12712                    "name": "start1",
12713                    "description": "<p>lower bound of the value&#39;s current range</p>\n",
12714                    "type": "Number"
12715                },
12716                {
12717                    "name": "stop1",
12718                    "description": "<p>upper bound of the value&#39;s current range</p>\n",
12719                    "type": "Number"
12720                },
12721                {
12722                    "name": "start2",
12723                    "description": "<p>lower bound of the value&#39;s target range</p>\n",
12724                    "type": "Number"
12725                },
12726                {
12727                    "name": "stop2",
12728                    "description": "<p>upper bound of the value&#39;s target range</p>\n",
12729                    "type": "Number"
12730                },
12731                {
12732                    "name": "withinBounds",
12733                    "description": "<p>constrain the value to the newly mapped range</p>\n",
12734                    "type": "Boolean",
12735                    "optional": true
12736                }
12737            ],
12738            "return": {
12739                "description": "remapped number",
12740                "type": "Number"
12741            },
12742            "example": [
12743                "\n  <div><code>\nvar value = 25;\nvar 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  var 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  var x2 = map(mouseX, 0, width, 0, 100, true);\n  ellipse(x2, 75, 25, 25);\n}\n</code></div>"
12744            ],
12745            "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",
12746            "class": "p5",
12747            "module": "Math",
12748            "submodule": "Calculation"
12749        },
12750        {
12751            "file": "src/math/calculation.js",
12752            "line": 474,
12753            "description": "<p>Determines the largest value in a sequence of numbers, and then returns\nthat value. max() accepts any number of Number parameters, or an Array\nof any length.</p>\n",
12754            "itemtype": "method",
12755            "name": "max",
12756            "return": {
12757                "description": "maximum Number",
12758                "type": "Number"
12759            },
12760            "example": [
12761                "\n<div><code>\nfunction setup() {\n  // Change the elements in the array and run the sketch\n  // to show how max() works!\n  var 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  var spacing = 15;\n  var elemsY = 25;\n  for (var i = 0; i < numArray.length;
12761 i++) {\n    text(numArray[i], i * spacing, elemsY);\n  }\n  var maxX = 33;\n  var maxY = 80;\n  // Draw the Maximum value in the array.\n  textSize(32);\n  text(max(numArray), maxX, maxY);\n}\n</code></div>"
12762            ],
12763            "alt": "Small text at top reads: Array Elements 2 1 5 4 8 9. Large text at center: 9",
12764            "class": "p5",
12765            "module": "Math",
12766            "submodule": "Calculation",
12767            "overloads": [
12768                {
12769                    "line": 474,
12770                    "params": [
12771                        {
12772                            "name": "n0",
12773                            "description": "<p>Number to compare</p>\n",
12774                            "type": "Number"
12775                        },
12776                        {
12777                            "name": "n1",
12778                            "description": "<p>Number to compare</p>\n",
12779                            "type": "Number"
12780                        }
12781                    ],
12782                    "return": {
12783                        "description": "maximum Number",
12784                        "type": "Number"
12785                    }
12786                },
12787                {
12788                    "line": 510,
12789                    "params": [
12790                        {
12791                            "name": "nums",
12792                            "description": "<p>Numbers to compare</p>\n",
12793                            "type": "Number[]"
12794                        }
12795                    ],
12796                    "return": {
12797                        "description": "",
12798                        "type": "Number"
12799                    }
12800                }
12801            ]
12802        },
12803        {
12804            "file": "src/math/calculation.js",
12805            "line": 524,
12806            "description": "<p>Determines the smallest value in a sequence of numbers, and then returns\nthat value. min() accepts any number of Number parameters, or an Array\nof any length.</p>\n",
12807            "itemtype": "method",
12808            "name": "min",
12809            "return": {
12810                "description": "minimum Number",
12811                "type": "Number"
12812            },
12813            "example": [
12814                "\n<div><code>\nfunction setup() {\n  // Change the elements in the array and run the sketch\n  // to show how min() works!\n  var 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  var spacing = 15;\n  var elemsY = 25;\n  for (var i = 0; i < numArray.length; i++) {\n    text(numArray[i], i * spacing, elemsY);\n  }\n  var maxX = 33;\n  var maxY = 80;\n  // Draw the Minimum value in the array.\n  textSize(32);\n  text(min(numArray), maxX, maxY);\n}\n</code></div>"
12815            ],
12816            "alt": "Small text at top reads: Array Elements 2 1 5 4 8 9. Large text at center: 1",
12817            "class": "p5",
12818            "module": "Math",
12819            "submodule": "Calculation",
12820            "overloads": [
12821                {
12822                    "line": 524,
12823                    "params": [
12824                        {
12825                            "name": "n0",
12826                            "description": "<p>Number to compare</p>\n",
12827                            "type": "Number"
12828                        },
12829                        {
12830                            "name": "n1",
12831                            "description": "<p>Number to compare</p>\n",
12832                            "type": "Number"
12833                        }
12834                    ],
12835                    "return": {
12836                        "description": "minimum Number",
12837                        "type": "Number"
12838                    }
12839                },
12840                {
12841                    "line": 560,
12842                    "params": [
12843                        {
12844                            "name": "nums",
12845                            "description": "<p>Numbers to compare</p>\n",
12846                            "type": "Number[]"
12847                        }
12848                    ],
12849                    "return": {
12850                        "description": "",
12851                        "type": "Number"
12852                    }
12853                }
12854            ]
12855        },
12856        {
12857            "file": "src/math/calculation.js",
12858            "line": 574,
12859            "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",
12860            "itemtype": "method",
12861            "name": "norm",
12862            "params": [
12863                {
12864                    "name": "value",
12865                    "description": "<p>incoming value to be normalized</p>\n",
12866                    "type": "Number"
12867                },
12868                {
12869                    "name": "start",
12870                    "description": "<p>lower bound of the value&#39;s current range</p>\n",
12871                    "type": "Number"
12872                },
12873                {
12874                    "name": "stop",
12875                    "description": "<p>upper bound of the value&#39;s current range</p>\n",
12876                    "type": "Number"
12877                }
12878            ],
12879            "return": {
12880                "description": "normalized number",
12881                "type": "Number"
12882            },
12883            "example": [
12884                "\n<div><code>\nfunction draw() {\n  background(200);\n  var currentNum = mouseX;\n  var lowerBound = 0;\n  var upperBound = width; //100;\n  var normalized = norm(currentNum, lowerBound, upperBound);\n  var lineY = 70;\n  line(0, lineY, width, lineY);\n  //Draw an ellipse mapped to the non-normalized value.\n  noStroke();\n  fill(50);\n  var s = 7; // ellipse size\n  ellipse(currentNum, lineY, s, s);\n\n  // Draw the guide\n  var guideY = lineY + 15;\n  text('0', 0, guideY);\n  textAlign(RIGHT);\n  text('100', width, guideY);
12884\n\n  // Draw the normalized value\n  textAlign(LEFT);\n  fill(0);\n  textSize(32);\n  var normalY = 40;\n  var normalX = 20;\n  text(normalized, normalX, normalY);\n}\n</code></div>"
12885            ],
12886            "alt": "ellipse moves with mouse. 0 shown left & 100 right and updating values center",
12887            "class": "p5",
12888            "module": "Math",
12889            "submodule": "Calculation"
12890        },
12891        {
12892            "file": "src/math/calculation.js",
12893            "line": 627,
12894            "description": "<p>Facilitates exponential expressions. The pow() 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",
12895            "itemtype": "method",
12896            "name": "pow",
12897            "params": [
12898                {
12899                    "name": "n",
12900                    "description": "<p>base of the exponential expression</p>\n",
12901                    "type": "Number"
12902                },
12903                {
12904                    "name": "e",
12905                    "description": "<p>power by which to raise the base</p>\n",
12906                    "type": "Number"
12907                }
12908            ],
12909            "return": {
12910                "description": "n^e",
12911                "type": "Number"
12912            },
12913            "example": [
12914                "\n<div><code>\nfunction setup() {\n  //Exponentially increase the size of an ellipse.\n  var eSize = 3; // Original Size\n  var 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>"
12915            ],
12916            "alt": "small to large ellipses radiating from top left of canvas",
12917            "class": "p5",
12918            "module": "Math",
12919            "submodule": "Calculation"
12920        },
12921        {
12922            "file": "src/math/calculation.js",
12923            "line": 661,
12924            "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",
12925            "itemtype": "method",
12926            "name": "round",
12927            "params": [
12928                {
12929                    "name": "n",
12930                    "description": "<p>number to round</p>\n",
12931                    "type": "Number"
12932                }
12933            ],
12934            "return": {
12935                "description": "rounded number",
12936                "type": "Integer"
12937            },
12938            "example": [
12939                "\n<div><code>\nfunction draw() {\n  background(200);\n  //map, mouseX between 0 and 5.\n  var ax = map(mouseX, 0, 100, 0, 5);\n  var ay = 66;\n\n  // Round the mapped number.\n  var bx = round(map(mouseX, 0, 100, 0, 5));\n  var 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>"
12940            ],
12941            "alt": "horizontal center line squared values displayed on top and regular on bottom.",
12942            "class": "p5",
12943            "module": "Math",
12944            "submodule": "Calculation"
12945        },
12946        {
12947            "file": "src/math/calculation.js",
12948            "line": 700,
12949            "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",
12950            "itemtype": "method",
12951            "name": "sq",
12952            "params": [
12953                {
12954                    "name": "n",
12955                    "description": "<p>number to square</p>\n",
12956                    "type": "Number"
12957                }
12958            ],
12959            "return": {
12960                "description": "squared number",
12961                "type": "Number"
12962            },
12963            "example": [
12964                "\n<div><code>\nfunction draw() {\n  background(200);\n  var eSize = 7;\n  var x1 = map(mouseX, 0, width, 0, 10);\n  var y1 = 80;\n  var x2 = sq(x1);\n  var 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  var 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>"
12965            ],
12966            "alt": "horizontal center line squared values displayed on top and regular on bottom.",
12967            "class": "p5",
12968            "module": "Math",
12969            "submodule": "Calculation"
12970        },
12971        {
12972            "file": "src/math/calculation.js",
12973            "line": 747,
12974            "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",
12975            "itemtype": "method",
12976            "name": "sqrt",
12977            "params": [
12978                {
12979                    "name": "n",
12980                    "description": "<p>non-negative number to square root</p>\n",
12981                    "type": "Number"
12982                }
12983            ],
12984            "return": {
12985                "description": "square root of number",
12986                "type": "Number"
12987            },
12988            "example": [
12989                "\n<div><code>\nfunction draw() {\n  background(200);\n  var eSize = 7;\n  var x1 = mouseX;\n  var y1 = 80;\n  var x2 = sqrt(x1);\n  var 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  var spacing = 15;\n  text('x = ' + x1, 0, y1 + spacing);\n  text('sqrt(x) = ' + x2, 0, y2 + spacing);\n}\n</code></div>"
12990            ],
12991            "alt": "horizontal center line squareroot values displayed on top and regular on bottom.",
12992            "class": "p5",
12993            "module": "Math",
12994            "submodule": "Calculation"
12995        },
12996        {
12997            "file": "src/math/math.js",
12998            "line": 12,
12999            "description": "<p>Creates a new p5.Vector (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",
13000            "itemtype": "method",
13001            "name": "createVector",
13002            "params": [
13003                {
13004                    "name": "x",
13005                    "description": "<p>x component of the vector</p>\n",
13006                    "type": "Number",
13007                    "optional": true
13008                },
13009                {
13010                    "name": "y",
13011                    "description": "<p>y component of the vector</p>\n",
13012                    "type": "Number",
13013                    "optional": true
13014                },
13015                {
13016                    "name": "z",
13017                    "description": "<p>z component of the vector</p>\n",
13018                    "type": "Number",
13019                    "optional": true
13020                }
13021            ],
13022            "return": {
13023                "description": "",
13024                "type": "p5.Vector"
13025            },
13026            "example": [
13027                "\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>"
13028            ],
13029            "alt": "a purple sphere lit by a point light oscillating horizontally",
13030            "class": "p5",
13031            "module": "Math",
13032            "submodule": "Math"
13033        },
13034        {
13035            "file": "src/math/noise.js",
13036            "line": 40,
13037            "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>
13037 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 noiseSeed() 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",
13038            "itemtype": "method",
13039            "name": "noise",
13040            "params": [
13041                {
13042                    "name": "x",
13043                    "description": "<p>x-coordinate in noise space</p>\n",
13044                    "type": "Number"
13045                },
13046                {
13047                    "name": "y",
13048                    "description": "<p>y-coordinate in noise space</p>\n",
13049                    "type": "Number",
13050                    "optional": true
13051                },
13052                {
13053                    "name": "z",
13054                    "description": "<p>z-coordinate in noise space</p>\n",
13055                    "type": "Number",
13056                    "optional": true
13057                }
13058            ],
13059            "return": {
13060                "description": "Perlin noise value (between 0 and 1) at specified\n                     coordinates",
13061                "type": "Number"
13062            },
13063            "example": [
13064                "\n<div>\n<code>\nvar xoff = 0.0;\n\nfunction draw() {\n  background(204);\n  xoff = xoff + 0.01;\n  var n = noise(xoff) * width;\n  line(n, 0, n, height);\n}\n</code>\n</div>\n<div>\n<code>var noiseScale=0.02;\n\nfunction draw() {\n  background(0);\n  for (var x=0; x < width; x++) {\n    var 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>"
13065            ],
13066            "alt": "vertical line moves left to right with updating noise values.\nhorizontal wave pattern effected by mouse x-position & updating noise values.",
13067            "class": "p5",
13068            "module": "Math",
13069            "submodule": "Noise"
13070        },
13071        {
13072            "file": "src/math/noise.js",
13073            "line": 187,
13074            "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",
13075            "itemtype": "method",
13076            "name": "noiseDetail",
13077            "params": [
13078                {
13079                    "name": "lod",
13080                    "description": "<p>number of octaves to be used by the noise</p>\n",
13081                    "type": "Number"
13082                },
13083                {
13084                    "name": "falloff",
13085                    "description": "<p>falloff factor for each octave</p>\n",
13086                    "type": "Number"
13087                }
13088            ],
13089            "example": [
13090                "\n <div>\n <code>\n var noiseVal;\n var noiseScale = 0.02;\nfunction setup() {\n   createCanvas(100, 100);\n }\nfunction draw() {\n   background(0);\n   for (var y = 0; y < height;
13090 y++) {\n     for (var 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>"
13091            ],
13092            "alt": "2 vertical grey smokey patterns affected my mouse x-position and noise.",
13093            "class": "p5",
13094            "module": "Math",
13095            "submodule": "Noise"
13096        },
13097        {
13098            "file": "src/math/noise.js",
13099            "line": 253,
13100            "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",
13101            "itemtype": "method",
13102            "name": "noiseSeed",
13103            "params": [
13104                {
13105                    "name": "seed",
13106                    "description": "<p>the seed value</p>\n",
13107                    "type": "Number"
13108                }
13109            ],
13110            "example": [
13111                "\n<div>\n<code>var xoff = 0.0;\n\nfunction setup() {\n  noiseSeed(99);\n  stroke(0, 10);\n}\n\nfunction draw() {\n  xoff = xoff + .01;\n  var n = noise(xoff) * width;\n  line(n, 0, n, height);\n}\n</code>\n</div>"
13112            ],
13113            "alt": "vertical grey lines drawing in pattern affected by noise.",
13114            "class": "p5",
13115            "module": "Math",
13116            "submodule": "Noise"
13117        },
13118        {
13119            "file": "src/math/p5.Vector.js",
13120            "line": 67,
13121            "description": "<p>The x component of the vector</p>\n",
13122            "itemtype": "property",
13123            "name": "x",
13124            "type": "Number",
13125            "class": "p5.Vector",
13126            "module": "Math",
13127            "submodule": "Math"
13128        },
13129        {
13130            "file": "src/math/p5.Vector.js",
13131            "line": 72,
13132            "description": "<p>The y component of the vector</p>\n",
13133            "itemtype": "property",
13134            "name": "y",
13135            "type": "Number",
13136            "class": "p5.Vector",
13137            "module": "Math",
13138            "submodule": "Math"
13139        },
13140        {
13141            "file": "src/math/p5.Vector.js",
13142            "line": 77,
13143            "description": "<p>The z component of the vector</p>\n",
13144            "itemtype": "property",
13145            "name": "z",
13146            "type": "Number",
13147            "class": "p5.Vector",
13148            "module": "Math",
13149            "submodule": "Math"
13150        },
13151        {
13152            "file": "src/math/p5.Vector.js",
13153            "line": 84,
13154            "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",
13155            "itemtype": "method",
13156            "name": "toString",
13157            "return": {
13158                "description": "",
13159                "type": "String"
13160            },
13161            "example": [
13162                "\n<div class = \"norender\">\n<code>\nfunction setup() {\n  var 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  var v0 = createVector(0, 0);\n  var 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  var 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>"
13163            ],
13164            "class": "p5.Vector",
13165            "module": "Math",
13166            "submodule": "Math"
13167        },
13168        {
13169            "file": "src/math/p5.Vector.js",
13170            "line": 134,
13171            "description": "<p>Sets the x, y, and z component of the vector using two or three separate\nvariables, the data from a p5.Vector, or the values from a float array.</p>\n",
13172            "itemtype": "method",
13173            "name": "set",
13174            "chainable": 1,
13175            "example": [
13176                "\n<div class=\"norender\">\n<code>\nfunction setup() {\n  var v = createVector(1, 2, 3);
13176\n  v.set(4, 5, 6); // Sets vector to [4, 5, 6]\n\n  var v1 = createVector(0, 0, 0);\n  var arr = [1, 2, 3];\n  v1.set(arr); // Sets vector to [1, 2, 3]\n}\n</code>\n</div>\n\n<div>\n<code>\nvar 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  var 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>"
13177            ],
13178            "class": "p5.Vector",
13179            "module": "Math",
13180            "submodule": "Math",
13181            "overloads": [
13182                {
13183                    "line": 134,
13184                    "params": [
13185                        {
13186                            "name": "x",
13187                            "description": "<p>the x component of the vector</p>\n",
13188                            "type": "Number",
13189                            "optional": true
13190                        },
13191                        {
13192                            "name": "y",
13193                            "description": "<p>the y component of the vector</p>\n",
13194                            "type": "Number",
13195                            "optional": true
13196                        },
13197                        {
13198                            "name": "z",
13199                            "description": "<p>the z component of the vector</p>\n",
13200                            "type": "Number",
13201                            "optional": true
13202                        }
13203                    ],
13204                    "chainable": 1
13205                },
13206                {
13207                    "line": 193,
13208                    "params": [
13209                        {
13210                            "name": "value",
13211                            "description": "<p>the vector to set</p>\n",
13212                            "type": "p5.Vector|Number[]"
13213                        }
13214                    ],
13215                    "chainable": 1
13216                }
13217            ]
13218        },
13219        {
13220            "file": "src/math/p5.Vector.js",
13221            "line": 217,
13222            "description": "<p>Gets a copy of the vector, returns a p5.Vector object.</p>\n",
13223            "itemtype": "method",
13224            "name": "copy",
13225            "return": {
13226                "description": "the copy of the p5.Vector object",
13227                "type": "p5.Vector"
13228            },
13229            "example": [
13230                "\n<div class=\"norender\">\n<code>\nvar v1 = createVector(1, 2, 3);\nvar v2 = v1.copy();\nprint(v1.x === v2.x && v1.y === v2.y && v1.z === v2.z);\n// Prints \"true\"\n</code>\n</div>"
13231            ],
13232            "class": "p5.Vector",
13233            "module": "Math",
13234            "submodule": "Math"
13235        },
13236        {
13237            "file": "src/math/p5.Vector.js",
13238            "line": 240,
13239            "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 p5.Vector, the others\nacts directly on the vector. See the examples for more context.</p>\n",
13240            "itemtype": "method",
13241            "name": "add",
13242            "chainable": 1,
13243            "example": [
13244                "\n<div class=\"norender\">\n<code>\nvar 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\nvar v1 = createVector(1, 2, 3);\nvar v2 = createVector(2, 3, 4);\n\nvar 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  var v0 = createVector(0, 0);\n  var v1 = createVector(mouseX, mouseY);\n  drawArrow(v0, v1, 'red');\n\n  var v2 = createVector(-30, 20);\n  drawArrow(v1, v2, 'blue');\n\n  var 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  var 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>"
13245            ],
13246            "class": "p5.Vector",
13247            "module": "Math",
13248            "submodule": "Math",
13249            "overloads": [
13250                {
13251                    "line": 240,
13252                    "params": [
13253                        {
13254                            "name": "x",
13255                            "description": "<p>the x component of the vector to be added</p>\n",
13256                            "type": "Number"
13257                        },
13258                        {
13259                            "name": "y",
13260                            "description": "<p>the y component of the vector to be added</p>\n",
13261                            "type": "Number",
13262                            "optional": true
13263                        },
13264                        {
13265                            "name": "z",
13266                            "description": "<p>the z component of the vector to be added</p>\n",
13267                            "type": "Number",
13268                            "optional": true
13269                        }
13270                    ],
13271                    "chainable": 1
13272                },
13273                {
13274                    "line": 306,
13275                    "params": [
13276                        {
13277                            "name": "value",
13278                            "description": "<p>the vector to add</p>\n",
13279                            "type": "p5.Vector|Number[]"
13280                        }
13281                    ],
13282                    "chainable": 1
13283                },
13284                {
13285                    "line": 1556,
13286                    "params": [
13287                        {
13288                            "name": "v1",
13289                            "description": "<p>a p5.Vector to add</p>\n",
13290                            "type": "p5.Vector"
13291                        },
13292                        {
13293                            "name": "v2",
13294                            "description": "<p>a p5.Vector to add</p>\n",
13295                            "type": "p5.Vector"
13296                        },
13297                        {
13298                            "name": "target",
13299                            "description": "<p>the vector to receive the result</p>\n",
13300                            "type": "p5.Vector"
13301                        }
13302                    ],
13303                    "static": 1
13304                },
13305                {
13306                    "line": 1563,
13307                    "params": [
13308                        {
13309                            "name": "v1",
13310                            "description": "",
13311                            "type": "p5.Vector"
13312                        },
13313                        {
13314                            "name": "v2",
13315                            "description": "",
13316                            "type": "p5.Vector"
13317                        }
13318                    ],
13319                    "static": 1,
13320                    "return": {
13321                        "description": "the resulting p5.Vector",
13322                        "type": "p5.Vector"
13323                    }
13324                }
13325            ]
13326        },
13327        {
13328            "file": "src/math/p5.Vector.js",
13329            "line": 330,
13330            "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 p5.Vector, the\nother acts directly on the vector. See the examples for more context.</p>\n",
13331            "itemtype": "method",
13332            "name": "sub",
13333            "chainable": 1,
13334            "example": [
13335                "\n<div class=\"norender\">\n<code>
13335\nvar 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\nvar v1 = createVector(2, 3, 4);\nvar v2 = createVector(1, 2, 3);\n\nvar 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  var v0 = createVector(0, 0);\n  var v1 = createVector(70, 50);\n  drawArrow(v0, v1, 'red');\n\n  var v2 = createVector(mouseX, mouseY);\n  drawArrow(v0, v2, 'blue');\n\n  var 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  var 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>"
13336            ],
13337            "class": "p5.Vector",
13338            "module": "Math",
13339            "submodule": "Math",
13340            "overloads": [
13341                {
13342                    "line": 330,
13343                    "params": [
13344                        {
13345                            "name": "x",
13346                            "description": "<p>the x component of the vector to subtract</p>\n",
13347                            "type": "Number"
13348                        },
13349                        {
13350                            "name": "y",
13351                            "description": "<p>the y component of the vector to subtract</p>\n",
13352                            "type": "Number",
13353                            "optional": true
13354                        },
13355                        {
13356                            "name": "z",
13357                            "description": "<p>the z component of the vector to subtract</p>\n",
13358                            "type": "Number",
13359                            "optional": true
13360                        }
13361                    ],
13362                    "chainable": 1
13363                },
13364                {
13365                    "line": 396,
13366                    "params": [
13367                        {
13368                            "name": "value",
13369                            "description": "<p>the vector to subtract</p>\n",
13370                            "type": "p5.Vector|Number[]"
13371                        }
13372                    ],
13373                    "chainable": 1
13374                },
13375                {
13376                    "line": 1586,
13377                    "params": [
13378                        {
13379                            "name": "v1",
13380                            "description": "<p>a p5.Vector to subtract from</p>\n",
13381                            "type": "p5.Vector"
13382                        },
13383                        {
13384                            "name": "v2",
13385                            "description": "<p>a p5.Vector to subtract</p>\n",
13386                            "type": "p5.Vector"
13387                        },
13388                        {
13389                            "name": "target",
13390                            "description": "<p>if undefined a new vector will be created</p>\n",
13391                            "type": "p5.Vector"
13392                        }
13393                    ],
13394                    "static": 1
13395                },
13396                {
13397                    "line": 1593,
13398                    "params": [
13399                        {
13400                            "name": "v1",
13401                            "description": "",
13402                            "type": "p5.Vector"
13403                        },
13404                        {
13405                            "name": "v2",
13406                            "description": "",
13407                            "type": "p5.Vector"
13408                        }
13409                    ],
13410                    "static": 1,
13411                    "return": {
13412                        "description": "the resulting p5.Vector",
13413                        "type": "p5.Vector"
13414                    }
13415                }
13416            ]
13417        },
13418        {
13419            "file": "src/math/p5.Vector.js",
13420            "line": 420,
13421            "description": "<p>Multiply the vector by a scalar. The static version of this method\ncreates a new p5.Vector while the non static version acts on the vector\ndirectly. See the examples for more context.</p>\n",
13422            "itemtype": "method",
13423            "name": "mult",
13424            "chainable": 1,
13425            "example": [
13426                "\n<div class=\"norender\">\n<code>\nvar 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\nvar v1 = createVector(1, 2, 3);\nvar 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  var v0 = createVector(50, 50);\n  var v1 = createVector(25, -25);\n  drawArrow(v0, v1, 'red');\n\n  var num = map(mouseX, 0, width, -2, 2, true);\n  var 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  var 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>"
13427            ],
13428            "class": "p5.Vector",
13429            "module": "Math",
13430            "submodule": "Math",
13431            "overloads": [
13432                {
13433                    "line": 420,
13434                    "params": [
13435                        {
13436                            "name": "n",
13437                            "description": "<p>the number to multiply with the vector</p>\n",
13438                            "type": "Number"
13439                        }
13440                    ],
13441                    "chainable": 1
13442                },
13443                {
13444                    "line": 1614,
13445                    "params": [
13446                        {
13447                            "name": "v",
13448                            "description": "<p>the vector to multiply</p>\n",
13449                            "type": "p5.Vector"
13450                        },
13451                        {
13452                            "name": "n",
13453                            "description": "",
13454                            "type": "Number"
13455                        },
13456                        {
13457                            "name": "target",
13458                            "description": "<p>if undefined a new vector will be created</p>\n",
13459                            "type": "p5.Vector"
13460                        }
13461                    ],
13462                    "static": 1
13463                },
13464                {
13465                    "line": 1621,
13466                    "params": [
13467                        {
13468                            "name": "v",
13469                            "description": "",
13470                            "type": "p5.Vector"
13471                        },
13472                        {
13473                            "name": "n",
13474                            "description": "",
13475                            "type": "Number"
13476                        }
13477                    ],
13478                    "static": 1,
13479                    "return": {
13480                        "description": "the resulting new p5.Vector",
13481                        "type": "p5.Vector"
13482                    }
13483                }
13484            ]
13485        },
13486        {
13487            "file": "src/math/p5.Vector.js",
13488            "line": 495,
13489            "description": "<p>Divide the vector by a scalar. The static version of this method creates a\nnew p5.Vector while the non static version acts on the vector directly.\nSee the examples for more context.</p>\n",
13490            "itemtype": "method",
13491            "name": "div",
13492            "chainable": 1,
13493            "example": [
13494                "\n<div class=\"norender\">\n<code>\nvar 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\nvar v1 = createVector(6, 4, 2);\nvar 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  var v0 = createVector(0, 100);\n  var v1 = createVector(50, -50);\n  drawArrow(v0, v1, 'red');\n\n  var num = map(mouseX, 0, width, 10, 0.5, true);\n  var 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  var 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>"
13495            ],
13496            "class": "p5.Vector",
13497            "module": "Math",
13498            "submodule": "Math",
13499            "overloads": [
13500                {
13501                    "line": 495,
13502                    "params": [
13503                        {
13504                            "name": "n",
13505                            "description": "<p>the number to divide the vector by</p>\n",
13506                            "type": "Number"
13507                        }
13508                    ],
13509                    "chainable": 1
13510                },
13511                {
13512                    "line": 1641,
13513                    "params": [
13514                        {
13515                            "name": "v",
13516                            "description": "<p>the vector to divide</p>\n",
13517                            "type": "p5.Vector"
13518                        },
13519                        {
13520                            "name": "n",
13521                            "description": "",
13522                            "type": "Number"
13523                        },
13524                        {
13525                            "name": "target",
13526                            "description": "<p>if undefined a new vector will be created</p>\n",
13527                            "type": "p5.Vector"
13528                        }
13529                    ],
13530                    "static": 1
13531                },
13532                {
13533                    "line": 1648,
13534                    "params": [
13535                        {
13536                            "name": "v",
13537                            "description": "",
13538                            "type": "p5.Vector"
13539                        },
13540                        {
13541                            "name": "n",
13542                            "description": "",
13543                            "type": "Number"
13544                        }
13545                    ],
13546                    "static": 1,
13547                    "return": {
13548                        "description": "the resulting new p5.Vector",
13549                        "type": "p5.Vector"
13550                    }
13551                }
13552            ]
13553        },
13554        {
13555            "file": "src/math/p5.Vector.js",
13556            "line": 573,
13557            "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",
13558            "itemtype": "method",
13559            "name": "mag",
13560            "return": {
13561                "description": "magnitude of the vector",
13562                "type": "Number"
13563            },
13564            "example": [
13565                "\n<div>\n<code>\nfunction draw() {\n  background(240);\n\n  var v0 = createVector(0, 0);\n  var v1 = createVector(mouseX, mouseY);\n  drawArrow(v0, v1, 'black');\n\n  noStroke();
13565\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  var 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>\nvar v = createVector(20.0, 30.0, 40.0);\nvar m = v.mag();\nprint(m); // Prints \"53.85164807134504\"\n</code>\n</div>"
13566            ],
13567            "class": "p5.Vector",
13568            "module": "Math",
13569            "submodule": "Math",
13570            "overloads": [
13571                {
13572                    "line": 573,
13573                    "params": [],
13574                    "return": {
13575                        "description": "magnitude of the vector",
13576                        "type": "Number"
13577                    }
13578                },
13579                {
13580                    "line": 1738,
13581                    "params": [
13582                        {
13583                            "name": "vecT",
13584                            "description": "<p>the vector to return the magnitude of</p>\n",
13585                            "type": "p5.Vector"
13586                        }
13587                    ],
13588                    "static": 1,
13589                    "return": {
13590                        "description": "the magnitude of vecT",
13591                        "type": "Number"
13592                    }
13593                }
13594            ]
13595        },
13596        {
13597            "file": "src/math/p5.Vector.js",
13598            "line": 621,
13599            "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",
13600            "itemtype": "method",
13601            "name": "magSq",
13602            "return": {
13603                "description": "squared magnitude of the vector",
13604                "type": "Number"
13605            },
13606            "example": [
13607                "\n<div class=\"norender\">\n<code>\n// Static method\nvar 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  var v0 = createVector(0, 0);\n  var 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  var 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>"
13608            ],
13609            "class": "p5.Vector",
13610            "module": "Math",
13611            "submodule": "Math"
13612        },
13613        {
13614            "file": "src/math/p5.Vector.js",
13615            "line": 675,
13616            "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",
13617            "itemtype": "method",
13618            "name": "dot",
13619            "return": {
13620                "description": "the dot product",
13621                "type": "Number"
13622            },
13623            "example": [
13624                "\n<div class=\"norender\">\n<code>\nvar v1 = createVector(1, 2, 3);\nvar 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\nvar v1 = createVector(1, 2, 3);\nvar v2 = createVector(3, 2, 1);\nprint(p5.Vector.dot(v1, v2)); // Prints \"10\"\n</code>\n</div>"
13625            ],
13626            "class": "p5.Vector",
13627            "module": "Math",
13628            "submodule": "Math",
13629            "overloads": [
13630                {
13631                    "line": 675,
13632                    "params": [
13633                        {
13634                            "name": "x",
13635                            "description": "<p>x component of the vector</p>\n",
13636                            "type": "Number"
13637                        },
13638                        {
13639                            "name": "y",
13640                            "description": "<p>y component of the vector</p>\n",
13641                            "type": "Number",
13642                            "optional": true
13643                        },
13644                        {
13645                            "name": "z",
13646                            "description": "<p>z component of the vector</p>\n",
13647                            "type": "Number",
13648                            "optional": true
13649                        }
13650                    ],
13651                    "return": {
13652                        "description": "the dot product",
13653                        "type": "Number"
13654                    }
13655                },
13656                {
13657                    "line": 706,
13658                    "params": [
13659                        {
13660                            "name": "value",
13661                            "description": "<p>value component of the vector or a p5.Vector</p>\n",
13662                            "type": "p5.Vector"
13663                        }
13664                    ],
13665                    "return": {
13666                        "description": "",
13667                        "type": "Number"
13668                    }
13669                },
13670                {
13671                    "line": 1668,
13672                    "params": [
13673                        {
13674                            "name": "v1",
13675                            "description": "<p>the first p5.Vector</p>\n",
13676                            "type": "p5.Vector"
13677                        },
13678                        {
13679                            "name": "v2",
13680                            "description": "<p>the second p5.Vector</p>\n",
13681                            "type": "p5.Vector"
13682                        }
13683                    ],
13684                    "static": 1,
13685                    "return": {
13686                        "description": "the dot product",
13687                        "type": "Number"
13688                    }
13689                }
13690            ]
13691        },
13692        {
13693            "file": "src/math/p5.Vector.js",
13694            "line": 718,
13695            "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 p5.Vector.\nSee the examples for more context.</p>\n",
13696            "itemtype": "method",
13697            "name": "cross",
13698            "return": {
13699                "description": "p5.Vector composed of cross product",
13700                "type": "p5.Vector"
13701            },
13702            "example": [
13703                "\n<div class=\"norender\">\n<code>\nvar v1 = createVector(1, 2, 3);\nvar 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\nvar v1 = createVector(1, 0, 0);\nvar v2 = createVector(0, 1, 0);
13703\n\nvar crossProduct = p5.Vector.cross(v1, v2);\n// crossProduct has components [0, 0, 1]\nprint(crossProduct);\n</code>\n</div>"
13704            ],
13705            "class": "p5.Vector",
13706            "module": "Math",
13707            "submodule": "Math",
13708            "overloads": [
13709                {
13710                    "line": 718,
13711                    "params": [
13712                        {
13713                            "name": "v",
13714                            "description": "<p>p5.Vector to be crossed</p>\n",
13715                            "type": "p5.Vector"
13716                        }
13717                    ],
13718                    "return": {
13719                        "description": "p5.Vector composed of cross product",
13720                        "type": "p5.Vector"
13721                    }
13722                },
13723                {
13724                    "line": 1682,
13725                    "params": [
13726                        {
13727                            "name": "v1",
13728                            "description": "<p>the first p5.Vector</p>\n",
13729                            "type": "p5.Vector"
13730                        },
13731                        {
13732                            "name": "v2",
13733                            "description": "<p>the second p5.Vector</p>\n",
13734                            "type": "p5.Vector"
13735                        }
13736                    ],
13737                    "static": 1,
13738                    "return": {
13739                        "description": "the cross product",
13740                        "type": "Number"
13741                    }
13742                }
13743            ]
13744        },
13745        {
13746            "file": "src/math/p5.Vector.js",
13747            "line": 759,
13748            "description": "<p>Calculates the Euclidean distance between two points (considering a\npoint as a vector object).</p>\n",
13749            "itemtype": "method",
13750            "name": "dist",
13751            "return": {
13752                "description": "the distance",
13753                "type": "Number"
13754            },
13755            "example": [
13756                "\n<div class=\"norender\">\n<code>\nvar v1 = createVector(1, 0, 0);\nvar v2 = createVector(0, 1, 0);\n\nvar distance = v1.dist(v2); // distance is 1.4142...\nprint(distance);\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\n// Static method\nvar v1 = createVector(1, 0, 0);\nvar v2 = createVector(0, 1, 0);\n\nvar 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  var v0 = createVector(0, 0);\n\n  var v1 = createVector(70, 50);\n  drawArrow(v0, v1, 'red');\n\n  var 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  var 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>"
13757            ],
13758            "class": "p5.Vector",
13759            "module": "Math",
13760            "submodule": "Math",
13761            "overloads": [
13762                {
13763                    "line": 759,
13764                    "params": [
13765                        {
13766                            "name": "v",
13767                            "description": "<p>the x, y, and z coordinates of a p5.Vector</p>\n",
13768                            "type": "p5.Vector"
13769                        }
13770                    ],
13771                    "return": {
13772                        "description": "the distance",
13773                        "type": "Number"
13774                    }
13775                },
13776                {
13777                    "line": 1697,
13778                    "params": [
13779                        {
13780                            "name": "v1",
13781                            "description": "<p>the first p5.Vector</p>\n",
13782                            "type": "p5.Vector"
13783                        },
13784                        {
13785                            "name": "v2",
13786                            "description": "<p>the second p5.Vector</p>\n",
13787                            "type": "p5.Vector"
13788                        }
13789                    ],
13790                    "static": 1,
13791                    "return": {
13792                        "description": "the distance",
13793                        "type": "Number"
13794                    }
13795                }
13796            ]
13797        },
13798        {
13799            "file": "src/math/p5.Vector.js",
13800            "line": 830,
13801            "description": "<p>Normalize the vector to length 1 (make it a unit vector).</p>\n",
13802            "itemtype": "method",
13803            "name": "normalize",
13804            "return": {
13805                "description": "normalized p5.Vector",
13806                "type": "p5.Vector"
13807            },
13808            "example": [
13809                "\n<div class=\"norender\">\n<code>\nvar 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  var v0 = createVector(50, 50);\n  var 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  var 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>"
13810            ],
13811            "class": "p5.Vector",
13812            "module": "Math",
13813            "submodule": "Math"
13814        },
13815        {
13816            "file": "src/math/p5.Vector.js",
13817            "line": 886,
13818            "description": "<p>Limit the magnitude of this vector to the value used for the <b>max</b>\nparameter.</p>\n",
13819            "itemtype": "method",
13820            "name": "limit",
13821            "params": [
13822                {
13823                    "name": "max",
13824                    "description": "<p>the maximum magnitude for the vector</p>\n",
13825                    "type": "Number"
13826                }
13827            ],
13828            "chainable": 1,
13829            "example": [
13830                "\n<div class=\"norender\">\n<code>\nvar 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  var v0 = createVector(50, 50);\n  var 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  var 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>"
13831            ],
13832            "class": "p5.Vector",
13833            "module": "Math",
13834            "submodule": "Math"
13835        },
13836        {
13837            "file": "src/math/p5.Vector.js",
13838            "line": 944,
13839            "description": "<p>Set the magnitude of this vector to the value used for the <b>len</b>\nparameter.</p>\n",
13840            "itemtype": "method",
13841            "name": "setMag",
13842            "params": [
13843                {
13844                    "name": "len",
13845                    "description": "<p>the new length for this vector</p>\n",
13846                    "type": "Number"
13847                }
13848            ],
13849            "chainable": 1,
13850            "example": [
13851                "\n<div class=\"norender\">\n<code>\nvar 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  var v0 = createVector(0, 0);\n  var v1 = createVector(50, 50);\n\n  drawArrow(v0, v1, 'red');\n\n  var 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  var 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>"
13852            ],
13853            "class": "p5.Vector",
13854            "module": "Math",
13855            "submodule": "Math"
13856        },
13857        {
13858            "file": "src/math/p5.Vector.js",
13859            "line": 1000,
13860            "description": "<p>Calculate the angle of rotation for this vector (only 2D vectors)</p>\n",
13861            "itemtype": "method",
13862            "name": "heading",
13863            "return": {
13864                "description": "the angle of rotation",
13865                "type": "Number"
13866            },
13867            "example": [
13868                "\n<div class = \"norender\">\n<code>\nfunction setup() {\n  var v1 = createVector(30, 50);\n  print(v1.heading()); // 1.0303768265243125\n\n  v1 = createVector(40, 50);\n  print(v1.heading());
13868 // 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  var v0 = createVector(50, 50);\n  var v1 = createVector(mouseX - 50, mouseY - 50);\n\n  drawArrow(v0, v1, 'black');\n\n  var 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  var 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>"
13869            ],
13870            "class": "p5.Vector",
13871            "module": "Math",
13872            "submodule": "Math"
13873        },
13874        {
13875            "file": "src/math/p5.Vector.js",
13876            "line": 1069,
13877            "description": "<p>Rotate the vector by an angle (only 2D vectors), magnitude remains the\nsame</p>\n",
13878            "itemtype": "method",
13879            "name": "rotate",
13880            "params": [
13881                {
13882                    "name": "angle",
13883                    "description": "<p>the angle of rotation</p>\n",
13884                    "type": "Number"
13885                }
13886            ],
13887            "chainable": 1,
13888            "example": [
13889                "\n<div class=\"norender\">\n<code>\nvar 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>\nvar angle = 0;\nfunction draw() {\n  background(240);\n\n  var v0 = createVector(50, 50);\n  var 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  var 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>"
13890            ],
13891            "class": "p5.Vector",
13892            "module": "Math",
13893            "submodule": "Math"
13894        },
13895        {
13896            "file": "src/math/p5.Vector.js",
13897            "line": 1125,
13898            "description": "<p>Calculates and returns the angle (in radians) between two vectors.</p>\n",
13899            "itemtype": "method",
13900            "name": "angleBetween",
13901            "params": [
13902                {
13903                    "name": "the",
13904                    "description": "<p>x, y, and z components of a p5.Vector</p>\n",
13905                    "type": "p5.Vector"
13906                }
13907            ],
13908            "return": {
13909                "description": "the angle between (in radians)",
13910                "type": "Number"
13911            },
13912            "example": [
13913                "\n<div class=\"norender\">\n<code>\nvar v1 = createVector(1, 0, 0);\nvar v2 = createVector(0, 1, 0);\n\nvar 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  var v0 = createVector(50, 50);\n\n  var v1 = createVector(50, 0);\n  drawArrow(v0, v1, 'red');\n\n  var v2 = createVector(mouseX - 50, mouseY - 50);\n  drawArrow(v0, v2, 'blue');\n\n  var 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  var 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>"
13914            ],
13915            "class": "p5.Vector",
13916            "module": "Math",
13917            "submodule": "Math"
13918        },
13919        {
13920            "file": "src/math/p5.Vector.js",
13921            "line": 1198,
13922            "description": "<p>Linear interpolate the vector to another vector</p>\n",
13923            "itemtype": "method",
13924            "name": "lerp",
13925            "chainable": 1,
13926            "example": [
13927                "\n<div class=\"norender\">\n<code>\nvar 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>\nvar v1 = createVector(0, 0, 0);\nvar v2 = createVector(100, 100, 0);\n\nvar 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>\nvar step = 0.01;\nvar amount = 0;\n\nfunction draw() {\n  background(240);\n  var v0 = createVector(0, 0);\n\n  var v1 = createVector(mouseX, mouseY);\n  drawArrow(v0, v1, 'red');\n\n  var v2 = createVector(90, 90);\n  drawArrow(v0, v2, 'blue');\n\n  if (amount > 1 || amount < 0) {\n    step *= -1;\n  }\n  amount += step;\n  var 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  var 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>"
13928            ],
13929            "class": "p5.Vector",
13930            "module": "Math",
13931            "submodule": "Math",
13932            "overloads": [
13933                {
13934                    "line": 1198,
13935                    "params": [
13936                        {
13937                            "name": "x",
13938                            "description": "<p>the x component</p>\n",
13939                            "type": "Number"
13940                        },
13941                        {
13942                            "name": "y",
13943                            "description": "<p>the y component</p>\n",
13944                            "type": "Number"
13945                        },
13946                        {
13947                            "name": "z",
13948                            "description": "<p>the z component</p>\n",
13949                            "type": "Number"
13950                        },
13951                        {
13952                            "name": "amt",
13953                            "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",
13954                            "type": "Number"
13955                        }
13956                    ],
13957                    "chainable": 1
13958                },
13959                {
13960                    "line": 1271,
13961                    "params": [
13962                        {
13963                            "name": "v",
13964                            "description": "<p>the p5.Vector to lerp to</p>\n",
13965                            "type": "p5.Vector"
13966                        },
13967                        {
13968                            "name": "amt",
13969                            "description": "",
13970                            "type": "Number"
13971                        }
13972                    ],
13973                    "chainable": 1
13974                },
13975                {
13976                    "line": 1712,
13977                    "params": [
13978                        {
13979                            "name": "v1",
13980                            "description": "",
13981                            "type": "p5.Vector"
13982                        },
13983                        {
13984                            "name": "v2",
13985                            "description": "",
13986                            "type": "p5.Vector"
13987                        },
13988                        {
13989                            "name": "amt",
13990                            "description": "",
13991                            "type": "Number"
13992                        },
13993                        {
13994                            "name": "target",
13995                            "description": "<p>if undefined a new vector will be created</p>\n",
13996                            "type": "p5.Vector"
13997                        }
13998                    ],
13999                    "static": 1
14000                },
14001                {
14002                    "line": 1720,
14003                    "params": [
14004                        {
14005                            "name": "v1",
14006                            "description": "",
14007                            "type": "p5.Vector"
14008                        },
14009                        {
14010                            "name": "v2",
14011                            "description": "",
14012                            "type": "p5.Vector"
14013                        },
14014                        {
14015                            "name": "amt",
14016                            "description": "",
14017                            "type": "Number"
14018                        }
14019                    ],
14020                    "static": 1,
14021                    "return": {
14022                        "description": "the lerped value",
14023                        "type": "Number"
14024                    }
14025                }
14026            ]
14027        },
14028        {
14029            "file": "src/math/p5.Vector.js",
14030            "line": 1287,
14031            "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.copy()</b>
14031 method to copy into your own\narray.</p>\n",
14032            "itemtype": "method",
14033            "name": "array",
14034            "return": {
14035                "description": "an Array with the 3 values",
14036                "type": "Number[]"
14037            },
14038            "example": [
14039                "\n<div class = \"norender\">\n<code>\nfunction setup() {\n  var 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>\nvar v = createVector(10.0, 20.0, 30.0);\nvar 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>"
14040            ],
14041            "class": "p5.Vector",
14042            "module": "Math",
14043            "submodule": "Math"
14044        },
14045        {
14046            "file": "src/math/p5.Vector.js",
14047            "line": 1319,
14048            "description": "<p>Equality check against a p5.Vector</p>\n",
14049            "itemtype": "method",
14050            "name": "equals",
14051            "return": {
14052                "description": "whether the vectors are equals",
14053                "type": "Boolean"
14054            },
14055            "example": [
14056                "\n<div class = \"norender\">\n<code>\nvar v1 = createVector(5, 10, 20);\nvar v2 = createVector(5, 10, 20);\nvar 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>\nvar v1 = createVector(10.0, 20.0, 30.0);\nvar v2 = createVector(10.0, 20.0, 30.0);\nvar v3 = createVector(0.0, 0.0, 0.0);\nprint(v1.equals(v2)); // true\nprint(v1.equals(v3)); // false\n</code>\n</div>"
14057            ],
14058            "class": "p5.Vector",
14059            "module": "Math",
14060            "submodule": "Math",
14061            "overloads": [
14062                {
14063                    "line": 1319,
14064                    "params": [
14065                        {
14066                            "name": "x",
14067                            "description": "<p>the x component of the vector</p>\n",
14068                            "type": "Number",
14069                            "optional": true
14070                        },
14071                        {
14072                            "name": "y",
14073                            "description": "<p>the y component of the vector</p>\n",
14074                            "type": "Number",
14075                            "optional": true
14076                        },
14077                        {
14078                            "name": "z",
14079                            "description": "<p>the z component of the vector</p>\n",
14080                            "type": "Number",
14081                            "optional": true
14082                        }
14083                    ],
14084                    "return": {
14085                        "description": "whether the vectors are equals",
14086                        "type": "Boolean"
14087                    }
14088                },
14089                {
14090                    "line": 1349,
14091                    "params": [
14092                        {
14093                            "name": "value",
14094                            "description": "<p>the vector to compare</p>\n",
14095                            "type": "p5.Vector|Array"
14096                        }
14097                    ],
14098                    "return": {
14099                        "description": "",
14100                        "type": "Boolean"
14101                    }
14102                }
14103            ]
14104        },
14105        {
14106            "file": "src/math/p5.Vector.js",
14107            "line": 1374,
14108            "description": "<p>Make a new 2D vector from an angle</p>\n",
14109            "itemtype": "method",
14110            "name": "fromAngle",
14111            "static": 1,
14112            "params": [
14113                {
14114                    "name": "angle",
14115                    "description": "<p>the desired angle, in radians</p>\n",
14116                    "type": "Number"
14117                },
14118                {
14119                    "name": "length",
14120                    "description": "<p>the length of the new vector (defaults to 1)</p>\n",
14121                    "type": "Number",
14122                    "optional": true
14123                }
14124            ],
14125            "return": {
14126                "description": "the new p5.Vector object",
14127                "type": "p5.Vector"
14128            },
14129            "example": [
14130                "\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  var 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  var 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  var v = p5.Vector.fromAngle(radians(myDegrees), 30);\n  var vx = v.x;\n  var 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>"
14131            ],
14132            "class": "p5.Vector",
14133            "module": "Math",
14134            "submodule": "Math"
14135        },
14136        {
14137            "file": "src/math/p5.Vector.js",
14138            "line": 1426,
14139            "description": "<p>Make a new 3D vector from a pair of ISO spherical angles</p>\n",
14140            "itemtype": "method",
14141            "name": "fromAngles",
14142            "static": 1,
14143            "params": [
14144                {
14145                    "name": "theta",
14146                    "description": "<p>the polar angle, in radians (zero is up)</p>\n",
14147                    "type": "Number"
14148                },
14149                {
14150                    "name": "phi",
14151                    "description": "<p>the azimuthal angle, in radians\n                              (zero is out of the screen)</p>\n",
14152                    "type": "Number"
14153                },
14154                {
14155                    "name": "length",
14156                    "description": "<p>the length of the new vector (defaults to 1)</p>\n",
14157                    "type": "Number",
14158                    "optional": true
14159                }
14160            ],
14161            "return": {
14162                "description": "the new p5.Vector object",
14163                "type": "p5.Vector"
14164            },
14165            "example": [
14166                "\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  var 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>"
14167            ],
14168            "class": "p5.Vector",
14169            "module": "Math",
14170            "submodule": "Math"
14171        },
14172        {
14173            "file": "src/math/p5.Vector.js",
14174            "line": 1475,
14175            "description": "<p>Make a new 2D unit vector from a random angle</p>\n",
14176            "itemtype": "method",
14177            "name": "random2D",
14178            "static": 1,
14179            "return": {
14180                "description": "the new p5.Vector object",
14181                "type": "p5.Vector"
14182            },
14183            "example": [
14184                "\n<div class=\"norender\">\n<code>\nvar v = p5.Vector.random2D();\n// May make v's attributes something like:\n// [0.61554617, -0.51195765, 0.0] or\n// [-0.4695841, -0.
1418414366731, 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  var v0 = createVector(50, 50);\n  var 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  var 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>"
14185            ],
14186            "class": "p5.Vector",
14187            "module": "Math",
14188            "submodule": "Math"
14189        },
14190        {
14191            "file": "src/math/p5.Vector.js",
14192            "line": 1528,
14193            "description": "<p>Make a new random 3D unit vector.</p>\n",
14194            "itemtype": "method",
14195            "name": "random3D",
14196            "static": 1,
14197            "return": {
14198                "description": "the new p5.Vector object",
14199                "type": "p5.Vector"
14200            },
14201            "example": [
14202                "\n<div class=\"norender\">\n<code>\nvar 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>"
14203            ],
14204            "class": "p5.Vector",
14205            "module": "Math",
14206            "submodule": "Math"
14207        },
14208        {
14209            "file": "src/math/p5.Vector.js",
14210            "line": 1611,
14211            "description": "<p>Multiplies a vector by a scalar and returns a new vector.</p>\n",
14212            "class": "p5.Vector",
14213            "module": "Math",
14214            "submodule": "Math"
14215        },
14216        {
14217            "file": "src/math/p5.Vector.js",
14218            "line": 1638,
14219            "description": "<p>Divides a vector by a scalar and returns a new vector.</p>\n",
14220            "class": "p5.Vector",
14221            "module": "Math",
14222            "submodule": "Math"
14223        },
14224        {
14225            "file": "src/math/p5.Vector.js",
14226            "line": 1665,
14227            "description": "<p>Calculates the dot product of two vectors.</p>\n",
14228            "class": "p5.Vector",
14229            "module": "Math",
14230            "submodule": "Math"
14231        },
14232        {
14233            "file": "src/math/p5.Vector.js",
14234            "line": 1679,
14235            "description": "<p>Calculates the cross product of two vectors.</p>\n",
14236            "class": "p5.Vector",
14237            "module": "Math",
14238            "submodule": "Math"
14239        },
14240        {
14241            "file": "src/math/p5.Vector.js",
14242            "line": 1693,
14243            "description": "<p>Calculates the Euclidean distance between two points (considering a\npoint as a vector object).</p>\n",
14244            "class": "p5.Vector",
14245            "module": "Math",
14246            "submodule": "Math"
14247        },
14248        {
14249            "file": "src/math/p5.Vector.js",
14250            "line": 1708,
14251            "description": "<p>Linear interpolate a vector to another vector and return the result as a\nnew vector.</p>\n",
14252            "class": "p5.Vector",
14253            "module": "Math",
14254            "submodule": "Math"
14255        },
14256        {
14257            "file": "src/math/random.js",
14258            "line": 48,
14259            "description": "<p>Sets the seed value for random().</p>\n<p>By default, random() 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",
14260            "itemtype": "method",
14261            "name": "randomSeed",
14262            "params": [
14263                {
14264                    "name": "seed",
14265                    "description": "<p>the seed value</p>\n",
14266                    "type": "Number"
14267                }
14268            ],
14269            "example": [
14270                "\n<div>\n<code>\nrandomSeed(99);\nfor (var i = 0; i < 100;
14270 i++) {\n  var r = random(0, 255);\n  stroke(r);\n  line(i, 0, i, 100);\n}\n</code>\n</div>"
14271            ],
14272            "alt": "many vertical lines drawn in white, black or grey.",
14273            "class": "p5",
14274            "module": "Math",
14275            "submodule": "Random"
14276        },
14277        {
14278            "file": "src/math/random.js",
14279            "line": 79,
14280            "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",
14281            "itemtype": "method",
14282            "name": "random",
14283            "return": {
14284                "description": "the random number",
14285                "type": "Number"
14286            },
14287            "example": [
14288                "\n<div>\n<code>\nfor (var i = 0; i < 100; i++) {\n  var r = random(50);\n  stroke(r * 5);\n  line(50, i, 50 + r, i);\n}\n</code>\n</div>\n<div>\n<code>\nfor (var i = 0; i < 100; i++) {\n  var 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\nvar words = ['apple', 'bear', 'cat', 'dog'];\nvar word = random(words); // select random word\ntext(word, 10, 50); // draw the word\n</code>\n</div>"
14289            ],
14290            "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",
14291            "class": "p5",
14292            "module": "Math",
14293            "submodule": "Random",
14294            "overloads": [
14295                {
14296                    "line": 79,
14297                    "params": [
14298                        {
14299                            "name": "min",
14300                            "description": "<p>the lower bound (inclusive)</p>\n",
14301                            "type": "Number",
14302                            "optional": true
14303                        },
14304                        {
14305                            "name": "max",
14306                            "description": "<p>the upper bound (exclusive)</p>\n",
14307                            "type": "Number",
14308                            "optional": true
14309                        }
14310                    ],
14311                    "return": {
14312                        "description": "the random number",
14313                        "type": "Number"
14314                    }
14315                },
14316                {
14317                    "line": 133,
14318                    "params": [
14319                        {
14320                            "name": "choices",
14321                            "description": "<p>the array to choose from</p>\n",
14322                            "type": "Array"
14323                        }
14324                    ],
14325                    "return": {
14326                        "description": "the random element from the array",
14327                        "type": "*"
14328                    }
14329                }
14330            ]
14331        },
14332        {
14333            "file": "src/math/random.js",
14334            "line": 166,
14335            "description": "<p>Returns a random number fitting a Gaussian, or\n normal, distribution. There is theoretically no minimum or maximum\n value that randomGaussian() 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",
14336            "itemtype": "method",
14337            "name": "randomGaussian",
14338            "params": [
14339                {
14340                    "name": "mean",
14341                    "description": "<p>the mean</p>\n",
14342                    "type": "Number"
14343                },
14344                {
14345                    "name": "sd",
14346                    "description": "<p>the standard deviation</p>\n",
14347                    "type": "Number"
14348                }
14349            ],
14350            "return": {
14351                "description": "the random number",
14352                "type": "Number"
14353            },
14354            "example": [
14355                "\n <div>\n <code>\n for (var y = 0; y < 100;
14355 y++) {\n   var x = randomGaussian(50, 15);\n   line(50, y, x, y);\n }\n </code>\n </div>\n <div>\n <code>\n var distribution = new Array(360);\nfunction setup() {\n   createCanvas(100, 100);\n   for (var 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 (var i = 0; i < distribution.length; i++) {\n     rotate(TWO_PI / distribution.length);\n     stroke(0);\n     var dist = abs(distribution[i]);\n     line(0, 0, dist, 0);\n   }\n }\n </code>\n </div>"
14356            ],
14357            "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",
14358            "class": "p5",
14359            "module": "Math",
14360            "submodule": "Random"
14361        },
14362        {
14363            "file": "src/math/trigonometry.js",
14364            "line": 20,
14365            "description": "<p>The inverse of cos(), 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",
14366            "itemtype": "method",
14367            "name": "acos",
14368            "params": [
14369                {
14370                    "name": "value",
14371                    "description": "<p>the value whose arc cosine is to be returned</p>\n",
14372                    "type": "Number"
14373                }
14374            ],
14375            "return": {
14376                "description": "the arc cosine of the given value",
14377                "type": "Number"
14378            },
14379            "example": [
14380                "\n<div class= “norender\">\n<code>\nvar a = PI;\nvar c = cos(a);\nvar 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>\nvar a = PI + PI / 4.0;\nvar c = cos(a);\nvar ac = acos(c);\n// Prints: \"3.926991 : -0.70710665 : 2.3561943\"\nprint(a + ' : ' + c + ' : ' + ac);\n</code>\n</div>"
14381            ],
14382            "class": "p5",
14383            "module": "Math",
14384            "submodule": "Trigonometry"
14385        },
14386        {
14387            "file": "src/math/trigonometry.js",
14388            "line": 54,
14389            "description": "<p>The inverse of sin(), 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",
14390            "itemtype": "method",
14391            "name": "asin",
14392            "params": [
14393                {
14394                    "name": "value",
14395                    "description": "<p>the value whose arc sine is to be returned</p>\n",
14396                    "type": "Number"
14397                }
14398            ],
14399            "return": {
14400                "description": "the arc sine of the given value",
14401                "type": "Number"
14402            },
14403            "example": [
14404                "\n<div class= “norender\">\n<code>\nvar a = PI + PI / 3;\nvar s = sin(a);\nvar 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>\nvar a = PI + PI / 3.0;\nvar s = sin(a);\nvar as = asin(s);\n// Prints: \"4.1887903 : -0.86602545 : -1.0471976\"\nprint(a + ' : ' + s + ' : ' + as);\n</code>\n</div>\n"
14405            ],
14406            "class": "p5",
14407            "module": "Math",
14408            "submodule": "Trigonometry"
14409        },
14410        {
14411            "file": "src/math/trigonometry.js",
14412            "line": 89,
14413            "description": "<p>The inverse of tan(), 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",
14414            "itemtype": "method",
14415            "name": "atan",
14416            "params": [
14417                {
14418                    "name": "value",
14419                    "description": "<p>the value whose arc tangent is to be returned</p>\n",
14420                    "type": "Number"
14421                }
14422            ],
14423            "return": {
14424                "description": "the arc tangent of the given value",
14425                "type": "Number"
14426            },
14427            "example": [
14428                "\n<div class= “norender\">\n<code>\nvar a = PI + PI / 3;\nvar t = tan(a);\nvar 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>\nvar a = PI + PI / 3.0;\nvar t = tan(a);\nvar at = atan(t);\n// Prints: \"4.1887903 : 1.7320513 : 1.0471977\"\nprint(a + ' : ' + t + ' : ' + at);\n</code>\n</div>\n"
14429            ],
14430            "class": "p5",
14431            "module": "Math",
14432            "submodule": "Trigonometry"
14433        },
14434        {
14435            "file": "src/math/trigonometry.js",
14436            "line": 124,
14437            "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() 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",
14438            "itemtype": "method",
14439            "name": "atan2",
14440            "params": [
14441                {
14442                    "name": "y",
14443                    "description": "<p>y-coordinate of the point</p>\n",
14444                    "type": "Number"
14445                },
14446                {
14447                    "name": "x",
14448                    "description": "<p>x-coordinate of the point</p>\n",
14449                    "type": "Number"
14450                }
14451            ],
14452            "return": {
14453                "description": "the arc tangent of the given point",
14454                "type": "Number"
14455            },
14456            "example": [
14457                "\n<div>\n<code>\nfunction draw() {\n  background(204);\n  translate(width / 2, height / 2);
14457\n  var a = atan2(mouseY - height / 2, mouseX - width / 2);\n  rotate(a);\n  rect(-30, -5, 60, 10);\n}\n</code>\n</div>"
14458            ],
14459            "alt": "60 by 10 rect at center of canvas rotates with mouse movements",
14460            "class": "p5",
14461            "module": "Math",
14462            "submodule": "Trigonometry"
14463        },
14464        {
14465            "file": "src/math/trigonometry.js",
14466            "line": 160,
14467            "description": "<p>Calculates the cosine of an angle. This function takes into account the\ncurrent angleMode. Values are returned in the range -1 to 1.</p>\n",
14468            "itemtype": "method",
14469            "name": "cos",
14470            "params": [
14471                {
14472                    "name": "angle",
14473                    "description": "<p>the angle</p>\n",
14474                    "type": "Number"
14475                }
14476            ],
14477            "return": {
14478                "description": "the cosine of the angle",
14479                "type": "Number"
14480            },
14481            "example": [
14482                "\n<div>\n<code>\nvar a = 0.0;\nvar inc = TWO_PI / 25.0;\nfor (var 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>"
14483            ],
14484            "alt": "vertical black lines form wave patterns, extend-down on left and right side",
14485            "class": "p5",
14486            "module": "Math",
14487            "submodule": "Trigonometry"
14488        },
14489        {
14490            "file": "src/math/trigonometry.js",
14491            "line": 188,
14492            "description": "<p>Calculates the sine of an angle. This function takes into account the\ncurrent angleMode. Values are returned in the range -1 to 1.</p>\n",
14493            "itemtype": "method",
14494            "name": "sin",
14495            "params": [
14496                {
14497                    "name": "angle",
14498                    "description": "<p>the angle</p>\n",
14499                    "type": "Number"
14500                }
14501            ],
14502            "return": {
14503                "description": "the sine of the angle",
14504                "type": "Number"
14505            },
14506            "example": [
14507                "\n<div>\n<code>\nvar a = 0.0;\nvar inc = TWO_PI / 25.0;\nfor (var 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>"
14508            ],
14509            "alt": "vertical black lines extend down and up from center to form wave pattern",
14510            "class": "p5",
14511            "module": "Math",
14512            "submodule": "Trigonometry"
14513        },
14514        {
14515            "file": "src/math/trigonometry.js",
14516            "line": 216,
14517            "description": "<p>Calculates the tangent of an angle. This function takes into account\nthe current angleMode. Values are returned in the range -1 to 1.</p>\n",
14518            "itemtype": "method",
14519            "name": "tan",
14520            "params": [
14521                {
14522                    "name": "angle",
14523                    "description": "<p>the angle</p>\n",
14524                    "type": "Number"
14525                }
14526            ],
14527            "return": {
14528                "description": "the tangent of the angle",
14529                "type": "Number"
14530            },
14531            "example": [
14532                "\n<div>\n<code>\nvar a = 0.0;\nvar inc = TWO_PI / 50.0;\nfor (var i = 0; i < 100; i = i + 2) {\n  line(i, 50, i, 50 + tan(a) * 2.0);\n  a = a + inc;\n}\n</code>"
14533            ],
14534            "alt": "vertical black lines end down and up from center to form spike pattern",
14535            "class": "p5",
14536            "module": "Math",
14537            "submodule": "Trigonometry"
14538        },
14539        {
14540            "file": "src/math/trigonometry.js",
14541            "line": 244,
14542            "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 angleMode.</p>\n",
14543            "itemtype": "method",
14544            "name": "degrees",
14545            "params": [
14546                {
14547                    "name": "radians",
14548                    "description": "<p>the radians value to convert to degrees</p>\n",
14549                    "type": "Number"
14550                }
14551            ],
14552            "return": {
14553                "description": "the converted angle",
14554                "type": "Number"
14555            },
14556            "example": [
14557                "\n<div class= “norender\">\n<code>\nvar rad = PI / 4;\nvar deg = degrees(rad);\nprint(rad + ' radians is ' + deg + ' degrees');\n// Prints: 0.7853981633974483 radians is 45 degrees\n</code>\n</div>\n"
14558            ],
14559            "class": "p5",
14560            "module": "Math",
14561            "submodule": "Trigonometry"
14562        },
14563        {
14564            "file": "src/math/trigonometry.js",
14565            "line": 271,
14566            "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 angleMode.</p>\n",
14567            "itemtype": "method",
14568            "name": "radians",
14569            "params": [
14570                {
14571                    "name": "degrees",
14572                    "description": "<p>the degree value to convert to radians</p>\n",
14573                    "type": "Number"
14574                }
14575            ],
14576            "return": {
14577                "description": "the converted angle",
14578                "type": "Number"
14579            },
14580            "example": [
14581                "\n<div class= “norender\">\n<code>\nvar deg = 45.0;\nvar rad = radians(deg);\nprint(deg + ' degrees is ' + rad + ' radians');\n// Prints: 45 degrees is 0.7853981633974483 radians\n</code>\n</div>"
14582            ],
14583            "class": "p5",
14584            "module": "Math",
14585            "submodule": "Trigonometry"
14586        },
14587        {
14588            "file": "src/math/trigonometry.js",
14589            "line": 296,
14590            "description": "<p>Sets the current mode of p5 to given mode. Default mode is RADIANS.</p>\n",
14591            "itemtype": "method",
14592            "name": "angleMode",
14593            "params": [
14594                {
14595                    "name": "mode",
14596                    "description": "<p>either RADIANS or DEGREES</p>\n",
14597                    "type": "Constant"
14598                }
14599            ],
14600            "example": [
14601                "\n<div>\n<code>\nfunction draw() {\n  background(204);\n  angleMode(DEGREES);
14601 // Change the mode to DEGREES\n  var 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); // var a stays the same\n  rect(-40, -5, 20, 10); // Smaller rectangle is rotating in radians\n}\n</code>\n</div>"
14602            ],
14603            "alt": "40 by 10 rect in center rotates with mouse moves. 20 by 10 rect moves faster.",
14604            "class": "p5",
14605            "module": "Math",
14606            "submodule": "Trigonometry"
14607        },
14608        {
14609            "file": "src/typography/attributes.js",
14610            "line": 13,
14611            "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 text() 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 text(). 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",
14612            "itemtype": "method",
14613            "name": "textAlign",
14614            "chainable": 1,
14615            "example": [
14616                "\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>"
14617            ],
14618            "alt": "Letters ABCD displayed at top right, EFGH at center and IJKL at bottom left.",
14619            "class": "p5",
14620            "module": "Typography",
14621            "submodule": "Attributes",
14622            "overloads": [
14623                {
14624                    "line": 13,
14625                    "params": [
14626                        {
14627                            "name": "horizAlign",
14628                            "description": "<p>horizontal alignment, either LEFT,\n                           CENTER, or RIGHT</p>\n",
14629                            "type": "Constant"
14630                        },
14631                        {
14632                            "name": "vertAlign",
14633                            "description": "<p>vertical alignment, either TOP,\n                           BOTTOM, CENTER, or BASELINE</p>\n",
14634                            "type": "Constant",
14635                            "optional": true
14636                        }
14637                    ],
14638                    "chainable": 1
14639                },
14640                {
14641                    "line": 51,
14642                    "params": [],
14643                    "return": {
14644                        "description": "",
14645                        "type": "Object"
14646                    }
14647                }
14648            ]
14649        },
14650        {
14651            "file": "src/typography/attributes.js",
14652            "line": 60,
14653            "description": "<p>Sets/gets the spacing, in pixels, between lines of text. This\nsetting will be used in all subsequent calls to the text() function.</p>\n",
14654            "itemtype": "method",
14655            "name": "textLeading",
14656            "chainable": 1,
14657            "example": [
14658                "\n<div>\n<code>\n// Text to display. The \"\\n\" is a \"new line\" character\nvar 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>"
14659            ],
14660            "alt": "set L1 L2 & L3 displayed vertically 3 times. spacing increases for each set",
14661            "class": "p5",
14662            "module": "Typography",
14663            "submodule": "Attributes",
14664            "overloads": [
14665                {
14666                    "line": 60,
14667                    "params": [
14668                        {
14669                            "name": "leading",
14670                            "description": "<p>the size in pixels for spacing between lines</p>\n",
14671                            "type": "Number"
14672                        }
14673                    ],
14674                    "chainable": 1
14675                },
14676                {
14677                    "line": 89,
14678                    "params": [],
14679                    "return": {
14680                        "description": "",
14681                        "type": "Number"
14682                    }
14683                }
14684            ]
14685        },
14686        {
14687            "file": "src/typography/attributes.js",
14688            "line": 98,
14689            "description": "<p>Sets/gets the current font size. This size will be used in all subsequent\ncalls to the text() function. Font size is measured in pixels.</p>\n",
14690            "itemtype": "method",
14691            "name": "textSize",
14692            "chainable": 1,
14693            "example": [
14694                "\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>"
14695            ],
14696            "alt": "Font Size 12 displayed small, Font Size 14 medium & Font Size 16 large",
14697            "class": "p5",
14698            "module": "Typography",
14699            "submodule": "Attributes",
14700            "overloads": [
14701                {
14702                    "line": 98,
14703                    "params": [
14704                        {
14705                            "name": "theSize",
14706                            "description": "<p>the size of the letters in units of pixels</p>\n",
14707                            "type": "Number"
14708                        }
14709                    ],
14710                    "chainable": 1
14711                },
14712                {
14713                    "line": 121,
14714                    "params": [],
14715                    "return": {
14716                        "description": "",
14717                        "type": "Number"
14718                    }
14719                }
14720            ]
14721        },
14722        {
14723            "file": "src/typography/attributes.js",
14724            "line": 130,
14725            "description": "<p>Sets/gets the style of the text for system fonts to NORMAL, ITALIC, or BOLD.\nNote: this may be is overridden by CSS styling. For non-system fonts\n(opentype, truetype, etc.) please load styled fonts instead.</p>\n",
14726            "itemtype": "method",
14727            "name": "textStyle",
14728            "chainable": 1,
14729            "example": [
14730                "\n<div>\n<code>\nstrokeWeight(0);\ntextSize(12);\ntextStyle(NORMAL);\ntext('Font Style Normal', 10, 30);\ntextStyle(ITALIC);\ntext('Font Style Italic', 10, 60);\ntextStyle(BOLD);\ntext('Font Style Bold', 10, 90);\n</code>\n</div>"
14731            ],
14732            "alt": "words Font Style Normal displayed normally, Italic in italic and bold in bold",
14733            "class": "p5",
14734            "module": "Typography",
14735            "submodule": "Attributes",
14736            "overloads": [
14737                {
14738                    "line": 130,
14739                    "params": [
14740                        {
14741                            "name": "theStyle",
14742                            "description": "<p>styling for text, either NORMAL,\n                           ITALIC, or BOLD</p>\n",
14743                            "type": "Constant"
14744                        }
14745                    ],
14746                    "chainable": 1
14747                },
14748                {
14749                    "line": 156,
14750                    "params": [],
14751                    "return": {
14752                        "description": "",
14753                        "type": "String"
14754                    }
14755                }
14756            ]
14757        },
14758        {
14759            "file": "src/typography/attributes.js",
14760            "line": 165,
14761            "description": "<p>
14761Calculates and returns the width of any character or text string.</p>\n",
14762            "itemtype": "method",
14763            "name": "textWidth",
14764            "params": [
14765                {
14766                    "name": "theText",
14767                    "description": "<p>the String of characters to measure</p>\n",
14768                    "type": "String"
14769                }
14770            ],
14771            "return": {
14772                "description": "",
14773                "type": "Number"
14774            },
14775            "example": [
14776                "\n<div>\n<code>\ntextSize(28);\n\nvar aChar = 'P';\nvar cWidth = textWidth(aChar);\ntext(aChar, 0, 40);\nline(cWidth, 0, cWidth, 50);\n\nvar aString = 'p5.js';\nvar sWidth = textWidth(aString);\ntext(aString, 0, 85);\nline(sWidth, 50, sWidth, 100);\n</code>\n</div>"
14777            ],
14778            "alt": "Letter P and p5.js are displayed with vertical lines at end. P is wide",
14779            "class": "p5",
14780            "module": "Typography",
14781            "submodule": "Attributes"
14782        },
14783        {
14784            "file": "src/typography/attributes.js",
14785            "line": 200,
14786            "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",
14787            "itemtype": "method",
14788            "name": "textAscent",
14789            "return": {
14790                "description": "",
14791                "type": "Number"
14792            },
14793            "example": [
14794                "\n<div>\n<code>\nvar base = height * 0.75;\nvar scalar = 0.8; // Different for each font\n\ntextSize(32); // Set initial text size\nvar 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>"
14795            ],
14796            "class": "p5",
14797            "module": "Typography",
14798            "submodule": "Attributes"
14799        },
14800        {
14801            "file": "src/typography/attributes.js",
14802            "line": 229,
14803            "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",
14804            "itemtype": "method",
14805            "name": "textDescent",
14806            "return": {
14807                "description": "",
14808                "type": "Number"
14809            },
14810            "example": [
14811                "\n<div>\n<code>\nvar base = height * 0.75;\nvar scalar = 0.8; // Different for each font\n\ntextSize(32); // Set initial text size\nvar 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>"
14812            ],
14813            "class": "p5",
14814            "module": "Typography",
14815            "submodule": "Attributes"
14816        },
14817        {
14818            "file": "src/typography/attributes.js",
14819            "line": 258,
14820            "description": "<p>Helper function to measure ascent and descent.</p>\n",
14821            "class": "p5",
14822            "module": "Typography",
14823            "submodule": "Attributes"
14824        },
14825        {
14826            "file": "src/typography/loading_displaying.js",
14827            "line": 16,
14828            "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 an from a URL or other\nremote location may be blocked due to your browser&#39;s built-in\nsecurity.</p>\n",
14829            "itemtype": "method",
14830            "name": "loadFont",
14831            "params": [
14832                {
14833                    "name": "path",
14834                    "description": "<p>name of the file or url to load</p>\n",
14835                    "type": "String"
14836                },
14837                {
14838                    "name": "callback",
14839                    "description": "<p>function to be executed after\n                                   loadFont() completes</p>\n",
14840                    "type": "Function",
14841                    "optional": true
14842                },
14843                {
14844                    "name": "onError",
14845                    "description": "<p>function to be executed if\n                                   an error occurs</p>\n",
14846                    "type": "Function",
14847                    "optional": true
14848                }
14849            ],
14850            "return": {
14851                "description": "p5.Font object",
14852                "type": "p5.Font"
14853            },
14854            "example": [
14855                "\n\n<p>Calling loadFont() inside preload() guarantees that the load\noperation will have completed before setup() and draw() are called.</p>\n\n<div><code>\nvar 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 preload(), 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 string name of the font to style other HTML\nelements.</p>\n\n<div><code>\nfunction preload() {\n  loadFont('assets/Avenir.otf');\n}\n\nfunction setup() {\n  var myDiv = createDiv('hello there');\n  myDiv.style('font-family', 'Avenir');\n}\n</code></div>"
14856            ],
14857            "alt": "p5*js in p5's theme dark pink\np5*js in p5's theme dark pink",
14858            "class": "p5",
14859            "module": "Typography",
14860            "submodule": "Loading & Displaying"
14861        },
14862        {
14863            "file": "src/typography/loading_displaying.js",
14864            "line": 143,
14865            "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\ntextFont() function and a default size will be used unless a font is set\nwith textSize(). Change the color of the text with the fill() function.\nChange the outline of the text with the stroke() and strokeWeight(
14865)\nfunctions.\n<br><br>\nThe text displays in relation to the textAlign() 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 rectMode() setting. Text that\ndoes not fit completely within the rectangle specified will not be drawn\nto the screen.</p>\n",
14866            "itemtype": "method",
14867            "name": "text",
14868            "params": [
14869                {
14870                    "name": "str",
14871                    "description": "<p>the alphanumeric\n                                            symbols to be displayed</p>\n",
14872                    "type": "String|Object|Array|Number|Boolean"
14873                },
14874                {
14875                    "name": "x",
14876                    "description": "<p>x-coordinate of text</p>\n",
14877                    "type": "Number"
14878                },
14879                {
14880                    "name": "y",
14881                    "description": "<p>y-coordinate of text</p>\n",
14882                    "type": "Number"
14883                },
14884                {
14885                    "name": "x2",
14886                    "description": "<p>by default, the width of the text box,\n                    see rectMode() for more info</p>\n",
14887                    "type": "Number",
14888                    "optional": true
14889                },
14890                {
14891                    "name": "y2",
14892                    "description": "<p>by default, the height of the text box,\n                    see rectMode() for more info</p>\n",
14893                    "type": "Number",
14894                    "optional": true
14895                }
14896            ],
14897            "chainable": 1,
14898            "example": [
14899                "\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>\nvar 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>"
14900            ],
14901            "alt": "'word' displayed 3 times going from black, blue to translucent blue\nThe quick brown fox jumped over the lazy dog.",
14902            "class": "p5",
14903            "module": "Typography",
14904            "submodule": "Loading & Displaying"
14905        },
14906        {
14907            "file": "src/typography/loading_displaying.js",
14908            "line": 202,
14909            "description": "<p>Sets the current font that will be drawn with the text() function.</p>\n",
14910            "itemtype": "method",
14911            "name": "textFont",
14912            "return": {
14913                "description": "the current font",
14914                "type": "Object"
14915            },
14916            "example": [
14917                "\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>\nvar 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>"
14918            ],
14919            "alt": "words Font Style Normal displayed normally, Italic in italic and bold in bold",
14920            "class": "p5",
14921            "module": "Typography",
14922            "submodule": "Loading & Displaying",
14923            "overloads": [
14924                {
14925                    "line": 202,
14926                    "params": [],
14927                    "return": {
14928                        "description": "the current font",
14929                        "type": "Object"
14930                    }
14931                },
14932                {
14933                    "line": 245,
14934                    "params": [
14935                        {
14936                            "name": "font",
14937                            "description": "<p>a font loaded via loadFont(), 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",
14938                            "type": "Object|String"
14939                        },
14940                        {
14941                            "name": "size",
14942                            "description": "<p>the font size to use</p>\n",
14943                            "type": "Number",
14944                            "optional": true
14945                        }
14946                    ],
14947                    "chainable": 1
14948                }
14949            ]
14950        },
14951        {
14952            "file": "src/typography/p5.Font.js",
14953            "line": 31,
14954            "description": "<p>Underlying opentype font implementation</p>\n",
14955            "itemtype": "property",
14956            "name": "font",
14957            "class": "p5.Font",
14958            "module": "Typography",
14959            "submodule": "Font"
14960        },
14961        {
14962            "file": "src/typography/p5.Font.js",
14963            "line": 43,
14964            "description": "<p>
14964Returns a tight bounding box for the given text string using this\nfont (currently only supports single lines)</p>\n",
14965            "itemtype": "method",
14966            "name": "textBounds",
14967            "params": [
14968                {
14969                    "name": "line",
14970                    "description": "<p>a line of text</p>\n",
14971                    "type": "String"
14972                },
14973                {
14974                    "name": "x",
14975                    "description": "<p>x-position</p>\n",
14976                    "type": "Number"
14977                },
14978                {
14979                    "name": "y",
14980                    "description": "<p>y-position</p>\n",
14981                    "type": "Number"
14982                },
14983                {
14984                    "name": "fontSize",
14985                    "description": "<p>font size to use (optional)</p>\n",
14986                    "type": "Number",
14987                    "optional": true
14988                },
14989                {
14990                    "name": "options",
14991                    "description": "<p>opentype options (optional)</p>\n",
14992                    "type": "Object",
14993                    "optional": true
14994                }
14995            ],
14996            "return": {
14997                "description": "a rectangle object with properties: x, y, w, h",
14998                "type": "Object"
14999            },
15000            "example": [
15001                "\n<div>\n<code>\nvar font;\nvar textString = 'Lorem ipsum dolor sit amet.';\nfunction preload() {\n  font = loadFont('./assets/Regular.otf');\n}\nfunction setup() {\n  background(210);\n\n  var 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>"
15002            ],
15003            "alt": "words Lorem ipsum dol go off canvas and contained by white bounding box",
15004            "class": "p5.Font",
15005            "module": "Typography",
15006            "submodule": "Font"
15007        },
15008        {
15009            "file": "src/typography/p5.Font.js",
15010            "line": 158,
15011            "description": "<p>Computes an array of points following the path for specified text</p>\n",
15012            "itemtype": "method",
15013            "name": "textToPoints",
15014            "params": [
15015                {
15016                    "name": "txt",
15017                    "description": "<p>a line of text</p>\n",
15018                    "type": "String"
15019                },
15020                {
15021                    "name": "x",
15022                    "description": "<p>x-position</p>\n",
15023                    "type": "Number"
15024                },
15025                {
15026                    "name": "y",
15027                    "description": "<p>y-position</p>\n",
15028                    "type": "Number"
15029                },
15030                {
15031                    "name": "fontSize",
15032                    "description": "<p>font size to use (optional)</p>\n",
15033                    "type": "Number"
15034                },
15035                {
15036                    "name": "options",
15037                    "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",
15038                    "type": "Object",
15039                    "optional": true
15040                }
15041            ],
15042            "return": {
15043                "description": "an array of points, each with x, y, alpha (the path angle)",
15044                "type": "Array"
15045            },
15046            "example": [
15047                "\n<div>\n<code>\nvar font;\nfunction preload() {\n  font = loadFont('./assets/Avenir.otf');\n}\n\nvar points;\nvar 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 (var i = 0; i < points.length;
15047 i++) {\n    var 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"
15048            ],
15049            "class": "p5.Font",
15050            "module": "Typography",
15051            "submodule": "Font"
15052        },
15053        {
15054            "file": "src/utilities/array_functions.js",
15055            "line": 12,
15056            "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",
15057            "itemtype": "method",
15058            "name": "append",
15059            "deprecated": true,
15060            "deprecationMessage": "Use <a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push\">array.push(value)</a> instead.",
15061            "params": [
15062                {
15063                    "name": "array",
15064                    "description": "<p>Array to append</p>\n",
15065                    "type": "Array"
15066                },
15067                {
15068                    "name": "value",
15069                    "description": "<p>to be added to the Array</p>\n",
15070                    "type": "Any"
15071                }
15072            ],
15073            "example": [
15074                "\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>"
15075            ],
15076            "class": "p5",
15077            "module": "Data",
15078            "submodule": "Array Functions"
15079        },
15080        {
15081            "file": "src/utilities/array_functions.js",
15082            "line": 36,
15083            "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 concat().\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",
15084            "itemtype": "method",
15085            "name": "arrayCopy",
15086            "deprecated": true,
15087            "example": [
15088                "\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>"
15089            ],
15090            "class": "p5",
15091            "module": "Data",
15092            "submodule": "Array Functions",
15093            "overloads": [
15094                {
15095                    "line": 36,
15096                    "params": [
15097                        {
15098                            "name": "src",
15099                            "description": "<p>the source Array</p>\n",
15100                            "type": "Array"
15101                        },
15102                        {
15103                            "name": "srcPosition",
15104                            "description": "<p>starting position in the source Array</p>\n",
15105                            "type": "Integer"
15106                        },
15107                        {
15108                            "name": "dst",
15109                            "description": "<p>the destination Array</p>\n",
15110                            "type": "Array"
15111                        },
15112                        {
15113                            "name": "dstPosition",
15114                            "description": "<p>starting position in the destination Array</p>\n",
15115                            "type": "Integer"
15116                        },
15117                        {
15118                            "name": "length",
15119                            "description": "<p>number of Array elements to be copied</p>\n",
15120                            "type": "Integer"
15121                        }
15122                    ]
15123                },
15124                {
15125                    "line": 74,
15126                    "params": [
15127                        {
15128                            "name": "src",
15129                            "description": "",
15130                            "type": "Array"
15131                        },
15132                        {
15133                            "name": "dst",
15134                            "description": "",
15135                            "type": "Array"
15136                        },
15137                        {
15138                            "name": "length",
15139                            "description": "",
15140                            "type": "Integer",
15141                            "optional": true
15142                        }
15143                    ]
15144                }
15145            ]
15146        },
15147        {
15148            "file": "src/utilities/array_functions.js",
15149            "line": 113,
15150            "description": "<p>Concatenates two arrays, maps to Array.concat(). Does not modify the\ninput arrays.</p>\n",
15151            "itemtype": "method",
15152            "name": "concat",
15153            "deprecated": true,
15154            "deprecationMessage": "Use <a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat\">arr1.concat(arr2)</a> instead.",
15155            "params": [
15156                {
15157                    "name": "a",
15158                    "description": "<p>first Array to concatenate</p>\n",
15159                    "type": "Array"
15160                },
15161                {
15162                    "name": "b",
15163                    "description": "<p>second Array to concatenate</p>\n",
15164                    "type": "Array"
15165                }
15166            ],
15167            "return": {
15168                "description": "concatenated array",
15169                "type": "Array"
15170            },
15171            "example": [
15172                "\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>"
15173            ],
15174            "class": "p5",
15175            "module": "Data",
15176            "submodule": "Array Functions"
15177        },
15178        {
15179            "file": "src/utilities/array_functions.js",
15180            "line": 144,
15181            "description": "<p>Reverses the order of an array, maps to Array.reverse()</p>\n",
15182            "itemtype": "method",
15183            "name": "reverse",
15184            "deprecated": true,
15185            "deprecationMessage": "Use <a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse\">array.reverse()</a> instead.",
15186            "params": [
15187                {
15188                    "name": "list",
15189                    "description": "<p>Array to reverse</p>\n",
15190                    "type": "Array"
15191                }
15192            ],
15193            "example": [
15194                "\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>"
15195            ],
15196            "class": "p5",
15197            "module": "Data",
15198            "submodule": "Array Functions"
15199        },
15200        {
15201            "file": "src/utilities/array_functions.js",
15202            "line": 165,
15203            "description": "<p>Decreases an array by one element and returns the shortened array,\nmaps to Array.pop().</p>\n",
15204            "itemtype": "method",
15205            "name": "shorten",
15206            "deprecated": true,
15207            "deprecationMessage": "Use <a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/pop\">array.pop()</a> instead.",
15208            "params": [
15209                {
15210                    "name": "list",
15211                    "description": "<p>Array to shorten</p>\n",
15212                    "type": "Array"
15213                }
15214            ],
15215            "return": {
15216                "description": "shortened Array",
15217                "type": "Array"
15218            },
15219            "example": [
15220                "\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>"
15221            ],
15222            "class": "p5",
15223            "module": "Data",
15224            "submodule": "Array Functions"
15225        },
15226        {
15227            "file": "src/utilities/array_functions.js",
15228            "line": 189,
15229            "description": "<p>Randomizes the order of the elements of an array. Implements\n<a href='http://Bost.Ocks.org/mike/shuffle/' target=_blank>
15229\nFisher-Yates Shuffle Algorithm</a>.</p>\n",
15230            "itemtype": "method",
15231            "name": "shuffle",
15232            "deprecated": true,
15233            "deprecationMessage": "See <a href=\"https://stackoverflow.com/questions/6274339/how-can-i-shuffle-an-array\">shuffling an array with JS</a> instead.",
15234            "params": [
15235                {
15236                    "name": "array",
15237                    "description": "<p>Array to shuffle</p>\n",
15238                    "type": "Array"
15239                },
15240                {
15241                    "name": "bool",
15242                    "description": "<p>modify passed array</p>\n",
15243                    "type": "Boolean",
15244                    "optional": true
15245                }
15246            ],
15247            "return": {
15248                "description": "shuffled Array",
15249                "type": "Array"
15250            },
15251            "example": [
15252                "\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>"
15253            ],
15254            "class": "p5",
15255            "module": "Data",
15256            "submodule": "Array Functions"
15257        },
15258        {
15259            "file": "src/utilities/array_functions.js",
15260            "line": 232,
15261            "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",
15262            "itemtype": "method",
15263            "name": "sort",
15264            "deprecated": true,
15265            "deprecationMessage": "Use <a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort\">array.sort()</a> instead.",
15266            "params": [
15267                {
15268                    "name": "list",
15269                    "description": "<p>Array to sort</p>\n",
15270                    "type": "Array"
15271                },
15272                {
15273                    "name": "count",
15274                    "description": "<p>number of elements to sort, starting from 0</p>\n",
15275                    "type": "Integer",
15276                    "optional": true
15277                }
15278            ],
15279            "example": [
15280                "\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>"
15281            ],
15282            "class": "p5",
15283            "module": "Data",
15284            "submodule": "Array Functions"
15285        },
15286        {
15287            "file": "src/utilities/array_functions.js",
15288            "line": 279,
15289            "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",
15290            "itemtype": "method",
15291            "name": "splice",
15292            "deprecated": true,
15293            "deprecationMessage": "Use <a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice\">array.splice()</a> instead.",
15294            "params": [
15295                {
15296                    "name": "list",
15297                    "description": "<p>Array to splice into</p>\n",
15298                    "type": "Array"
15299                },
15300                {
15301                    "name": "value",
15302                    "description": "<p>value to be spliced in</p>\n",
15303                    "type": "Any"
15304                },
15305                {
15306                    "name": "position",
15307                    "description": "<p>in the array from which to insert data</p>\n",
15308                    "type": "Integer"
15309                }
15310            ],
15311            "example": [
15312                "\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>"
15313            ],
15314            "class": "p5",
15315            "module": "Data",
15316            "submodule": "Array Functions"
15317        },
15318        {
15319            "file": "src/utilities/array_functions.js",
15320            "line": 313,
15321            "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",
15322            "itemtype": "method",
15323            "name": "subset",
15324            "deprecated": true,
15325            "deprecationMessage": "Use <a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice\">array.slice()</a> instead.",
15326            "params": [
15327                {
15328                    "name": "list",
15329                    "description": "<p>Array to extract from</p>\n",
15330                    "type": "Array"
15331                },
15332                {
15333                    "name": "start",
15334                    "description": "<p>position to begin</p>\n",
15335                    "type": "Integer"
15336                },
15337                {
15338                    "name": "count",
15339                    "description": "<p>number of values to extract</p>\n",
15340                    "type": "Integer",
15341                    "optional": true
15342                }
15343            ],
15344            "return": {
15345                "description": "Array of extracted elements",
15346                "type": "Array"
15347            },
15348            "example": [
15349                "\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>"
15350            ],
15351            "class": "p5",
15352            "module": "Data",
15353            "submodule": "Array Functions"
15354        },
15355        {
15356            "file": "src/utilities/conversion.js",
15357            "line": 12,
15358            "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",
15359            "itemtype": "method",
15360            "name": "float",
15361            "params": [
15362                {
15363                    "name": "str",
15364                    "description": "<p>float string to parse</p>\n",
15365                    "type": "String"
15366                }
15367            ],
15368            "return": {
15369                "description": "floating point representation of str
15369ing",
15370                "type": "Number"
15371            },
15372            "example": [
15373                "\n<div><code>\nvar str = '20';\nvar diameter = float(str);\nellipse(width / 2, height / 2, diameter, diameter);\n</code></div>"
15374            ],
15375            "alt": "20 by 20 white ellipse in the center of the canvas",
15376            "class": "p5",
15377            "module": "Data",
15378            "submodule": "Conversion"
15379        },
15380        {
15381            "file": "src/utilities/conversion.js",
15382            "line": 42,
15383            "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",
15384            "itemtype": "method",
15385            "name": "int",
15386            "return": {
15387                "description": "integer representation of value",
15388                "type": "Number"
15389            },
15390            "example": [
15391                "\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>"
15392            ],
15393            "class": "p5",
15394            "module": "Data",
15395            "submodule": "Conversion",
15396            "overloads": [
15397                {
15398                    "line": 42,
15399                    "params": [
15400                        {
15401                            "name": "n",
15402                            "description": "<p>value to parse</p>\n",
15403                            "type": "String|Boolean|Number"
15404                        },
15405                        {
15406                            "name": "radix",
15407                            "description": "<p>the radix to convert to (default: 10)</p>\n",
15408                            "type": "Integer",
15409                            "optional": true
15410                        }
15411                    ],
15412                    "return": {
15413                        "description": "integer representation of value",
15414                        "type": "Number"
15415                    }
15416                },
15417                {
15418                    "line": 62,
15419                    "params": [
15420                        {
15421                            "name": "ns",
15422                            "description": "<p>values to parse</p>\n",
15423                            "type": "Array"
15424                        }
15425                    ],
15426                    "return": {
15427                        "description": "integer representation of values",
15428                        "type": "Number[]"
15429                    }
15430                }
15431            ]
15432        },
15433        {
15434            "file": "src/utilities/conversion.js",
15435            "line": 82,
15436            "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",
15437            "itemtype": "method",
15438            "name": "str",
15439            "params": [
15440                {
15441                    "name": "n",
15442                    "description": "<p>value to parse</p>\n",
15443                    "type": "String|Boolean|Number|Array"
15444                }
15445            ],
15446            "return": {
15447                "description": "string representation of value",
15448                "type": "String"
15449            },
15450            "example": [
15451                "\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>"
15452            ],
15453            "class": "p5",
15454            "module": "Data",
15455            "submodule": "Conversion"
15456        },
15457        {
15458            "file": "src/utilities/conversion.js",
15459            "line": 108,
15460            "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",
15461            "itemtype": "method",
15462            "name": "boolean",
15463            "params": [
15464                {
15465                    "name": "n",
15466                    "description": "<p>value to parse</p>\n",
15467                    "type": "String|Boolean|Number|Array"
15468                }
15469            ],
15470            "return": {
15471                "description": "boolean representation of value",
15472                "type": "Boolean"
15473            },
15474            "example": [
15475                "\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>"
15476            ],
15477            "class": "p5",
15478            "module": "Data",
15479            "submodule": "Conversion"
15480        },
15481        {
15482            "file": "src/utilities/conversion.js",
15483            "line": 140,
15484            "description": "<p>Converts a number, string representation of a number, or boolean to its byte\nrepresentation. A b
15484yte 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",
15485            "itemtype": "method",
15486            "name": "byte",
15487            "return": {
15488                "description": "byte representation of value",
15489                "type": "Number"
15490            },
15491            "example": [
15492                "\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>"
15493            ],
15494            "class": "p5",
15495            "module": "Data",
15496            "submodule": "Conversion",
15497            "overloads": [
15498                {
15499                    "line": 140,
15500                    "params": [
15501                        {
15502                            "name": "n",
15503                            "description": "<p>value to parse</p>\n",
15504                            "type": "String|Boolean|Number"
15505                        }
15506                    ],
15507                    "return": {
15508                        "description": "byte representation of value",
15509                        "type": "Number"
15510                    }
15511                },
15512                {
15513                    "line": 162,
15514                    "params": [
15515                        {
15516                            "name": "ns",
15517                            "description": "<p>values to parse</p>\n",
15518                            "type": "Array"
15519                        }
15520                    ],
15521                    "return": {
15522                        "description": "array of byte representation of values",
15523                        "type": "Number[]"
15524                    }
15525                }
15526            ]
15527        },
15528        {
15529            "file": "src/utilities/conversion.js",
15530            "line": 176,
15531            "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",
15532            "itemtype": "method",
15533            "name": "char",
15534            "return": {
15535                "description": "string representation of value",
15536                "type": "String"
15537            },
15538            "example": [
15539                "\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>"
15540            ],
15541            "class": "p5",
15542            "module": "Data",
15543            "submodule": "Conversion",
15544            "overloads": [
15545                {
15546                    "line": 176,
15547                    "params": [
15548                        {
15549                            "name": "n",
15550                            "description": "<p>value to parse</p>\n",
15551                            "type": "String|Number"
15552                        }
15553                    ],
15554                    "return": {
15555                        "description": "string representation of value",
15556                        "type": "String"
15557                    }
15558                },
15559                {
15560                    "line": 195,
15561                    "params": [
15562                        {
15563                            "name": "ns",
15564                            "description": "<p>values to parse</p>\n",
15565                            "type": "Array"
15566                        }
15567                    ],
15568                    "return": {
15569                        "description": "array of string representation of values",
15570                        "type": "String[]"
15571                    }
15572                }
15573            ]
15574        },
15575        {
15576            "file": "src/utilities/conversion.js",
15577            "line": 210,
15578            "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",
15579            "itemtype": "method",
15580            "name": "unchar",
15581            "return": {
15582                "description": "integer representation of value",
15583                "type": "Number"
15584            },
15585            "example": [
15586                "\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>"
15587            ],
15588            "class": "p5",
15589            "module": "Data",
15590            "submodule": "Conversion",
15591            "overloads": [
15592                {
15593                    "line": 210,
15594                    "params": [
15595                        {
15596                            "name": "n",
15597                            "description": "<p>value to parse</p>\n",
15598                            "type": "String"
15599                        }
15600                    ],
15601                    "return": {
15602                        "description": "integer representation of value",
15603                        "type": "Number"
15604                    }
15605                },
15606                {
15607                    "line": 226,
15608                    "params": [
15609                        {
15610                            "name": "ns",
15611                            "description": "<p>values to parse</p>\n",
15612                            "type": "Array"
15613                        }
15614                    ],
15615                    "return": {
15616                        "description": "integer representation of values",
15617                        "type": "Number[]"
15618                    }
15619                }
15620            ]
15621        },
15622        {
15623            "file": "src/utilities/conversion.js",
15624            "line": 239,
15625            "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
15625ings in hexadecimal notation of the same length is returned.</p>\n",
15626            "itemtype": "method",
15627            "name": "hex",
15628            "return": {
15629                "description": "hexadecimal string representation of value",
15630                "type": "String"
15631            },
15632            "example": [
15633                "\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>"
15634            ],
15635            "class": "p5",
15636            "module": "Data",
15637            "submodule": "Conversion",
15638            "overloads": [
15639                {
15640                    "line": 239,
15641                    "params": [
15642                        {
15643                            "name": "n",
15644                            "description": "<p>value to parse</p>\n",
15645                            "type": "Number"
15646                        },
15647                        {
15648                            "name": "digits",
15649                            "description": "",
15650                            "type": "Number",
15651                            "optional": true
15652                        }
15653                    ],
15654                    "return": {
15655                        "description": "hexadecimal string representation of value",
15656                        "type": "String"
15657                    }
15658                },
15659                {
15660                    "line": 257,
15661                    "params": [
15662                        {
15663                            "name": "ns",
15664                            "description": "<p>array of values to parse</p>\n",
15665                            "type": "Number[]"
15666                        },
15667                        {
15668                            "name": "digits",
15669                            "description": "",
15670                            "type": "Number",
15671                            "optional": true
15672                        }
15673                    ],
15674                    "return": {
15675                        "description": "hexadecimal string representation of values",
15676                        "type": "String[]"
15677                    }
15678                }
15679            ]
15680        },
15681        {
15682            "file": "src/utilities/conversion.js",
15683            "line": 286,
15684            "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",
15685            "itemtype": "method",
15686            "name": "unhex",
15687            "return": {
15688                "description": "integer representation of hexadecimal value",
15689                "type": "Number"
15690            },
15691            "example": [
15692                "\n<div class='norender'><code>\nprint(unhex('A')); // 10\nprint(unhex('FF')); // 255\nprint(unhex(['FF', 'AA', '00'])); // [ 255, 170, 0 ]\n</code></div>"
15693            ],
15694            "class": "p5",
15695            "module": "Data",
15696            "submodule": "Conversion",
15697            "overloads": [
15698                {
15699                    "line": 286,
15700                    "params": [
15701                        {
15702                            "name": "n",
15703                            "description": "<p>value to parse</p>\n",
15704                            "type": "String"
15705                        }
15706                    ],
15707                    "return": {
15708                        "description": "integer representation of hexadecimal value",
15709                        "type": "Number"
15710                    }
15711                },
15712                {
15713                    "line": 302,
15714                    "params": [
15715                        {
15716                            "name": "ns",
15717                            "description": "<p>values to parse</p>\n",
15718                            "type": "Array"
15719                        }
15720                    ],
15721                    "return": {
15722                        "description": "integer representations of hexadecimal value",
15723                        "type": "Number[]"
15724                    }
15725                }
15726            ]
15727        },
15728        {
15729            "file": "src/utilities/string_functions.js",
15730            "line": 15,
15731            "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 nf() or\nnfs().</p>\n",
15732            "itemtype": "method",
15733            "name": "join",
15734            "params": [
15735                {
15736                    "name": "list",
15737                    "description": "<p>array of Strings to be joined</p>\n",
15738                    "type": "Array"
15739                },
15740                {
15741                    "name": "separator",
15742                    "description": "<p>String to be placed between each item</p>\n",
15743                    "type": "String"
15744                }
15745            ],
15746            "return": {
15747                "description": "joined String",
15748                "type": "String"
15749            },
15750            "example": [
15751                "\n<div>\n<code>\nvar array = ['Hello', 'world!'];\nvar separator = ' ';\nvar message = join(array, separator);\ntext(message, 5, 50);\n</code>\n</div>"
15752            ],
15753            "alt": "\"hello world!\" displayed middle left of canvas.",
15754            "class": "p5",
15755            "module": "Data",
15756            "submodule": "String Functions"
15757        },
15758        {
15759            "file": "src/utilities/string_functions.js",
15760            "line": 44,
15761            "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",
15762            "itemtype": "method",
15763            "name": "match",
15764            "params": [
15765                {
15766                    "name": "str",
15767                    "description": "<p>the String to be searched</p>\n",
15768                    "type": "String"
15769                },
15770                {
15771                    "name": "regexp",
15772                    "description": "<p>the regexp to be used for matching</p>\n",
15773                    "type": "String"
15774                }
15775            ],
15776            "return": {
15777                "description": "Array of Strings found",
15778                "type": "String[]"
15779            },
15780            "example": [
15781                "\n<div>\n<code>\nvar string = 'Hello p5js*!';\nvar regexp = 'p5js\\\\*';\nvar m = match(string, regexp);\ntext(m, 5, 50);\n</code>\n</div>"
15782            ],
15783            "alt": "\"p5js*\" displayed middle left of canvas.",
15784            "class": "p5",
15785            "module": "Data",
15786            "submodule": "String Functions"
15787        },
15788        {
15789            "file": "src/utilities/string_functions.js",
15790            "line": 85,
15791            "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
15791ing 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",
15792            "itemtype": "method",
15793            "name": "matchAll",
15794            "params": [
15795                {
15796                    "name": "str",
15797                    "description": "<p>the String to be searched</p>\n",
15798                    "type": "String"
15799                },
15800                {
15801                    "name": "regexp",
15802                    "description": "<p>the regexp to be used for matching</p>\n",
15803                    "type": "String"
15804                }
15805            ],
15806            "return": {
15807                "description": "2d Array of Strings found",
15808                "type": "String[]"
15809            },
15810            "example": [
15811                "\n<div class=\"norender\">\n<code>\nvar string = 'Hello p5js*! Hello world!';\nvar regexp = 'Hello';\nmatchAll(string, regexp);\n</code>\n</div>"
15812            ],
15813            "class": "p5",
15814            "module": "Data",
15815            "submodule": "String Functions"
15816        },
15817        {
15818            "file": "src/utilities/string_functions.js",
15819            "line": 132,
15820            "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.</p>\n",
15821            "itemtype": "method",
15822            "name": "nf",
15823            "return": {
15824                "description": "formatted String",
15825                "type": "String"
15826            },
15827            "example": [
15828                "\n<div>\n<code>\nfunction setup() {\n  background(200);\n  var num = 112.53106115;\n\n  noStroke();\n  fill(0);\n  textSize(14);\n  // Draw formatted numbers\n  text(nf(num, 5, 2), 10, 20);\n\n  text(nf(num, 4, 3), 10, 55);\n\n  text(nf(num, 3, 6), 10, 85);\n\n  // Draw dividing lines\n  stroke(120);\n  line(0, 30, width, 30);\n  line(0, 65, width, 65);\n}\n</code>\n</div>"
15829            ],
15830            "alt": "\"0011253\" top left, \"0112.531\" mid left, \"112.531061\" bottom left canvas",
15831            "class": "p5",
15832            "module": "Data",
15833            "submodule": "String Functions",
15834            "overloads": [
15835                {
15836                    "line": 132,
15837                    "params": [
15838                        {
15839                            "name": "num",
15840                            "description": "<p>the Number to format</p>\n",
15841                            "type": "Number|String"
15842                        },
15843                        {
15844                            "name": "left",
15845                            "description": "<p>number of digits to the left of the\n                               decimal point</p>\n",
15846                            "type": "Integer|String",
15847                            "optional": true
15848                        },
15849                        {
15850                            "name": "right",
15851                            "description": "<p>number of digits to the right of the\n                               decimal point</p>\n",
15852                            "type": "Integer|String",
15853                            "optional": true
15854                        }
15855                    ],
15856                    "return": {
15857                        "description": "formatted String",
15858                        "type": "String"
15859                    }
15860                },
15861                {
15862                    "line": 174,
15863                    "params": [
15864                        {
15865                            "name": "nums",
15866                            "description": "<p>the Numbers to format</p>\n",
15867                            "type": "Array"
15868                        },
15869                        {
15870                            "name": "left",
15871                            "description": "",
15872                            "type": "Integer|String",
15873                            "optional": true
15874                        },
15875                        {
15876                            "name": "right",
15877                            "description": "",
15878                            "type": "Integer|String",
15879                            "optional": true
15880                        }
15881                    ],
15882                    "return": {
15883                        "description": "formatted Strings",
15884                        "type": "String[]"
15885                    }
15886                }
15887            ]
15888        },
15889        {
15890            "file": "src/utilities/string_functions.js",
15891            "line": 237,
15892            "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",
15893            "itemtype": "method",
15894            "name": "nfc",
15895            "return": {
15896                "description": "formatted String",
15897                "type": "String"
15898            },
15899            "example": [
15900                "\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>"
15901            ],
15902            "alt": "\"11,253,106.115\" top middle and \"1.00,1.00,2.00\" displayed bottom mid",
15903            "class": "p5",
15904            "module": "Data",
15905            "submodule": "String Functions",
15906            "overloads": [
15907                {
15908                    "line": 237,
15909                    "params": [
15910                        {
15911                            "name": "num",
15912                            "description": "<p>the Number to format</p>\n",
15913                            "type": "Number|String"
15914                        },
15915                        {
15916                            "name": "right",
15917                            "description": "<p>number of digits to the right of the\n                                 decimal point</p>\n",
15918                            "type": "Integer|String",
15919                            "optional": true
15920                        }
15921                    ],
15922                    "return": {
15923                        "description": "formatted String",
15924                        "type": "String"
15925                    }
15926                },
15927                {
15928                    "line": 275,
15929                    "params": [
15930                        {
15931                            "name": "nums",
15932                            "description": "<p>the Numbers to format</p>\n",
15933                            "type": "Array"
15934                        },
15935                        {
15936                            "name": "right",
15937                            "description": "",
15938                            "type": "Integer|String",
15939                            "optional": true
15940                        }
15941                    ],
15942                    "return": {
15943                        "description": "formatted Strings",
15944                        "type": "String[]"
15945                    }
15946                }
15947            ]
15948        },
15949        {
15950            "file": "src/utilities/string_functions.js",
15951            "line": 313,
15952            "description": "<p>Utility function for formatting numbers into strings. Similar to nf() 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",
15953            "itemtype": "method",
15954            "name": "nfp",
15955            "return": {
15956                "description": "formatted String",
15957                "type": "String"
15958            },
15959            "example": [
15960                "\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>"
15961            ],
15962            "alt": "\"+11253106.11\" top middle and \"-11253106.11\" displayed bottom middle",
15963            "class": "p5",
15964            "module": "Data",
15965            "submodule": "String Functions",
15966            "overloads": [
15967                {
15968                    "line": 313,
15969                    "params": [
15970                        {
15971                            "name": "num",
15972                            "description": "<p>the Number to format</p>\n",
15973                            "type": "Number"
15974                        },
15975                        {
15976                            "name": "left",
15977                            "description": "<p>number of digits to the left of the decimal\n                               point</p>\n",
15978                            "type": "Integer",
15979                            "optional": true
15980                        },
15981                        {
15982                            "name": "right",
15983                            "description": "<p>number of digits to the right of the\n                               decimal point</p>\n",
15984                            "type": "Integer",
15985                            "optional": true
15986                        }
15987                    ],
15988                    "return": {
15989                        "description": "formatted String",
15990                        "type": "String"
15991                    }
15992                },
15993                {
15994                    "line": 354,
15995                    "params": [
15996                        {
15997                            "name": "nums",
15998                            "description": "<p>the Numbers to format</p>\n",
15999                            "type": "Number[]"
16000                        },
16001                        {
16002                            "name": "left",
16003                            "description": "",
16004                            "type": "Integer",
16005                            "optional": true
16006                        },
16007                        {
16008                            "name": "right",
16009                            "description": "",
16010                            "type": "Integer",
16011                            "optional": true
16012                        }
16013                    ],
16014                    "return": {
16015                        "description": "formatted Strings",
16016                        "type": "String[]"
16017                    }
16018                }
16019            ]
16020        },
16021        {
16022            "file": "src/utilities/string_functions.js",
16023            "line": 375,
16024            "description": "<p>Utility function for formatting numbers into strings. Similar to nf() but\nputs a &quot; &quot; (space) in front of positive numbers and a &quot;-&quot; in front of\nnegative numbers. There are two versions: one for formatting floats, and\none for formatting ints. The values for the digits, left, and right\nparameters should always be positive integers.</p>\n",
16025            "itemtype": "method",
16026            "name": "nfs",
16027            "return": {
16028                "description": "formatted String",
16029                "type": "String"
16030            },
16031            "example": [
16032                "\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  // Draw formatted numbers\n  text(nfs(num1, 4, 2), 10, 30);\n\n  text(nfs(num2, 4, 2), 10, 80);\n\n  // Draw dividing line\n  stroke(120);\n  line(0, 50, width, 50);\n}\n</code>\n</div>"
16033            ],
16034            "alt": "\"11253106.11\" top middle and \"-11253106.11\" displayed bottom middle",
16035            "class": "p5",
16036            "module": "Data",
16037            "submodule": "String Functions",
16038            "overloads": [
16039                {
16040                    "line": 375,
16041                    "params": [
16042                        {
16043                            "name": "num",
16044                            "description": "<p>the Number to format</p>\n",
16045                            "type": "Number"
16046                        },
16047                        {
16048                            "name": "left",
16049                            "description": "<p>number of digits to the left of the decimal\n                               point</p>\n",
16050                            "type": "Integer",
16051                            "optional": true
16052                        },
16053                        {
16054                            "name": "right",
16055                            "description": "<p>number of digits to the right of the\n                               decimal point</p>\n",
16056                            "type": "Integer",
16057                            "optional": true
16058                        }
16059                    ],
16060                    "return": {
16061                        "description": "formatted String",
16062                        "type": "String"
16063                    }
16064                },
16065                {
16066                    "line": 416,
16067                    "params": [
16068                        {
16069                            "name": "nums",
16070                            "description": "<p>the Numbers to format</p>\n",
16071                            "type": "Array"
16072                        },
16073                        {
16074                            "name": "left",
16075                            "description": "",
16076                            "type": "Integer",
16077                            "optional": true
16078                        },
16079                        {
16080                            "name": "right",
16081                            "description": "",
16082                            "type": "Integer",
16083                            "optional": true
16084                        }
16085                    ],
16086                    "return": {
16087                        "description": "formatted Strings",
16088                        "type": "String[]"
16089                    }
16090                }
16091            ]
16092        },
16093        {
16094            "file": "src/utilities/string_functions.js",
16095            "line": 437,
16096            "description": "<p>The split() 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 splitTokens() function works in a similar fashion, except that it\nsplits using a range of characters instead of a specific character or\nsequence.</p>\n",
16097            "itemtype": "method",
16098            "name": "split",
16099            "params": [
16100                {
16101                    "name": "value",
16102                    "description": "<p>the String to be split</p>\n",
16103                    "type": "String"
16104                },
16105                {
16106                    "name": "delim",
16107                    "description": "<p>the String used to separate the data</p>\n",
16108                    "type": "String"
16109                }
16110            ],
16111            "return": {
16112                "description": "Array of Strings",
16113                "type": "String[]"
16114            },
16115            "example": [
16116                "\n<div>\n<code>\nvar names = 'Pat,Xio,Alex';\nvar splitString = split(names, ',');
16116\ntext(splitString[0], 5, 30);\ntext(splitString[1], 5, 50);\ntext(splitString[2], 5, 70);\n</code>\n</div>"
16117            ],
16118            "alt": "\"pat\" top left, \"Xio\" mid left and \"Alex\" displayed bottom left",
16119            "class": "p5",
16120            "module": "Data",
16121            "submodule": "String Functions"
16122        },
16123        {
16124            "file": "src/utilities/string_functions.js",
16125            "line": 471,
16126            "description": "<p>The splitTokens() 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",
16127            "itemtype": "method",
16128            "name": "splitTokens",
16129            "params": [
16130                {
16131                    "name": "value",
16132                    "description": "<p>the String to be split</p>\n",
16133                    "type": "String"
16134                },
16135                {
16136                    "name": "delim",
16137                    "description": "<p>list of individual Strings that will be used as\n                         separators</p>\n",
16138                    "type": "String",
16139                    "optional": true
16140                }
16141            ],
16142            "return": {
16143                "description": "Array of Strings",
16144                "type": "String[]"
16145            },
16146            "example": [
16147                "\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>"
16148            ],
16149            "class": "p5",
16150            "module": "Data",
16151            "submodule": "String Functions"
16152        },
16153        {
16154            "file": "src/utilities/string_functions.js",
16155            "line": 526,
16156            "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",
16157            "itemtype": "method",
16158            "name": "trim",
16159            "return": {
16160                "description": "a trimmed String",
16161                "type": "String"
16162            },
16163            "example": [
16164                "\n<div>\n<code>\nvar string = trim('  No new lines\\n   ');\ntext(string + ' here', 2, 50);\n</code>\n</div>"
16165            ],
16166            "alt": "\"No new lines here\" displayed center canvas",
16167            "class": "p5",
16168            "module": "Data",
16169            "submodule": "String Functions",
16170            "overloads": [
16171                {
16172                    "line": 526,
16173                    "params": [
16174                        {
16175                            "name": "str",
16176                            "description": "<p>a String to be trimmed</p>\n",
16177                            "type": "String"
16178                        }
16179                    ],
16180                    "return": {
16181                        "description": "a trimmed String",
16182                        "type": "String"
16183                    }
16184                },
16185                {
16186                    "line": 546,
16187                    "params": [
16188                        {
16189                            "name": "strs",
16190                            "description": "<p>an Array of Strings to be trimmed</p>\n",
16191                            "type": "Array"
16192                        }
16193                    ],
16194                    "return": {
16195                        "description": "an Array of trimmed Strings",
16196                        "type": "String[]"
16197                    }
16198                }
16199            ]
16200        },
16201        {
16202            "file": "src/utilities/time_date.js",
16203            "line": 12,
16204            "description": "<p>p5.js communicates with the clock on your computer. The day() function\nreturns the current day as a value from 1 - 31.</p>\n",
16205            "itemtype": "method",
16206            "name": "day",
16207            "return": {
16208                "description": "the current day",
16209                "type": "Integer"
16210            },
16211            "example": [
16212                "\n<div>\n<code>\nvar d = day();\ntext('Current day: \\n' + d, 5, 50);\n</code>\n</div>"
16213            ],
16214            "alt": "Current day is displayed",
16215            "class": "p5",
16216            "module": "IO",
16217            "submodule": "Time & Date"
16218        },
16219        {
16220            "file": "src/utilities/time_date.js",
16221            "line": 34,
16222            "description": "<p>p5.js communicates with the clock on your computer. The hour() function\nreturns the current hour as a value from 0 - 23.</p>\n",
16223            "itemtype": "method",
16224            "name": "hour",
16225            "return": {
16226                "description": "the current hour",
16227                "type": "Integer"
16228            },
16229            "example": [
16230                "\n<div>\n<code>\nvar h = hour();\ntext('Current hour:\\n' + h, 5, 50);\n</code>\n</div>"
16231            ],
16232            "alt": "Current hour is displayed",
16233            "class": "p5",
16234            "module": "IO",
16235            "submodule": "Time & Date"
16236        },
16237        {
16238            "file": "src/utilities/time_date.js",
16239            "line": 56,
16240            "description": "<p>p5.js communicates with the clock on your computer. The minute() function\nreturns the current minute as a value from 0 - 59.</p>\n",
16241            "itemtype": "method",
16242            "name": "minute",
16243            "return": {
16244                "description": "the current minute",
16245                "type": "Integer"
16246            },
16247            "example": [
16248                "\n<div>\n<code>\nvar m = minute();\ntext('Current minute: \\n' + m, 5, 50);\n</code>\n</div>"
16249            ],
16250            "alt": "Current minute is displayed",
16251            "class": "p5",
16252            "module": "IO",
16253            "submodule": "Time & Date"
16254        },
16255        {
16256            "file": "src/utilities/time_date.js",
16257            "line": 78,
16258            "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",
16259            "itemtype": "method",
16260            "name": "millis",
16261            "return": {
16262                "description": "the number of milliseconds since starting the program",
16263                "type": "Number"
16264            },
16265            "example": [
16266                "\n<div>\n<code>\nvar millisecond = millis();\ntext('Milliseconds \\nrunning: \\n' + millisecond, 5, 40);\n</code>\n</div>"
16267            ],
16268            "alt": "number of milliseconds since program has started displayed",
16269            "class": "p5",
16270            "module": "IO",
16271            "submodule": "Time & Date"
16272        },
16273        {
16274            "file": "src/utilities/time_date.js",
16275            "line": 101,
16276            "description": "<p>p5.js communicates with the clock on your computer. The month() function\nreturns the current month as a value from 1 - 12.</p>\n",
16277            "itemtype": "method",
16278            "name": "month",
16279            "return": {
16280                "description": "the current month",
16281                "type": "Integer"
16282            },
16283            "example": [
16284                "\n<div>\n<code>\nvar m = month();\ntext('Current month: \\n' + m, 5, 50);\n</code>\n</div>"
16285            ],
16286            "alt": "Current month is displayed",
16287            "class": "p5",
16288            "module": "IO",
16289            "submodule": "Time & Date"
16290        },
16291        {
16292            "file": "src/utilities/time_date.js",
16293            "line": 123,
16294            "description": "<p>p5.js communicates with the clock on your computer. The second() function\nreturns the current second as a value from 0 - 59.</p>\n",
16295            "itemtype": "method",
16296            "name": "second",
16297            "return": {
16298                "description": "the current second",
16299                "type": "Integer"
16300            },
16301            "example": [
16302                "\n<div>\n<code>\nvar s = second();\ntext('Current second: \\n' + s, 5, 50);\n</code>\n</div>"
16303            ],
16304            "alt": "Current second is displayed",
16305            "class": "p5",
16306            "module": "IO",
16307            "submodule": "Time & Date"
16308        },
16309        {
16310            "file": "src/utilities/time_date.js",
16311            "line": 145,
16312            "description": "<p>p5.js communicates with the clock on your computer. The year() function\nreturns the current year as an integer (2014, 2015, 2016, etc).</p>\n",
16313            "itemtype": "method",
16314            "name": "year",
16315            "return": {
16316                "description": "the current year",
16317                "type": "Integer"
16318            },
16319            "example": [
16320                "\n<div>\n<code>\nvar y = year();\ntext('Current year: \\n' + y, 5, 50);\n</code>\n</div>"
16321            ],
16322            "alt": "Current year is displayed",
16323            "class": "p5",
16324            "module": "IO",
16325            "submodule": "Time & Date"
16326        },
16327        {
16328            "file": "src/webgl/camera.js",
16329            "line": 12,
16330            "description": "<p>Sets camera position for a 3D sketch. The function behaves similarly\ngluLookAt, except that it replaces the existing modelview matrix instead\nof applying any transformations calculated here on top of the existing\nmodel view.\nWhen called with no arguments, this function\nsets a default camera equivalent to calling\ncamera(0, 0, (height/2.0) / tan(PI*30.0 / 180.0), 0, 0, 0, 0, 1, 0);</p>\n",
16331            "itemtype": "method",
16332            "name": "camera",
16333            "params": [
16334                {
16335                    "name": "x",
16336                    "description": "<p>camera position value on x axis</p>\n",
16337                    "type": "Number",
16338                    "optional": true
16339                },
16340                {
16341                    "name": "y",
16342                    "description": "<p>camera position value on y axis</p>\n",
16343                    "type": "Number",
16344                    "optional": true
16345                },
16346                {
16347                    "name": "z",
16348                    "description": "<p>camera position value on z axis</p>\n",
16349                    "type": "Number",
16350                    "optional": true
16351                },
16352                {
16353                    "name": "centerX",
16354                    "description": "<p>x coordinate representing center of the sketch</p>\n",
16355                    "type": "Number",
16356                    "optional": true
16357                },
16358                {
16359                    "name": "centerY",
16360                    "description": "<p>y coordinate representing center of the sketch</p>\n",
16361                    "type": "Number",
16362                    "optional": true
16363                },
16364                {
16365                    "name": "centerZ",
16366                    "description": "<p>z coordinate representing center of the sketch</p>\n",
16367                    "type": "Number",
16368                    "optional": true
16369                },
16370                {
16371                    "name": "upX",
16372                    "description": "<p>x component of direction &#39;up&#39; from camera</p>\n",
16373                    "type": "Number",
16374                    "optional": true
16375                },
16376                {
16377                    "name": "upY",
16378                    "description": "<p>y component of direction &#39;up&#39; from camera</p>\n",
16379                    "type": "Number",
16380                    "optional": true
16381                },
16382                {
16383                    "name": "upZ",
16384                    "description": "<p>z component of direction &#39;up&#39; from camera</p>\n",
16385                    "type": "Number",
16386                    "optional": true
16387                }
16388            ],
16389            "chainable": 1,
16390            "example": [
16391                "\n<div>\n<code>\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n}\nfunction draw() {\n  //move the camera away from the plane by a sin wave\n  camera(0, 0, sin(frameCount * 0.01) * 100, 0, 0, 0, 0, 1, 0);\n  plane(120, 120);\n}\n</code>\n</div>"
16392            ],
16393            "alt": "blue square shrinks in size grows to fill canvas. disappears then loops.",
16394            "class": "p5",
16395            "module": "Lights, Camera",
16396            "submodule": "Camera"
16397        },
16398        {
16399            "file": "src/webgl/camera.js",
16400            "line": 161,
16401            "description": "<p>Sets perspective camera. When called with no arguments, the defaults\nprovided are equivalent to\nperspective(PI/3.0, width/height, cameraZ/10.0, cameraZ<em>10.0)\nwhere cameraZ is ((height/2.0) / tan(PI</em>60.0/360.0));</p>\n",
16402            "itemtype": "method",
16403            "name": "perspective",
16404            "params": [
16405                {
16406                    "name": "fovy",
16407                    "description": "<p>camera frustum vertical field of view,\n                          from bottom to top of view, in angleMode units</p>\n",
16408                    "type": "Number",
16409                    "optional": true
16410                },
16411                {
16412                    "name": "aspect",
16413                    "description": "<p>camera frustum aspect ratio</p>\n",
16414                    "type": "Number",
16415                    "optional": true
16416                },
16417                {
16418                    "name": "near",
16419                    "description": "<p>frustum near plane length</p>\n",
16420                    "type": "Number",
16421                    "optional": true
16422                },
16423                {
16424                    "name": "far",
16425                    "description": "<p>frustum far plane length</p>\n",
16426                    "type": "Number",
16427                    "optional": true
16428                }
16429            ],
16430            "chainable": 1,
16431            "example": [
16432                "\n<div>\n<code>
16432\n//drag mouse to toggle the world!\n//you will see there's a vanish point\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n  var fov = 60 / 180 * PI;\n  var cameraZ = height / 2.0 / tan(fov / 2.0);\n  perspective(60 / 180 * PI, width / height, cameraZ * 0.1, cameraZ * 10);\n}\nfunction draw() {\n  background(200);\n  orbitControl();\n  for (var i = -1; i < 2; i++) {\n    for (var j = -2; j < 3; j++) {\n      push();\n      translate(i * 160, 0, j * 160);\n      box(40, 40, 40);\n      pop();\n    }\n  }\n}\n</code>\n</div>"
16433            ],
16434            "alt": "colored 3d boxes toggleable with mouse position",
16435            "class": "p5",
16436            "module": "Lights, Camera",
16437            "submodule": "Camera"
16438        },
16439        {
16440            "file": "src/webgl/camera.js",
16441            "line": 243,
16442            "description": "<p>Setup ortho camera</p>\n",
16443            "itemtype": "method",
16444            "name": "ortho",
16445            "params": [
16446                {
16447                    "name": "left",
16448                    "description": "<p>camera frustum left plane</p>\n",
16449                    "type": "Number",
16450                    "optional": true
16451                },
16452                {
16453                    "name": "right",
16454                    "description": "<p>camera frustum right plane</p>\n",
16455                    "type": "Number",
16456                    "optional": true
16457                },
16458                {
16459                    "name": "bottom",
16460                    "description": "<p>camera frustum bottom plane</p>\n",
16461                    "type": "Number",
16462                    "optional": true
16463                },
16464                {
16465                    "name": "top",
16466                    "description": "<p>camera frustum top plane</p>\n",
16467                    "type": "Number",
16468                    "optional": true
16469                },
16470                {
16471                    "name": "near",
16472                    "description": "<p>camera frustum near plane</p>\n",
16473                    "type": "Number",
16474                    "optional": true
16475                },
16476                {
16477                    "name": "far",
16478                    "description": "<p>camera frustum far plane</p>\n",
16479                    "type": "Number",
16480                    "optional": true
16481                }
16482            ],
16483            "chainable": 1,
16484            "example": [
16485                "\n<div>\n<code>\n//drag mouse to toggle the world!\n//there's no vanish 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  strokeWeight(0.1);\n  for (var i = -1; i < 2;
16485 i++) {\n    for (var j = -2; j < 3; j++) {\n      push();\n      translate(i * 160, 0, j * 160);\n      box(40, 40, 40);\n      pop();\n    }\n  }\n}\n</code>\n</div>"
16486            ],
16487            "alt": "3 3d boxes, reveal several more boxes on 3d plane when mouse used to toggle",
16488            "class": "p5",
16489            "module": "Lights, Camera",
16490            "submodule": "Camera"
16491        },
16492        {
16493            "file": "src/webgl/interaction.js",
16494            "line": 5,
16495            "itemtype": "method",
16496            "name": "orbitControl",
16497            "chainable": 1,
16498            "example": [
16499                "\n<div>\n<code>\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n  background(50);\n  // Orbit control allows the camera to orbit around a target.\n  orbitControl();\n  box(30, 50);\n}\n</code>\n</div>"
16500            ],
16501            "alt": "Camera orbits around box when mouse is hold-clicked & then moved.",
16502            "class": "p5",
16503            "module": "Lights, Camera"
16504        },
16505        {
16506            "file": "src/webgl/light.js",
16507            "line": 12,
16508            "description": "<p>Creates an ambient light with a color</p>\n",
16509            "itemtype": "method",
16510            "name": "ambientLight",
16511            "chainable": 1,
16512            "example": [
16513                "\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>"
16514            ],
16515            "alt": "evenly distributed light across a sphere",
16516            "class": "p5",
16517            "module": "Lights, Camera",
16518            "submodule": "Lights",
16519            "overloads": [
16520                {
16521                    "line": 12,
16522                    "params": [
16523                        {
16524                            "name": "v1",
16525                            "description": "<p>red or hue value relative to\n                                the current color range</p>\n",
16526                            "type": "Number"
16527                        },
16528                        {
16529                            "name": "v2",
16530                            "description": "<p>green or saturation value\n                                relative to the current color range</p>\n",
16531                            "type": "Number"
16532                        },
16533                        {
16534                            "name": "v3",
16535                            "description": "<p>blue or brightness value\n                                relative to the current color range</p>\n",
16536                            "type": "Number"
16537                        },
16538                        {
16539                            "name": "alpha",
16540                            "description": "",
16541                            "type": "Number",
16542                            "optional": true
16543                        }
16544                    ],
16545                    "chainable": 1
16546                },
16547                {
16548                    "line": 46,
16549                    "params": [
16550                        {
16551                            "name": "value",
16552                            "description": "<p>a color string</p>\n",
16553                            "type": "String"
16554                        }
16555                    ],
16556                    "chainable": 1
16557                },
16558                {
16559                    "line": 52,
16560                    "params": [
16561                        {
16562                            "name": "gray",
16563                            "description": "<p>a gray value</p>\n",
16564                            "type": "Number"
16565                        },
16566                        {
16567                            "name": "alpha",
16568                            "description": "",
16569                            "type": "Number",
16570                            "optional": true
16571                        }
16572                    ],
16573                    "chainable": 1
16574                },
16575                {
16576                    "line": 59,
16577                    "params": [
16578                        {
16579                            "name": "values",
16580                            "description": "<p>an array containing the red,green,blue &amp;\n                                and alpha components of the color</p>\n",
16581                            "type": "Number[]"
16582                        }
16583                    ],
16584                    "chainable": 1
16585                },
16586                {
16587                    "line": 66,
16588                    "params": [
16589                        {
16590                            "name": "color",
16591                            "description": "<p>the ambient light color</p>\n",
16592                            "type": "p5.Color"
16593                        }
16594                    ],
16595                    "chainable": 1
16596                }
16597            ]
16598        },
16599        {
16600            "file": "src/webgl/light.js",
16601            "line": 101,
16602            "description": "<p>Creates a directional light with a color and a direction</p>\n",
16603            "itemtype": "method",
16604            "name": "directionalLight",
16605            "chainable": 1,
16606            "example": [
16607                "\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  var dirX = (mouseX / width - 0.5) * 2;\n  var 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>"
16608            ],
16609            "alt": "light source on canvas changeable with mouse position",
16610            "class": "p5",
16611            "module": "Lights, Camera",
16612            "submodule": "Lights",
16613            "overloads": [
16614                {
16615                    "line": 101,
16616                    "params": [
16617                        {
16618                            "name": "v1",
16619                            "description": "<p>red or hue value (depending on the current\ncolor mode),</p>\n",
16620                            "type": "Number"
16621                        },
16622                        {
16623                            "name": "v2",
16624                            "description": "<p>green or saturation value</p>\n",
16625                            "type": "Number"
16626                        },
16627                        {
16628                            "name": "v3",
16629                            "description": "<p>blue or brightness value</p>\n",
16630                            "type": "Number"
16631                        },
16632                        {
16633                            "name": "position",
16634                            "description": "<p>the direction of the light</p>\n",
16635                            "type": "p5.Vector"
16636                        }
16637                    ],
16638                    "chainable": 1
16639                },
16640                {
16641                    "line": 134,
16642                    "params": [
16643                        {
16644                            "name": "color",
16645                            "description": "<p>color Array, CSS color string,\n                                            or p5.Color value</p>\n",
16646                            "type": "Number[]|String|p5.Color"
16647                        },
16648                        {
16649                            "name": "x",
16650                            "description": "<p>x axis direction</p>\n",
16651                            "type": "Number"
16652                        },
16653                        {
16654                            "name": "y",
16655                            "description": "<p>y axis direction</p>\n",
16656                            "type": "Number"
16657                        },
16658                        {
16659                            "name": "z",
16660                            "description": "<p>z axis direction</p>\n",
16661                            "type": "Number"
16662                        }
16663                    ],
16664                    "chainable": 1
16665                },
16666                {
16667                    "line": 144,
16668                    "params": [
16669                        {
16670                            "name": "color",
16671                            "description": "",
16672                            "type": "Number[]|String|p5.Color"
16673                        },
16674                        {
16675                            "name": "position",
16676                            "description": "",
16677                            "type": "p5.Vector"
16678                        }
16679                    ],
16680                    "chainable": 1
16681                },
16682                {
16683                    "line": 151,
16684                    "params": [
16685                        {
16686                            "name": "v1",
16687                            "description": "",
16688                            "type": "Number"
16689                        },
16690                        {
16691                            "name": "v2",
16692                            "description": "",
16693                            "type": "Number"
16694                        },
16695                        {
16696                            "name": "v3",
16697                            "description": "",
16698                            "type": "Number"
16699                        },
16700                        {
16701                            "name": "x",
16702                            "description": "",
16703                            "type": "Number"
16704                        },
16705                        {
16706                            "name": "y",
16707                            "description": "",
16708                            "type": "Number"
16709                        },
16710                        {
16711                            "name": "z",
16712                            "description": "",
16713                            "type": "Number"
16714                        }
16715                    ],
16716                    "chainable": 1
16717                }
16718            ]
16719        },
16720        {
16721            "file": "src/webgl/light.js",
16722            "line": 207,
16723            "description": "<p>Creates a point light with a color and a light position</p>\n",
16724            "itemtype": "method",
16725            "name": "pointLight",
16726            "chainable": 1,
16727            "example": [
16728                "\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  var locX = mouseX - width / 2;
16728\n  var 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>"
16729            ],
16730            "alt": "spot light on canvas changes position with mouse",
16731            "class": "p5",
16732            "module": "Lights, Camera",
16733            "submodule": "Lights",
16734            "overloads": [
16735                {
16736                    "line": 207,
16737                    "params": [
16738                        {
16739                            "name": "v1",
16740                            "description": "<p>red or hue value (depending on the current\ncolor mode),</p>\n",
16741                            "type": "Number"
16742                        },
16743                        {
16744                            "name": "v2",
16745                            "description": "<p>green or saturation value</p>\n",
16746                            "type": "Number"
16747                        },
16748                        {
16749                            "name": "v3",
16750                            "description": "<p>blue or brightness value</p>\n",
16751                            "type": "Number"
16752                        },
16753                        {
16754                            "name": "x",
16755                            "description": "<p>x axis position</p>\n",
16756                            "type": "Number"
16757                        },
16758                        {
16759                            "name": "y",
16760                            "description": "<p>y axis position</p>\n",
16761                            "type": "Number"
16762                        },
16763                        {
16764                            "name": "z",
16765                            "description": "<p>z axis position</p>\n",
16766                            "type": "Number"
16767                        }
16768                    ],
16769                    "chainable": 1
16770                },
16771                {
16772                    "line": 249,
16773                    "params": [
16774                        {
16775                            "name": "v1",
16776                            "description": "",
16777                            "type": "Number"
16778                        },
16779                        {
16780                            "name": "v2",
16781                            "description": "",
16782                            "type": "Number"
16783                        },
16784                        {
16785                            "name": "v3",
16786                            "description": "",
16787                            "type": "Number"
16788                        },
16789                        {
16790                            "name": "position",
16791                            "description": "<p>the position of the light</p>\n",
16792                            "type": "p5.Vector"
16793                        }
16794                    ],
16795                    "chainable": 1
16796                },
16797                {
16798                    "line": 258,
16799                    "params": [
16800                        {
16801                            "name": "color",
16802                            "description": "<p>color Array, CSS color string,\nor p5.Color value</p>\n",
16803                            "type": "Number[]|String|p5.Color"
16804                        },
16805                        {
16806                            "name": "x",
16807                            "description": "",
16808                            "type": "Number"
16809                        },
16810                        {
16811                            "name": "y",
16812                            "description": "",
16813                            "type": "Number"
16814                        },
16815                        {
16816                            "name": "z",
16817                            "description": "",
16818                            "type": "Number"
16819                        }
16820                    ],
16821                    "chainable": 1
16822                },
16823                {
16824                    "line": 268,
16825                    "params": [
16826                        {
16827                            "name": "color",
16828                            "description": "",
16829                            "type": "Number[]|String|p5.Color"
16830                        },
16831                        {
16832                            "name": "position",
16833                            "description": "",
16834                            "type": "p5.Vector"
16835                        }
16836                    ],
16837                    "chainable": 1
16838                }
16839            ]
16840        },
16841        {
16842            "file": "src/webgl/loading.js",
16843            "line": 14,
16844            "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\nloadModel() 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 scale() function.</p>\n",
16845            "itemtype": "method",
16846            "name": "loadModel",
16847            "return": {
16848                "description": "the p5.Geometry object",
16849                "type": "p5.Geometry"
16850            },
16851            "example": [
16852                "\n<div>\n<code>
16852\n//draw a spinning teapot\nvar teapot;\n\nfunction preload() {\n  teapot = loadModel('assets/teapot.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(teapot);\n}\n</code>\n</div>"
16853            ],
16854            "alt": "Vertically rotating 3-d teapot with red, green and blue gradient.",
16855            "class": "p5",
16856            "module": "Shape",
16857            "submodule": "3D Models",
16858            "overloads": [
16859                {
16860                    "line": 14,
16861                    "params": [
16862                        {
16863                            "name": "path",
16864                            "description": "<p>Path of the model to be loaded</p>\n",
16865                            "type": "String"
16866                        },
16867                        {
16868                            "name": "normalize",
16869                            "description": "<p>If true, scale the model to a\n                                     standardized size when loading</p>\n",
16870                            "type": "Boolean"
16871                        },
16872                        {
16873                            "name": "successCallback",
16874                            "description": "<p>Function to be called\n                                    once the model is loaded. Will be passed\n                                    the 3D model object.</p>\n",
16875                            "type": "function(p5.Geometry)",
16876                            "optional": true
16877                        },
16878                        {
16879                            "name": "failureCallback",
16880                            "description": "<p>called with event error if\n                                        the image fails to load.</p>\n",
16881                            "type": "Function(Event)",
16882                            "optional": true
16883                        }
16884                    ],
16885                    "return": {
16886                        "description": "the p5.Geometry object",
16887                        "type": "p5.Geometry"
16888                    }
16889                },
16890                {
16891                    "line": 61,
16892                    "params": [
16893                        {
16894                            "name": "path",
16895                            "description": "",
16896                            "type": "String"
16897                        },
16898                        {
16899                            "name": "successCallback",
16900                            "description": "",
16901                            "type": "function(p5.Geometry)",
16902                            "optional": true
16903                        },
16904                        {
16905                            "name": "failureCallback",
16906                            "description": "",
16907                            "type": "Function(Event)",
16908                            "optional": true
16909                        }
16910                    ],
16911                    "return": {
16912                        "description": "the p5.Geometry object",
16913                        "type": "p5.Geometry"
16914                    }
16915                }
16916            ]
16917        },
16918        {
16919            "file": "src/webgl/loading.js",
16920            "line": 106,
16921            "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",
16922            "class": "p5",
16923            "module": "Shape",
16924            "submodule": "3D Models"
16925        },
16926        {
16927            "file": "src/webgl/loading.js",
16928            "line": 215,
16929            "description": "<p>Render a 3d model to the screen.</p>\n",
16930            "itemtype": "method",
16931            "name": "model",
16932            "params": [
16933                {
16934                    "name": "model",
16935                    "description": "<p>Loaded 3d model to be rendered</p>\n",
16936                    "type": "p5.Geometry"
16937                }
16938            ],
16939            "example": [
16940                "\n<div>\n<code>\n//draw a spinning teapot\nvar teapot;\n\nfunction preload() {\n  teapot = loadModel('assets/teapot.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);
16940\n  model(teapot);\n}\n</code>\n</div>"
16941            ],
16942            "alt": "Vertically rotating 3-d teapot with red, green and blue gradient.",
16943            "class": "p5",
16944            "module": "Shape",
16945            "submodule": "3D Models"
16946        },
16947        {
16948            "file": "src/webgl/material.js",
16949            "line": 14,
16950            "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 preload().</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",
16951            "itemtype": "method",
16952            "name": "loadShader",
16953            "params": [
16954                {
16955                    "name": "vertFilename",
16956                    "description": "<p>path to file containing vertex shader\nsource code</p>\n",
16957                    "type": "String",
16958                    "optional": true
16959                },
16960                {
16961                    "name": "fragFilename",
16962                    "description": "<p>path to file containing fragment shader\nsource code</p>\n",
16963                    "type": "String",
16964                    "optional": true
16965                }
16966            ],
16967            "return": {
16968                "description": "a shader object created from the provided\nvertex and fragment shader files.",
16969                "type": "p5.Shader"
16970            },
16971            "class": "p5",
16972            "module": "Lights, Camera",
16973            "submodule": "Material"
16974        },
16975        {
16976            "file": "src/webgl/material.js",
16977            "line": 57,
16978            "itemtype": "method",
16979            "name": "createShader",
16980            "params": [
16981                {
16982                    "name": "vertSrc",
16983                    "description": "<p>source code for the vertex shader</p>\n",
16984                    "type": "String"
16985                },
16986                {
16987                    "name": "fragSrc",
16988                    "description": "<p>source code for the fragment shader</p>\n",
16989                    "type": "String"
16990                }
16991            ],
16992            "return": {
16993                "description": "a shader object created from the provided\nvertex and fragment shaders.",
16994                "type": "p5.Shader"
16995            },
16996            "example": [
16997                "\n<div modernizr='webgl'>\n<code>\n// the 'varying's are shared between both vertex & fragment shaders\nvar varying = 'precision highp float; varying vec2 vPos;';\n\n// the vertex shader is called for each vertex\nvar 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\nvar 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  '  }' +\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\nvar 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>"
16998            ],
16999            "alt": "zooming Mandelbrot set. a colorful, infinitely detailed fractal.",
17000            "class": "p5",
17001            "module": "Lights, Camera",
17002            "submodule": "Material"
17003        },
17004        {
17005            "file": "src/webgl/material.js",
17006            "line": 125,
17007            "description": "<p>The shader() 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\nloadShader().</p>\n",
17008            "itemtype": "method",
17009            "name": "shader",
17010            "chainable": 1,
17011            "params": [
17012                {
17013                    "name": "s",
17014                    "description": "<p>the desired p5.Shader to use for rendering\nshapes.</p>\n",
17015                    "type": "p5.Shader",
17016                    "optional": true
17017                }
17018            ],
17019            "class": "p5",
17020            "module": "Lights, Camera",
17021            "submodule": "Material"
17022        },
17023        {
17024            "file": "src/webgl/material.js",
17025            "line": 150,
17026            "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",
17027            "itemtype": "method",
17028            "name": "normalMaterial",
17029            "chainable": 1,
17030            "example": [
17031                "\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>"
17032            ],
17033            "alt": "Red, green and blue gradient.",
17034            "class": "p5",
17035            "module": "Lights, Camera",
17036            "submodule": "Material"
17037        },
17038        {
17039            "file": "src/webgl/material.js",
17040            "line": 185,
17041            "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",
17042            "itemtype": "method",
17043            "name": "texture",
17044            "params": [
17045                {
17046                    "name": "tex",
17047                    "description": "<p>2-dimensional graphics\n                   to render as texture</p>\n",
17048                    "type": "p5.Image|p5.MediaElement|p5.Graphics"
17049                }
17050            ],
17051            "chainable": 1,
17052            "example": [
17053                "\n<div>\n<code>\nvar 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>\nvar 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>\nvar 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>"
17054            ],
17055            "alt": "Rotating view of many images umbrella and grid roof on a 3d plane\nblack canvas\nblack canvas",
17056            "class": "p5",
17057            "module": "Lights, Camera",
17058            "submodule": "Material"
17059        },
17060        {
17061            "file": "src/webgl/material.js",
17062            "line": 275,
17063            "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",
17064            "itemtype": "method",
17065            "name": "ambientMaterial",
17066            "chainable": 1,
17067            "example": [
17068                "\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>"
17069            ],
17070            "alt": "radiating light source from top right of canvas",
17071            "class": "p5",
17072            "module": "Lights, Camera",
17073            "submodule": "Material",
17074            "overloads": [
17075                {
17076                    "line": 275,
17077                    "params": [
17078                        {
17079                            "name": "v1",
17080                            "description": "<p>gray value, red or hue value\n                        (depending on the current color mode),</p>\n",
17081                            "type": "Number"
17082                        },
17083                        {
17084                            "name": "v2",
17085                            "description": "<p>green or saturation value</p>\n",
17086                            "type": "Number",
17087                            "optional": true
17088                        },
17089                        {
17090                            "name": "v3",
17091                            "description": "<p>blue or brightness value</p>\n",
17092                            "type": "Number",
17093                            "optional": true
17094                        },
17095                        {
17096                            "name": "a",
17097                            "description": "<p>opacity</p>\n",
17098                            "type": "Number",
17099                            "optional": true
17100                        }
17101                    ],
17102                    "chainable": 1
17103                },
17104                {
17105                    "line": 306,
17106                    "params": [
17107                        {
17108                            "name": "color",
17109                            "description": "<p>color, color Array, or CSS color string</p>\n",
17110                            "type": "Number[]|String|p5.Color"
17111                        }
17112                    ],
17113                    "chainable": 1
17114                }
17115            ]
17116        },
17117        {
17118            "file": "src/webgl/material.js",
17119            "line": 324,
17120            "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",
17121            "itemtype": "method",
17122            "name": "specularMaterial",
17123            "chainable": 1,
17124            "example": [
17125                "\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>"
17126            ],
17127            "alt": "diffused radiating light source from top right of canvas",
17128            "class": "p5",
17129            "module": "Lights, Camera",
17130            "submodule": "Material",
17131            "overloads": [
17132                {
17133                    "line": 324,
17134                    "params": [
17135                        {
17136                            "name": "v1",
17137                            "description": "<p>gray value, red or hue value\n                      (depending on the current color mode),</p>\n",
17138                            "type": "Number"
17139                        },
17140                        {
17141                            "name": "v2",
17142                            "description": "<p>green or saturation value</p>\n",
17143                            "type": "Number",
17144                            "optional": true
17145                        },
17146                        {
17147                            "name": "v3",
17148                            "description": "<p>blue or brightness value</p>\n",
17149                            "type": "Number",
17150                            "optional": true
17151                        },
17152                        {
17153                            "name": "a",
17154                            "description": "<p>opacity</p>\n",
17155                            "type": "Number",
17156                            "optional": true
17157                        }
17158                    ],
17159                    "chainable": 1
17160                },
17161                {
17162                    "line": 355,
17163                    "params": [
17164                        {
17165                            "name": "color",
17166                            "description": "<p>color Array, or CSS color string</p>\n",
17167                            "type": "Number[]|String|p5.Color"
17168                        }
17169                    ],
17170                    "chainable": 1
17171                }
17172            ]
17173        },
17174        {
17175            "file": "src/webgl/p5.Geometry.js",
17176            "line": 52,
17177            "itemtype": "method",
17178            "name": "computeFaces",
17179            "chainable": 1,
17180            "class": "p5.Geometry",
17181            "module": "Lights, Camera"
17182        },
17183        {
17184            "file": "src/webgl/p5.Geometry.js",
17185            "line": 94,
17186            "description": "<p>computes smooth normals per vertex as an average of each\nface.</p>\n",
17187            "itemtype": "method",
17188            "name": "computeNormals",
17189            "chainable": 1,
17190            "class": "p5.Geometry",
17191            "module": "Lights, Camera"
17192        },
17193        {
17194            "file": "src/webgl/p5.Geometry.js",
17195            "line": 133,
17196            "description": "<p>Averages the vertex normals. Used in curved\nsurfaces</p>\n",
17197            "itemtype": "method",
17198            "name": "averageNormals",
17199            "chainable": 1,
17200            "class": "p5.Geometry",
17201            "module": "Lights, Camera"
17202        },
17203        {
17204            "file": "src/webgl/p5.Geometry.js",
17205            "line": 154,
17206            "description": "<p>Averages pole normals.  Used in spherical primitives</p>\n",
17207            "itemtype": "method",
17208            "name": "averagePoleNormals",
17209            "chainable": 1,
17210            "class": "p5.Geometry",
17211            "module": "Lights, Camera"
17212        },
17213        {
17214            "file": "src/webgl/p5.Geometry.js",
17215            "line": 247,
17216            "description": "<p>Modifies all vertices to be centered within the range -100 to 100.</p>\n",
17217            "itemtype": "method",
17218            "name": "normalize",
17219            "chainable": 1,
17220            "class": "p5.Geometry",
17221            "module": "Lights, Camera"
17222        },
17223        {
17224            "file": "src/webgl/p5.RendererGL.js",
17225            "line": 197,
17226            "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>
17226\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",
17227            "itemtype": "method",
17228            "name": "setAttributes",
17229            "example": [
17230                "\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, 30, 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>"
17231            ],
17232            "alt": "a rotating cube with smoother edges",
17233            "class": "p5",
17234            "module": "Rendering",
17235            "submodule": "Rendering",
17236            "overloads": [
17237                {
17238                    "line": 197,
17239                    "params": [
17240                        {
17241                            "name": "key",
17242                            "description": "<p>Name of attribute</p>\n",
17243                            "type": "String"
17244                        },
17245                        {
17246                            "name": "value",
17247                            "description": "<p>New value of named attribute</p>\n",
17248                            "type": "Boolean"
17249                        }
17250                    ]
17251                },
17252                {
17253                    "line": 330,
17254                    "params": [
17255                        {
17256                            "name": "obj",
17257                            "description": "<p>object with key-value pairs</p>\n",
17258                            "type": "Object"
17259                        }
17260                    ]
17261                }
17262            ]
17263        },
17264        {
17265            "file": "src/webgl/p5.Shader.js",
17266            "line": 270,
17267            "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",
17268            "itemtype": "method",
17269            "name": "setUniform",
17270            "chainable": 1,
17271            "params": [
17272                {
17273                    "name": "uniformName",
17274                    "description": "<p>the name of the uniform in the\nshader program</p>\n",
17275                    "type": "String"
17276                },
17277                {
17278                    "name": "data",
17279                    "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",
17280                    "type": "Object|Number|Boolean|Number[]"
17281                }
17282            ],
17283            "class": "p5.Shader",
17284            "module": "Lights, Camera",
17285            "submodule": "Shaders"
17286        },
17287        {
17288            "file": "src/webgl/primitives.js",
17289            "line": 14,
17290            "description": "<p>Draw a plane with given a width and height</p>\n",
17291            "itemtype": "method",
17292            "name": "plane",
17293            "params": [
17294                {
17295                    "name": "width",
17296                    "description": "<p>width of the plane</p>\n",
17297                    "type": "Number",
17298                    "optional": true
17299                },
17300                {
17301                    "name": "height",
17302                    "description": "<p>height of the plane</p>\n",
17303                    "type": "Number",
17304                    "optional": true
17305                },
17306                {
17307                    "name": "detailX",
17308                    "description": "<p>Optional number of triangle\n                            subdivisions in x-dimension</p>\n",
17309                    "type": "Integer",
17310                    "optional": true
17311                },
17312                {
17313                    "name": "detailY",
17314                    "description": "<p>Optional number of triangle\n                            subdivisions in y-dimension</p>\n",
17315                    "type": "Integer",
17316                    "optional": true
17317                }
17318            ],
17319            "chainable": 1,
17320            "example": [
17321                "\n<div>\n<code>
17321\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>"
17322            ],
17323            "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.",
17324            "class": "p5",
17325            "module": "Shape",
17326            "submodule": "3D Primitives"
17327        },
17328        {
17329            "file": "src/webgl/primitives.js",
17330            "line": 96,
17331            "description": "<p>Draw a box with given width, height and depth</p>\n",
17332            "itemtype": "method",
17333            "name": "box",
17334            "params": [
17335                {
17336                    "name": "width",
17337                    "description": "<p>width of the box</p>\n",
17338                    "type": "Number",
17339                    "optional": true
17340                },
17341                {
17342                    "name": "Height",
17343                    "description": "<p>height of the box</p>\n",
17344                    "type": "Number",
17345                    "optional": true
17346                },
17347                {
17348                    "name": "depth",
17349                    "description": "<p>depth of the box</p>\n",
17350                    "type": "Number",
17351                    "optional": true
17352                },
17353                {
17354                    "name": "detailX",
17355                    "description": "<p>Optional number of triangle\n                           subdivisions in x-dimension</p>\n",
17356                    "type": "Integer",
17357                    "optional": true
17358                },
17359                {
17360                    "name": "detailY",
17361                    "description": "<p>Optional number of triangle\n                           subdivisions in y-dimension</p>\n",
17362                    "type": "Integer",
17363                    "optional": true
17364                }
17365            ],
17366            "chainable": 1,
17367            "example": [
17368                "\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>"
17369            ],
17370            "class": "p5",
17371            "module": "Shape",
17372            "submodule": "3D Primitives"
17373        },
17374        {
17375            "file": "src/webgl/primitives.js",
17376            "line": 213,
17377            "description": "<p>Draw a sphere with given radius</p>\n",
17378            "itemtype": "method",
17379            "name": "sphere",
17380            "params": [
17381                {
17382                    "name": "radius",
17383                    "description": "<p>radius of circle</p>\n",
17384                    "type": "Number",
17385                    "optional": true
17386                },
17387                {
17388                    "name": "detailX",
17389                    "description": "<p>number of segments,\n                                   the more segments the smoother geometry\n                                   default is 24</p>\n",
17390                    "type": "Integer",
17391                    "optional": true
17392                },
17393                {
17394                    "name": "detailY",
17395                    "description": "<p>number of segments,\n                                   the more segments the smoother geometry\n                                   default is 16</p>\n",
17396                    "type": "Integer",
17397                    "optional": true
17398                }
17399            ],
17400            "chainable": 1,
17401            "example": [
17402                "\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>"
17403            ],
17404            "class": "p5",
17405            "module": "Shape",
17406            "submodule": "3D Primitives"
17407        },
17408        {
17409            "file": "src/webgl/primitives.js",
17410            "line": 391,
17411            "description": "<p>Draw a cylinder with given radius and height</p>\n",
17412            "itemtype": "method",
17413            "name": "cylinder",
17414            "params": [
17415                {
17416                    "name": "radius",
17417                    "description": "<p>radius of the surface</p>\n",
17418                    "type": "Number",
17419                    "optional": true
17420                },
17421                {
17422                    "name": "height",
17423                    "description": "<p>height of the cylinder</p>\n",
17424                    "type": "Number",
17425                    "optional": true
17426                },
17427                {
17428                    "name": "detailX",
17429                    "description": "<p>number of segments,\n                              the more segments the smoother geometry\n                              default is 24</p>\n",
17430                    "type": "Integer",
17431                    "optional": true
17432                },
17433                {
17434                    "name": "detailY",
17435                    "description": "<p>number of segments in y-dimension,\n                              the more segments the smoother geometry\n                              default is 1</p>\n",
17436                    "type": "Integer",
17437                    "optional": true
17438                },
17439                {
17440                    "name": "bottomCap",
17441                    "description": "<p>whether to draw the bottom of the cylinder</p>\n",
17442                    "type": "Boolean",
17443                    "optional": true
17444                },
17445                {
17446                    "name": "topCap",
17447                    "description": "<p>whether to draw the top of the cylinder</p>\n",
17448                    "type": "Boolean",
17449                    "optional": true
17450                }
17451            ],
17452            "chainable": 1,
17453            "example": [
17454                "\n<div>\n<code>
17454\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>"
17455            ],
17456            "class": "p5",
17457            "module": "Shape",
17458            "submodule": "3D Primitives"
17459        },
17460        {
17461            "file": "src/webgl/primitives.js",
17462            "line": 482,
17463            "description": "<p>Draw a cone with given radius and height</p>\n",
17464            "itemtype": "method",
17465            "name": "cone",
17466            "params": [
17467                {
17468                    "name": "radius",
17469                    "description": "<p>radius of the bottom surface</p>\n",
17470                    "type": "Number",
17471                    "optional": true
17472                },
17473                {
17474                    "name": "height",
17475                    "description": "<p>height of the cone</p>\n",
17476                    "type": "Number",
17477                    "optional": true
17478                },
17479                {
17480                    "name": "detailX",
17481                    "description": "<p>number of segments,\n                            the more segments the smoother geometry\n                            default is 24</p>\n",
17482                    "type": "Integer",
17483                    "optional": true
17484                },
17485                {
17486                    "name": "detailY",
17487                    "description": "<p>number of segments,\n                            the more segments the smoother geometry\n                            default is 1</p>\n",
17488                    "type": "Integer",
17489                    "optional": true
17490                },
17491                {
17492                    "name": "cap",
17493                    "description": "<p>whether to draw the base of the cone</p>\n",
17494                    "type": "Boolean",
17495                    "optional": true
17496                }
17497            ],
17498            "chainable": 1,
17499            "example": [
17500                "\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>"
17501            ],
17502            "class": "p5",
17503            "module": "Shape",
17504            "submodule": "3D Primitives"
17505        },
17506        {
17507            "file": "src/webgl/primitives.js",
17508            "line": 553,
17509            "description": "<p>Draw an ellipsoid with given radius</p>\n",
17510            "itemtype": "method",
17511            "name": "ellipsoid",
17512            "params": [
17513                {
17514                    "name": "radiusx",
17515                    "description": "<p>xradius of circle</p>\n",
17516                    "type": "Number",
17517                    "optional": true
17518                },
17519                {
17520                    "name": "radiusy",
17521                    "description": "<p>yradius of circle</p>\n",
17522                    "type": "Number",
17523                    "optional": true
17524                },
17525                {
17526                    "name": "radiusz",
17527                    "description": "<p>zradius of circle</p>\n",
17528                    "type": "Number",
17529                    "optional": true
17530                },
17531                {
17532                    "name": "detailX",
17533                    "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",
17534                    "type": "Integer",
17535                    "optional": true
17536                },
17537                {
17538                    "name": "detailY",
17539                    "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",
17540                    "type": "Integer",
17541                    "optional": true
17542                }
17543            ],
17544            "chainable": 1,
17545            "example": [
17546                "\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>"
17547            ],
17548            "class": "p5",
17549            "module": "Shape",
17550            "submodule": "3D Primitives"
17551        },
17552        {
17553            "file": "src/webgl/primitives.js",
17554            "line": 643,
17555            "description": "<p>Draw a torus with given radius and tube radius</p>\n",
17556            "itemtype": "method",
17557            "name": "torus",
17558            "params": [
17559                {
17560                    "name": "radius",
17561                    "description": "<p>radius of the whole ring</p>\n",
17562                    "type": "Number",
17563                    "optional": true
17564                },
17565                {
17566                    "name": "tubeRadius",
17567                    "description": "<p>radius of the tube</p>\n",
17568                    "type": "Number",
17569                    "optional": true
17570                },
17571                {
17572                    "name": "detailX",
17573                    "description": "<p>number of segments in x-dimension,\n                               the more segments the smoother geometry\n                               default is 24</p>\n",
17574                    "type": "Integer",
17575                    "optional": true
17576                },
17577                {
17578                    "name": "detailY",
17579                    "description": "<p>number of segments in y-dimension,\n                               the more segments the smoother geometry\n                               default is 16</p>\n",
17580                    "type": "Integer",
17581                    "optional": true
17582                }
17583            ],
17584            "chainable": 1,
17585            "example": [
17586                "\n<div>\n<code>
17586\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>"
17587            ],
17588            "class": "p5",
17589            "module": "Shape",
17590            "submodule": "3D Primitives"
17591        },
17592        {
17593            "file": "lib/addons/p5.dom.js",
17594            "line": 40,
17595            "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 p5.Element. 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",
17596            "itemtype": "method",
17597            "name": "select",
17598            "params": [
17599                {
17600                    "name": "name",
17601                    "description": "<p>id, class, or tag name of element to search for</p>\n",
17602                    "type": "String"
17603                },
17604                {
17605                    "name": "container",
17606                    "description": "<p>id, p5.Element, or\n                                            HTML element to search within</p>\n",
17607                    "type": "String|p5.Element|HTMLElement",
17608                    "optional": true
17609                }
17610            ],
17611            "return": {
17612                "description": "p5.Element containing node found",
17613                "type": "Object|p5.Element|null"
17614            },
17615            "example": [
17616                "\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"
17617            ],
17618            "class": "p5.dom",
17619            "module": "p5.dom",
17620            "submodule": "p5.dom"
17621        },
17622        {
17623            "file": "lib/addons/p5.dom.js",
17624            "line": 107,
17625            "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 p5.Elements\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",
17626            "itemtype": "method",
17627            "name": "selectAll",
17628            "params": [
17629                {
17630                    "name": "name",
17631                    "description": "<p>class or tag name of elements to search for</p>\n",
17632                    "type": "String"
17633                },
17634                {
17635                    "name": "container",
17636                    "description": "<p>id, p5.Element, or HTML element to search within</p>\n",
17637                    "type": "String",
17638                    "optional": true
17639                }
17640            ],
17641            "return": {
17642                "description": "Array of p5.Elements containing nodes found",
17643                "type": "Array"
17644            },
17645            "example": [
17646                "\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; 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"
17647            ],
17648            "class": "p5.dom",
17649            "module": "p5.dom",
17650            "submodule": "p5.dom"
17651        },
17652        {
17653            "file": "lib/addons/p5.dom.js",
17654            "line": 168,
17655            "description": "<p>Helper function for select and selectAll</p>\n",
17656            "class": "p5.dom",
17657            "module": "p5.dom",
17658            "submodule": "p5.dom"
17659        },
17660        {
17661            "file": "lib/addons/p5.dom.js",
17662            "line": 184,
17663            "description": "<p>Helper function for getElement and getElements.</p>\n",
17664            "class": "p5.dom",
17665            "module": "p5.dom",
17666            "submodule": "p5.dom"
17667        },
17668        {
17669            "file": "lib/addons/p5.dom.js",
17670            "line": 218,
17671            "description": "<p>Removes all elements created by p5, except any canvas / graphics\nelements created by createCanvas or createGraphics.\nEvent handlers are removed, and element is removed from the DOM.</p>\n",
17672            "itemtype": "method",
17673            "name": "removeElements",
17674            "example": [
17675                "\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"
17676            ],
17677            "class": "p5.dom",
17678            "module": "p5.dom",
17679            "submodule": "p5.dom"
17680        },
17681        {
17682            "file": "lib/addons/p5.dom.js",
17683            "line": 245,
17684            "description": "<p>Helpers for create methods.</p>\n",
17685            "class": "p5.dom",
17686            "module": "p5.dom",
17687            "submodule": "p5.dom"
17688        },
17689        {
17690            "file": "lib/addons/p5.dom.js",
17691            "line": 256,
17692            "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",
17693            "itemtype": "method",
17694            "name": "createDiv",
17695            "params": [
17696                {
17697                    "name": "html",
17698                    "description": "<p>inner HTML for element created</p>\n",
17699                    "type": "String",
17700                    "optional": true
17701                }
17702            ],
17703            "return": {
17704                "description": "pointer to p5.Element holding created node",
17705                "type": "Object|p5.Element"
17706            },
17707            "example": [
17708                "\n<div class='norender'><code>\ncreateDiv('this is some text');\n</code></div>"
17709            ],
17710            "class": "p5.dom",
17711            "module": "p5.dom",
17712            "submodule": "p5.dom"
17713        },
17714        {
17715            "file": "lib/addons/p5.dom.js",
17716            "line": 270,
17717            "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",
17718            "itemtype": "method",
17719            "name": "createP",
17720            "params": [
17721                {
17722                    "name": "html",
17723                    "description": "<p>inner HTML for element created</p>\n",
17724                    "type": "String",
17725                    "optional": true
17726                }
17727            ],
17728            "return": {
17729                "description": "pointer to p5.Element holding created node",
17730                "type": "Object|p5.Element"
17731            },
17732            "example": [
17733                "\n<div class='norender'><code>\ncreateP('this is some text');\n</code></div>"
17734            ],
17735            "class": "p5.dom",
17736            "module": "p5.dom",
17737            "submodule": "p5.dom"
17738        },
17739        {
17740            "file": "lib/addons/p5.dom.js",
17741            "line": 285,
17742            "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",
17743            "itemtype": "method",
17744            "name": "createSpan",
17745            "params": [
17746                {
17747                    "name": "html",
17748                    "description": "<p>inner HTML for element created</p>\n",
17749                    "type": "String",
17750                    "optional": true
17751                }
17752            ],
17753            "return": {
17754                "description": "pointer to p5.Element holding created node",
17755                "type": "Object|p5.Element"
17756            },
17757            "example": [
17758                "\n<div class='norender'><code>\ncreateSpan('this is some text');\n</code></div>"
17759            ],
17760            "class": "p5.dom",
17761            "module": "p5.dom",
17762            "submodule": "p5.dom"
17763        },
17764        {
17765            "file": "lib/addons/p5.dom.js",
17766            "line": 308,
17767            "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",
17768            "itemtype": "method",
17769            "name": "createImg",
17770            "params": [
17771                {
17772                    "name": "src",
17773                    "description": "<p>src path or url for image</p>\n",
17774                    "type": "String"
17775                },
17776                {
17777                    "name": "alt",
17778                    "description": "<p>alternate text to be used if image does not load</p>\n",
17779                    "type": "String",
17780                    "optional": true
17781                },
17782                {
17783                    "name": "successCallback",
17784                    "description": "<p>callback to be called once image data is loaded</p>\n",
17785                    "type": "Function",
17786                    "optional": true
17787                }
17788            ],
17789            "return": {
17790                "description": "pointer to p5.Element holding created node",
17791                "type": "Object|p5.Element"
17792            },
17793            "example": [
17794                "\n<div class='norender'><code>\ncreateImg('http://p5js.org/img/asterisk-01.png');\n</code></div>"
17795            ],
17796            "class": "p5.dom",
17797            "module": "p5.dom",
17798            "submodule": "p5.dom"
17799        },
17800        {
17801            "file": "lib/addons/p5.dom.js",
17802            "line": 351,
17803            "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",
17804            "itemtype": "method",
17805            "name": "createA",
17806            "params": [
17807                {
17808                    "name": "href",
17809                    "description": "<p>url of page to link to</p>\n",
17810                    "type": "String"
17811                },
17812                {
17813                    "name": "html",
17814                    "description": "<p>inner html of link element to display</p>\n",
17815                    "type": "String"
17816                },
17817                {
17818                    "name": "target",
17819                    "description": "<p>target where new link should open,\n                            could be _blank, _self, _parent, _top.</p>\n",
17820                    "type": "String",
17821                    "optional": true
17822                }
17823            ],
17824            "return": {
17825                "description": "pointer to p5.Element holding created node",
17826                "type": "Object|p5.Element"
17827            },
17828            "example": [
17829                "\n<div class='norender'><code>\ncreateA('http://p5js.org/', 'this is a link');\n</code></div>"
17830            ],
17831            "class": "p5.dom",
17832            "module": "p5.dom",
17833            "submodule": "p5.dom"
17834        },
17835        {
17836            "file": "lib/addons/p5.dom.js",
17837            "line": 376,
17838            "class": "p5.dom",
17839            "module": "p5.dom",
17840            "submodule": "p5.dom"
17841        },
17842        {
17843            "file": "lib/addons/p5.dom.js",
17844            "line": 378,
17845            "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",
17846            "itemtype": "method",
17847            "name": "createSlider",
17848            "params": [
17849                {
17850                    "name": "min",
17851                    "description": "<p>minimum value of the slider</p>\n",
17852                    "type": "Number"
17853                },
17854                {
17855                    "name": "max",
17856                    "description": "<p>maximum value of the slider</p>\n",
17857                    "type": "Number"
17858                },
17859                {
17860                    "name": "value",
17861                    "description": "<p>default value of the slider</p>\n",
17862                    "type": "Number",
17863                    "optional": true
17864                },
17865                {
17866                    "name": "step",
17867                    "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",
17868                    "type": "Number",
17869                    "optional": true
17870                }
17871            ],
17872            "return": {
17873                "description": "pointer to p5.Element holding created node",
17874                "type": "Object|p5.Element"
17875            },
17876            "example": [
17877                "\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();
17877\n  background(val, 100, 100, 1);\n}\n</code></div>"
17878            ],
17879            "class": "p5.dom",
17880            "module": "p5.dom",
17881            "submodule": "p5.dom"
17882        },
17883        {
17884            "file": "lib/addons/p5.dom.js",
17885            "line": 435,
17886            "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",
17887            "itemtype": "method",
17888            "name": "createButton",
17889            "params": [
17890                {
17891                    "name": "label",
17892                    "description": "<p>label displayed on the button</p>\n",
17893                    "type": "String"
17894                },
17895                {
17896                    "name": "value",
17897                    "description": "<p>value of the button</p>\n",
17898                    "type": "String",
17899                    "optional": true
17900                }
17901            ],
17902            "return": {
17903                "description": "pointer to p5.Element holding created node",
17904                "type": "Object|p5.Element"
17905            },
17906            "example": [
17907                "\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>"
17908            ],
17909            "class": "p5.dom",
17910            "module": "p5.dom",
17911            "submodule": "p5.dom"
17912        },
17913        {
17914            "file": "lib/addons/p5.dom.js",
17915            "line": 471,
17916            "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",
17917            "itemtype": "method",
17918            "name": "createCheckbox",
17919            "params": [
17920                {
17921                    "name": "label",
17922                    "description": "<p>label displayed after checkbox</p>\n",
17923                    "type": "String",
17924                    "optional": true
17925                },
17926                {
17927                    "name": "value",
17928                    "description": "<p>value of the checkbox; checked is true, unchecked is false</p>\n",
17929                    "type": "Boolean",
17930                    "optional": true
17931                }
17932            ],
17933            "return": {
17934                "description": "pointer to p5.Element holding created node",
17935                "type": "Object|p5.Element"
17936            },
17937            "example": [
17938                "\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>"
17939            ],
17940            "class": "p5.dom",
17941            "module": "p5.dom",
17942            "submodule": "p5.dom"
17943        },
17944        {
17945            "file": "lib/addons/p5.dom.js",
17946            "line": 539,
17947            "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 p5.Element when selecting existing select box</p>\n",
17948            "itemtype": "method",
17949            "name": "createSelect",
17950            "return": {
17951                "description": "",
17952                "type": "p5.Element"
17953            },
17954            "example": [
17955                "\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>"
17956            ],
17957            "class": "p5.dom",
17958            "module": "p5.dom",
17959            "submodule": "p5.dom",
17960            "overloads": [
17961                {
17962                    "line": 539,
17963                    "params": [
17964                        {
17965                            "name": "multiple",
17966                            "description": "<p>true if dropdown should support multiple selections</p>\n",
17967                            "type": "Boolean",
17968                            "optional": true
17969                        }
17970                    ],
17971                    "return": {
17972                        "description": "",
17973                        "type": "p5.Element"
17974                    }
17975                },
17976                {
17977                    "line": 567,
17978                    "params": [
17979                        {
17980                            "name": "existing",
17981                            "description": "<p>DOM select element</p>\n",
17982                            "type": "Object"
17983                        }
17984                    ],
17985                    "return": {
17986                        "description": "",
17987                        "type": "p5.Element"
17988                    }
17989                }
17990            ]
17991        },
17992        {
17993            "file": "lib/addons/p5.dom.js",
17994            "line": 643,
17995            "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",
17996            "itemtype": "method",
17997            "name": "createRadio",
17998            "params": [
17999                {
18000                    "name": "divId",
18001                    "description": "<p>the id and name of the created div and input field respectively</p>\n",
18002                    "type": "String",
18003                    "optional": true
18004                }
18005            ],
18006            "return": {
18007                "description": "pointer to p5.Element holding created node",
18008                "type": "Object|p5.Element"
18009            },
18010            "example": [
18011                "\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}
18011\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>"
18012            ],
18013            "class": "p5.dom",
18014            "module": "p5.dom",
18015            "submodule": "p5.dom"
18016        },
18017        {
18018            "file": "lib/addons/p5.dom.js",
18019            "line": 781,
18020            "description": "<p>Creates an &lt;input&gt;&lt;/input&gt; element in the DOM for text input.\nUse .size() to set the display length of the box.\nAppends to the container node if one is specified, otherwise\nappends to body.</p>\n",
18021            "itemtype": "method",
18022            "name": "createInput",
18023            "params": [
18024                {
18025                    "name": "value",
18026                    "description": "<p>default value of the input box</p>\n",
18027                    "type": "String",
18028                    "optional": true
18029                },
18030                {
18031                    "name": "type",
18032                    "description": "<p>type of text, ie text, password etc. Defaults to text</p>\n",
18033                    "type": "String",
18034                    "optional": true
18035                }
18036            ],
18037            "return": {
18038                "description": "pointer to p5.Element holding created node",
18039                "type": "Object|p5.Element"
18040            },
18041            "example": [
18042                "\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>"
18043            ],
18044            "class": "p5.dom",
18045            "module": "p5.dom",
18046            "submodule": "p5.dom"
18047        },
18048        {
18049            "file": "lib/addons/p5.dom.js",
18050            "line": 811,
18051            "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",
18052            "itemtype": "method",
18053            "name": "createFileInput",
18054            "params": [
18055                {
18056                    "name": "callback",
18057                    "description": "<p>callback function for when a file loaded</p>\n",
18058                    "type": "Function",
18059                    "optional": true
18060                },
18061                {
18062                    "name": "multiple",
18063                    "description": "<p>optional to allow multiple files selected</p>\n",
18064                    "type": "String",
18065                    "optional": true
18066                }
18067            ],
18068            "return": {
18069                "description": "pointer to p5.Element holding created DOM element",
18070                "type": "Object|p5.Element"
18071            },
18072            "example": [
18073                "\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}"
18074            ],
18075            "class": "p5.dom",
18076            "module": "p5.dom",
18077            "submodule": "p5.dom"
18078        },
18079        {
18080            "file": "lib/addons/p5.dom.js",
18081            "line": 897,
18082            "class": "p5.dom",
18083            "module": "p5.dom",
18084            "submodule": "p5.dom"
18085        },
18086        {
18087            "file": "lib/addons/p5.dom.js",
18088            "line": 934,
18089            "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 .hide()\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 str
18089ing 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",
18090            "itemtype": "method",
18091            "name": "createVideo",
18092            "params": [
18093                {
18094                    "name": "src",
18095                    "description": "<p>path to a video file, or array of paths for\n                            supporting different browsers</p>\n",
18096                    "type": "String|Array"
18097                },
18098                {
18099                    "name": "callback",
18100                    "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",
18101                    "type": "Object",
18102                    "optional": true
18103                }
18104            ],
18105            "return": {
18106                "description": "pointer to video p5.Element",
18107                "type": "p5.MediaElement|p5.Element"
18108            },
18109            "example": [
18110                "\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>"
18111            ],
18112            "class": "p5.dom",
18113            "module": "p5.dom",
18114            "submodule": "p5.dom"
18115        },
18116        {
18117            "file": "lib/addons/p5.dom.js",
18118            "line": 973,
18119            "class": "p5.dom",
18120            "module": "p5.dom",
18121            "submodule": "p5.dom"
18122        },
18123        {
18124            "file": "lib/addons/p5.dom.js",
18125            "line": 975,
18126            "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 string 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",
18127            "itemtype": "method",
18128            "name": "createAudio",
18129            "params": [
18130                {
18131                    "name": "src",
18132                    "description": "<p>path to an audio file, or array of paths\n                            for supporting different browsers</p>\n",
18133                    "type": "String|String[]",
18134                    "optional": true
18135                },
18136                {
18137                    "name": "callback",
18138                    "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",
18139                    "type": "Object",
18140                    "optional": true
18141                }
18142            ],
18143            "return": {
18144                "description": "pointer to audio p5.Element  /**",
18145                "type": "p5.MediaElement|p5.Element"
18146            },
18147            "example": [
18148                "\n<div><code>\nvar ele;\nfunction setup() {\n  ele = createAudio('assets/beat.mp3');
18148\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>"
18149            ],
18150            "class": "p5.dom",
18151            "module": "p5.dom",
18152            "submodule": "p5.dom"
18153        },
18154        {
18155            "file": "lib/addons/p5.dom.js",
18156            "line": 1013,
18157            "class": "p5.dom",
18158            "module": "p5.dom",
18159            "submodule": "p5.dom"
18160        },
18161        {
18162            "file": "lib/addons/p5.dom.js",
18163            "line": 1048,
18164            "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 .hide(). The feed\ncan be drawn onto the canvas using image().</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 createCapture(), 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>",
18165            "itemtype": "method",
18166            "name": "createCapture",
18167            "params": [
18168                {
18169                    "name": "type",
18170                    "description": "<p>type of capture, either VIDEO or\n                                  AUDIO if none specified, default both,\n                                  or a Constraints object</p>\n",
18171                    "type": "String|Constant|Object"
18172                },
18173                {
18174                    "name": "callback",
18175                    "description": "<p>function to be called once\n                                  stream has loaded</p>\n",
18176                    "type": "Function"
18177                }
18178            ],
18179            "return": {
18180                "description": "capture video p5.Element",
18181                "type": "Object|p5.Element"
18182            },
18183            "example": [
18184                "\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>"
18185            ],
18186            "class": "p5.dom",
18187            "module": "p5.dom",
18188            "submodule": "p5.dom"
18189        },
18190        {
18191            "file": "lib/addons/p5.dom.js",
18192            "line": 1167,
18193            "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",
18194            "itemtype": "method",
18195            "name": "createElement",
18196            "params": [
18197                {
18198                    "name": "tag",
18199                    "description": "<p>tag for the new element</p>\n",
18200                    "type": "String"
18201                },
18202                {
18203                    "name": "content",
18204                    "description": "<p>html content to be inserted into the element</p>\n",
18205                    "type": "String",
18206                    "optional": true
18207                }
18208            ],
18209            "return": {
18210                "description": "pointer to p5.Element holding created node",
18211                "type": "Object|p5.Element"
18212            },
18213            "example": [
18214                "\n<div class='norender'><code>\ncreateElement('h2', 'im an h2 p5.element!');\n</code></div>"
18215            ],
18216            "class": "p5.dom",
18217            "module": "p5.dom",
18218            "submodule": "p5.dom"
18219        },
18220        {
18221            "file": "lib/addons/p5.dom.js",
18222            "line": 1193,
18223            "description": "<p>Adds specified class to the element.</p>\n",
18224            "itemtype": "method",
18225            "name": "addClass",
18226            "params": [
18227                {
18228                    "name": "class",
18229                    "description": "<p>name of class to add</p>\n",
18230                    "type": "String"
18231                }
18232            ],
18233            "return": {
18234                "description": "",
18235                "type": "Object|p5.Element"
18236            },
18237            "example": [
18238                "\n <div class='norender'><code>\n var div = createDiv('div');\n div.addClass('myClass');\n </code></div>"
18239            ],
18240            "class": "p5.Element",
18241            "module": "p5.dom",
18242            "submodule": "p5.dom"
18243        },
18244        {
18245            "file": "lib/addons/p5.dom.js",
18246            "line": 1220,
18247            "description": "<p>Removes specified class from the element.</p>\n",
18248            "itemtype": "method",
18249            "name": "removeClass",
18250            "params": [
18251                {
18252                    "name": "class",
18253                    "description": "<p>name of class to remove</p>\n",
18254                    "type": "String"
18255                }
18256            ],
18257            "return": {
18258                "description": "* @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>",
18259                "type": "Object|p5.Element"
18260            },
18261            "class": "p5.Element",
18262            "module": "p5.dom",
18263            "submodule": "p5.dom"
18264        },
18265        {
18266            "file": "lib/addons/p5.dom.js",
18267            "line": 1251,
18268            "description": "<p>Attaches the element  as a child to the parent specified.\n Accepts either a string ID, DOM node, or p5.Element.\n If no argument is specified, an array of children DOM nodes is returned.</p>\n",
18269            "itemtype": "method",
18270            "name": "child",
18271            "params": [
18272                {
18273                    "name": "child",
18274                    "description": "<p>the ID, DOM node, or p5.Element\n                         to add to the current element</p>\n",
18275                    "type": "String|Object|p5.Element",
18276                    "optional": true
18277                }
18278            ],
18279            "return": {
18280                "description": "",
18281                "type": "p5.Element"
18282            },
18283            "example": [
18284                "\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 var div0 = createDiv('this is the parent');\n var elt = document.getElementById('myChildDiv');\n div0.child(elt);
18284 // use element from page\n </code></div>"
18285            ],
18286            "class": "p5.Element",
18287            "module": "p5.dom",
18288            "submodule": "p5.dom"
18289        },
18290        {
18291            "file": "lib/addons/p5.dom.js",
18292            "line": 1295,
18293            "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",
18294            "itemtype": "method",
18295            "name": "center",
18296            "params": [
18297                {
18298                    "name": "align",
18299                    "description": "<p>passing &#39;vertical&#39;, &#39;horizontal&#39; aligns element accordingly</p>\n",
18300                    "type": "String",
18301                    "optional": true
18302                }
18303            ],
18304            "return": {
18305                "description": "pointer to p5.Element",
18306                "type": "Object|p5.Element"
18307            },
18308            "example": [
18309                "\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>"
18310            ],
18311            "class": "p5.Element",
18312            "module": "p5.dom",
18313            "submodule": "p5.dom"
18314        },
18315        {
18316            "file": "lib/addons/p5.dom.js",
18317            "line": 1348,
18318            "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",
18319            "itemtype": "method",
18320            "name": "html",
18321            "params": [
18322                {
18323                    "name": "html",
18324                    "description": "<p>the HTML to be placed inside the element</p>\n",
18325                    "type": "String",
18326                    "optional": true
18327                },
18328                {
18329                    "name": "append",
18330                    "description": "<p>whether to append HTML to existing</p>\n",
18331                    "type": "Boolean",
18332                    "optional": true
18333                }
18334            ],
18335            "return": {
18336                "description": "",
18337                "type": "Object|p5.Element|String"
18338            },
18339            "example": [
18340                "\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>"
18341            ],
18342            "class": "p5.Element",
18343            "module": "p5.dom",
18344            "submodule": "p5.dom"
18345        },
18346        {
18347            "file": "lib/addons/p5.dom.js",
18348            "line": 1383,
18349            "description": "<p>Sets the position of the element relative to (0, 0) of the\n window. Essentially, set
18349s 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",
18350            "itemtype": "method",
18351            "name": "position",
18352            "params": [
18353                {
18354                    "name": "x",
18355                    "description": "<p>x-position relative to upper left of window</p>\n",
18356                    "type": "Number",
18357                    "optional": true
18358                },
18359                {
18360                    "name": "y",
18361                    "description": "<p>y-position relative to upper left of window</p>\n",
18362                    "type": "Number",
18363                    "optional": true
18364                }
18365            ],
18366            "return": {
18367                "description": "",
18368                "type": "Object|p5.Element"
18369            },
18370            "example": [
18371                "\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>"
18372            ],
18373            "class": "p5.Element",
18374            "module": "p5.dom",
18375            "submodule": "p5.dom"
18376        },
18377        {
18378            "file": "lib/addons/p5.dom.js",
18379            "line": 1473,
18380            "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",
18381            "itemtype": "method",
18382            "name": "style",
18383            "params": [
18384                {
18385                    "name": "property",
18386                    "description": "<p>property to be set</p>\n",
18387                    "type": "String"
18388                },
18389                {
18390                    "name": "value",
18391                    "description": "<p>value to assign to property (only String|Number for rotate/translate)</p>\n",
18392                    "type": "String|Number|p5.Color",
18393                    "optional": true
18394                },
18395                {
18396                    "name": "value2",
18397                    "description": "<p>position can take a 2nd value</p>\n",
18398                    "type": "String|Number|p5.Color",
18399                    "optional": true
18400                },
18401                {
18402                    "name": "value3",
18403                    "description": "<p>translate can take a 2nd &amp; 3rd value</p>\n",
18404                    "type": "String|Number|p5.Color",
18405                    "optional": true
18406                }
18407            ],
18408            "return": {
18409                "description": "value of property, if no value is specified\nor p5.Element",
18410                "type": "String|Object|p5.Element"
18411            },
18412            "example": [
18413                "\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>"
18414            ],
18415            "class": "p5.Element",
18416            "module": "p5.dom",
18417            "submodule": "p5.dom"
18418        },
18419        {
18420            "file": "lib/addons/p5.dom.js",
18421            "line": 1570,
18422            "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",
18423            "itemtype": "method",
18424            "name": "attribute",
18425            "params": [
18426                {
18427                    "name": "attr",
18428                    "description": "<p>attribute to set</p>\n",
18429                    "type": "String"
18430                },
18431                {
18432                    "name": "value",
18433                    "description": "<p>value to assign to attribute</p>\n",
18434                    "type": "String",
18435                    "optional": true
18436                }
18437            ],
18438            "return": {
18439                "description": "value of attribute, if no value is\n                             specified or p5.Element",
18440                "type": "String|Object|p5.Element"
18441            },
18442            "example": [
18443                "\n <div class='norender'><code>\n var myDiv = createDiv('I like pandas.');\n myDiv.attribute('align', 'center');\n </code></div>"
18444            ],
18445            "class": "p5.Element",
18446            "module": "p5.dom",
18447            "submodule": "p5.dom"
18448        },
18449        {
18450            "file": "lib/addons/p5.dom.js",
18451            "line": 1610,
18452            "description": "<p>Removes an attribute on the specified element.</p>\n",
18453            "itemtype": "method",
18454            "name": "removeAttribute",
18455            "params": [
18456                {
18457                    "name": "attr",
18458                    "description": "<p>attribute to remove</p>\n",
18459                    "type": "String"
18460                }
18461            ],
18462            "return": {
18463                "description": "",
18464                "type": "Object|p5.Element"
18465            },
18466            "example": [
18467                "\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>"
18468            ],
18469            "class": "p5.Element",
18470            "module": "p5.dom",
18471            "submodule": "p5.dom"
18472        },
18473        {
18474            "file": "lib/addons/p5.dom.js",
18475            "line": 1655,
18476            "description": "<p>Either returns the value of the element if no arguments\ngiven, or sets the value of the element.</p>\n",
18477            "itemtype": "method",
18478            "name": "value",
18479            "params": [
18480                {
18481                    "name": "value",
18482                    "description": "",
18483                    "type": "String|Number",
18484                    "optional": true
18485                }
18486            ],
18487            "return": {
18488                "description": "value of element if no value is specified or p5.Element",
18489                "type": "String|Object|p5.Element"
18490            },
18491            "example": [
18492                "\n<div class='norender'><code>\n// gets the value\nvar inp;\nfunction setup() {\n  inp = createInput('');\n}
18492\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>"
18493            ],
18494            "class": "p5.Element",
18495            "module": "p5.dom",
18496            "submodule": "p5.dom"
18497        },
18498        {
18499            "file": "lib/addons/p5.dom.js",
18500            "line": 1697,
18501            "description": "<p>Shows the current element. Essentially, setting display:block for the style.</p>\n",
18502            "itemtype": "method",
18503            "name": "show",
18504            "return": {
18505                "description": "",
18506                "type": "Object|p5.Element"
18507            },
18508            "example": [
18509                "\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>"
18510            ],
18511            "class": "p5.Element",
18512            "module": "p5.dom",
18513            "submodule": "p5.dom"
18514        },
18515        {
18516            "file": "lib/addons/p5.dom.js",
18517            "line": 1715,
18518            "description": "<p>Hides the current element. Essentially, setting display:none for the style.</p>\n",
18519            "itemtype": "method",
18520            "name": "hide",
18521            "return": {
18522                "description": "",
18523                "type": "Object|p5.Element"
18524            },
18525            "example": [
18526                "\n<div class='norender'><code>\nvar div = createDiv('this is a div');\ndiv.hide();\n</code></div>"
18527            ],
18528            "class": "p5.Element",
18529            "module": "p5.dom",
18530            "submodule": "p5.dom"
18531        },
18532        {
18533            "file": "lib/addons/p5.dom.js",
18534            "line": 1731,
18535            "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",
18536            "itemtype": "method",
18537            "name": "size",
18538            "params": [
18539                {
18540                    "name": "w",
18541                    "description": "<p>width of the element, either AUTO, or a number</p>\n",
18542                    "type": "Number|Constant",
18543                    "optional": true
18544                },
18545                {
18546                    "name": "h",
18547                    "description": "<p>height of the element, either AUTO, or a number</p>\n",
18548                    "type": "Number|Constant",
18549                    "optional": true
18550                }
18551            ],
18552            "return": {
18553                "description": "",
18554                "type": "Object|p5.Element"
18555            },
18556            "example": [
18557                "\n <div class='norender'><code>\n var div = createDiv('this is a div');\n div.size(100, 100);\n </code></div>"
18558            ],
18559            "class": "p5.Element",
18560            "module": "p5.dom",
18561            "submodule": "p5.dom"
18562        },
18563        {
18564            "file": "lib/addons/p5.dom.js",
18565            "line": 1805,
18566            "description": "<p>Removes the element and deregisters all listeners.</p>\n",
18567            "itemtype": "method",
18568            "name": "remove",
18569            "example": [
18570                "\n<div class='norender'><code>\nvar myDiv = createDiv('this is some text');\nmyDiv.remove();\n</code></div>"
18571            ],
18572            "class": "p5.Element",
18573            "module": "p5.dom",
18574            "submodule": "p5.dom"
18575        },
18576        {
18577            "file": "lib/addons/p5.dom.js",
18578            "line": 1851,
18579            "description": "<p>Path to the media element source.</p>\n",
18580            "itemtype": "property",
18581            "name": "src",
18582            "return": {
18583                "description": "src",
18584                "type": "String"
18585            },
18586            "example": [
18587                "\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>"
18588            ],
18589            "class": "p5.MediaElement",
18590            "module": "p5.dom",
18591            "submodule": "p5.dom"
18592        },
18593        {
18594            "file": "lib/addons/p5.dom.js",
18595            "line": 1917,
18596            "description": "<p>Play an HTML5 media element.</p>\n",
18597            "itemtype": "method",
18598            "name": "play",
18599            "return": {
18600                "description": "",
18601                "type": "Object|p5.Element"
18602            },
18603            "example": [
18604                "\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>"
18605            ],
18606            "class": "p5.MediaElement",
18607            "module": "p5.dom",
18608            "submodule": "p5.dom"
18609        },
18610        {
18611            "file": "lib/addons/p5.dom.js",
18612            "line": 1970,
18613            "description": "<p>Stops an HTML5 media element (sets current time to zero).</p>\n",
18614            "itemtype": "method",
18615            "name": "stop",
18616            "return": {
18617                "description": "",
18618                "type": "Object|p5.Element"
18619            },
18620            "example": [
18621                "\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>"
18622            ],
18623            "class": "p5.MediaElement",
18624            "module": "p5.dom",
18625            "submodule": "p5.dom"
18626        },
18627        {
18628            "file": "lib/addons/p5.dom.js",
18629            "line": 2034,
18630            "description": "<p>Pauses an HTML5 media element.</p>\n",
18631            "itemtype": "method",
18632            "name": "pause",
18633            "return": {
18634                "description": "",
18635                "type": "Object|p5.Element"
18636            },
18637            "example": [
18638                "\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>"
18639            ],
18640            "class": "p5.MediaElement",
18641            "module": "p5.dom",
18642            "submodule": "p5.dom"
18643        },
18644        {
18645            "file": "lib/addons/p5.dom.js",
18646            "line": 2096,
18647            "description": "<p>Set &#39;loop&#39; to true for an HTML5 media element, and starts playing.</p>\n",
18648            "itemtype": "method",
18649            "name": "loop",
18650            "return": {
18651                "description": "",
18652                "type": "Object|p5.Element"
18653            },
18654            "example": [
18655                "\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>"
18656            ],
18657            "class": "p5.MediaElement",
18658            "module": "p5.dom",
18659            "submodule": "p5.dom"
18660        },
18661        {
18662            "file": "lib/addons/p5.dom.js",
18663            "line": 2152,
18664            "description": "<p>Set &#39;loop&#39; to false for an HTML5 media element. Element will stop\nwhen it reaches the end.</p>\n",
18665            "itemtype": "method",
18666            "name": "noLoop",
18667            "return": {
18668                "description": "",
18669                "type": "Object|p5.Element"
18670            },
18671            "example": [
18672                "\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"
18673            ],
18674            "class": "p5.MediaElement",
18675            "module": "p5.dom",
18676            "submodule": "p5.dom"
18677        },
18678        {
18679            "file": "lib/addons/p5.dom.js",
18680            "line": 2204,
18681            "description": "<p>
18681Set HTML5 media element to autoplay or not.</p>\n",
18682            "itemtype": "method",
18683            "name": "autoplay",
18684            "params": [
18685                {
18686                    "name": "autoplay",
18687                    "description": "<p>whether the element should autoplay</p>\n",
18688                    "type": "Boolean"
18689                }
18690            ],
18691            "return": {
18692                "description": "",
18693                "type": "Object|p5.Element"
18694            },
18695            "class": "p5.MediaElement",
18696            "module": "p5.dom",
18697            "submodule": "p5.dom"
18698        },
18699        {
18700            "file": "lib/addons/p5.dom.js",
18701            "line": 2216,
18702            "description": "<p>Sets volume for this HTML5 media element. If no argument is given,\nreturns the current volume.</p>\n",
18703            "params": [
18704                {
18705                    "name": "val",
18706                    "description": "<p>volume between 0.0 and 1.0</p>\n",
18707                    "type": "Number",
18708                    "optional": true
18709                }
18710            ],
18711            "return": {
18712                "description": "current volume or p5.MediaElement",
18713                "type": "Number|p5.MediaElement"
18714            },
18715            "itemtype": "method",
18716            "name": "volume",
18717            "example": [
18718                "\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>"
18719            ],
18720            "class": "p5.MediaElement",
18721            "module": "p5.dom",
18722            "submodule": "p5.dom"
18723        },
18724        {
18725            "file": "lib/addons/p5.dom.js",
18726            "line": 2298,
18727            "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",
18728            "itemtype": "method",
18729            "name": "speed",
18730            "params": [
18731                {
18732                    "name": "speed",
18733                    "description": "<p>speed multiplier for element playback</p>\n",
18734                    "type": "Number",
18735                    "optional": true
18736                }
18737            ],
18738            "return": {
18739                "description": "current playback speed or p5.MediaElement",
18740                "type": "Number|Object|p5.MediaElement"
18741            },
18742            "example": [
18743                "\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}
18743\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>"
18744            ],
18745            "class": "p5.MediaElement",
18746            "module": "p5.dom",
18747            "submodule": "p5.dom"
18748        },
18749        {
18750            "file": "lib/addons/p5.dom.js",
18751            "line": 2377,
18752            "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",
18753            "itemtype": "method",
18754            "name": "time",
18755            "params": [
18756                {
18757                    "name": "time",
18758                    "description": "<p>time to jump to (in seconds)</p>\n",
18759                    "type": "Number",
18760                    "optional": true
18761                }
18762            ],
18763            "return": {
18764                "description": "current time (in seconds)\n                                or p5.MediaElement",
18765                "type": "Number|Object|p5.MediaElement"
18766            },
18767            "example": [
18768                "\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>"
18769            ],
18770            "class": "p5.MediaElement",
18771            "module": "p5.dom",
18772            "submodule": "p5.dom"
18773        },
18774        {
18775            "file": "lib/addons/p5.dom.js",
18776            "line": 2432,
18777            "description": "<p>Returns the duration of the HTML5 media element.</p>\n",
18778            "itemtype": "method",
18779            "name": "duration",
18780            "return": {
18781                "description": "duration",
18782                "type": "Number"
18783            },
18784            "example": [
18785                "\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>"
18786            ],
18787            "class": "p5.MediaElement",
18788            "module": "p5.dom",
18789            "submodule": "p5.dom"
18790        },
18791        {
18792            "file": "lib/addons/p5.dom.js",
18793            "line": 2550,
18794            "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",
18795            "itemtype": "method",
18796            "name": "onended",
18797            "params": [
18798                {
18799                    "name": "callback",
18800                    "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",
18801                    "type": "Function"
18802                }
18803            ],
18804            "return": {
18805                "description": "",
18806                "type": "Object|p5.MediaElement"
18807            },
18808            "example": [
18809                "\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>"
18810            ],
18811            "class": "p5.MediaElement",
18812            "module": "p5.dom",
18813            "submodule": "p5.dom"
18814        },
18815        {
18816            "file": "lib/addons/p5.dom.js",
18817            "line": 2581,
18818            "class": "p5.MediaElement",
18819            "module": "p5.dom",
18820            "submodule": "p5.dom"
18821        },
18822        {
18823            "file": "lib/addons/p5.dom.js",
18824            "line": 2583,
18825            "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",
18826            "itemtype": "method",
18827            "name": "connect",
18828            "params": [
18829                {
18830                    "name": "audioNode",
18831                    "description": "<p>AudioNode from the Web Audio API,\nor an object from the p5.sound library</p>\n",
18832                    "type": "AudioNode|Object"
18833                }
18834            ],
18835            "class": "p5.MediaElement",
18836            "module": "p5.dom",
18837            "submodule": "p5.dom"
18838        },
18839        {
18840            "file": "lib/addons/p5.dom.js",
18841            "line": 2632,
18842            "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",
18843            "itemtype": "method",
18844            "name": "disconnect",
18845            "class": "p5.MediaElement",
18846            "module": "p5.dom",
18847            "submodule": "p5.dom"
18848        },
18849        {
18850            "file": "lib/addons/p5.dom.js",
18851            "line": 2647,
18852            "class": "p5.MediaElement",
18853            "module": "p5.dom",
18854            "submodule": "p5.dom"
18855        },
18856        {
18857            "file": "lib/addons/p5.dom.js",
18858            "line": 2649,
18859            "description": "<p>Show the default MediaElement controls, as determined by the web browser.</p>\n",
18860            "itemtype": "method",
18861            "name": "showControls",
18862            "example": [
18863                "\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>"
18864            ],
18865            "class": "p5.MediaElement",
18866            "module": "p5.dom",
18867            "submodule": "p5.dom"
18868        },
18869        {
18870            "file": "lib/addons/p5.dom.js",
18871            "line": 2680,
18872            "description": "<p>Hide the default mediaElement controls.</p>\n",
18873            "itemtype": "method",
18874            "name": "hideControls",
18875            "example": [
18876                "\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>"
18877            ],
18878            "class": "p5.MediaElement",
18879            "module": "p5.dom",
18880            "submodule": "p5.dom"
18881        },
18882        {
18883            "file": "lib/addons/p5.dom.js",
18884            "line": 2709,
18885            "class": "p5.MediaElement",
18886            "module": "p5.dom",
18887            "submodule": "p5.dom"
18888        },
18889        {
18890            "file": "lib/addons/p5.dom.js",
18891            "line": 2720,
18892            "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",
18893            "itemtype": "method",
18894            "name": "addCue",
18895            "params": [
18896                {
18897                    "name": "time",
18898                    "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",
18899                    "type": "Number"
18900                },
18901                {
18902                    "name": "callback",
18903                    "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",
18904                    "type": "Function"
18905                },
18906                {
18907                    "name": "value",
18908                    "description": "<p>An object to be passed as the\n                            second parameter to the\n                            callback function.</p>\n",
18909                    "type": "Object",
18910                    "optional": true
18911                }
18912            ],
18913            "return": {
18914                "description": "id ID of this cue,\n                    useful for removeCue(id)",
18915                "type": "Number"
18916            },
18917            "example": [
18918                "\n<div><code>\nfunction setup() {\n  background(255, 255, 255);\n\n  var audioEl = createAudio('assets/beat.mp3');\n  audioEl.showControls();
18918\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>"
18919            ],
18920            "class": "p5.MediaElement",
18921            "module": "p5.dom",
18922            "submodule": "p5.dom"
18923        },
18924        {
18925            "file": "lib/addons/p5.dom.js",
18926            "line": 2782,
18927            "description": "<p>Remove a callback based on its ID. The ID is returned by the\naddCue method.</p>\n",
18928            "itemtype": "method",
18929            "name": "removeCue",
18930            "params": [
18931                {
18932                    "name": "id",
18933                    "description": "<p>ID of the cue, as returned by addCue</p>\n",
18934                    "type": "Number"
18935                }
18936            ],
18937            "example": [
18938                "\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>"
18939            ],
18940            "class": "p5.MediaElement",
18941            "module": "p5.dom",
18942            "submodule": "p5.dom"
18943        },
18944        {
18945            "file": "lib/addons/p5.dom.js",
18946            "line": 2824,
18947            "description": "<p>Remove all of the callbacks that had originally been scheduled\nvia the addCue method.</p>\n",
18948            "itemtype": "method",
18949            "name": "clearCues",
18950            "params": [
18951                {
18952                    "name": "id",
18953                    "description": "<p>ID of the cue, as returned by addCue</p>\n",
18954                    "type": "Number"
18955                }
18956            ],
18957            "example": [
18958                "\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>"
18959            ],
18960            "class": "p5.MediaElement",
18961            "module": "p5.dom",
18962            "submodule": "p5.dom"
18963        },
18964        {
18965            "file": "lib/addons/p5.dom.js",
18966            "line": 2894,
18967            "description": "<p>Underlying File object. All normal File methods can be called on this.</p>\n",
18968            "itemtype": "property",
18969            "name": "file",
18970            "class": "p5.File",
18971            "module": "p5.dom",
18972            "submodule": "p5.dom"
18973        },
18974        {
18975            "file": "lib/addons/p5.dom.js",
18976            "line": 2906,
18977            "description": "<p>File type (image, text, etc.)</p>\n",
18978            "itemtype": "property",
18979            "name": "type",
18980            "class": "p5.File",
18981            "module": "p5.dom",
18982            "submodule": "p5.dom"
18983        },
18984        {
18985            "file": "lib/addons/p5.dom.js",
18986            "line": 2912,
18987            "description": "<p>File subtype (usually the file extension jpg, png, xml, etc.)</p>\n",
18988            "itemtype": "property",
18989            "name": "subtype",
18990            "class": "p5.File",
18991            "module": "p5.dom",
18992            "submodule": "p5.dom"
18993        },
18994        {
18995            "file": "lib/addons/p5.dom.js",
18996            "line": 2918,
18997            "description": "<p>File name</p>\n",
18998            "itemtype": "property",
18999            "name": "name",
19000            "class": "p5.File",
19001            "module": "p5.dom",
19002            "submodule": "p5.dom"
19003        },
19004        {
19005            "file": "lib/addons/p5.dom.js",
19006            "line": 2924,
19007            "description": "<p>File size</p>\n",
19008            "itemtype": "property",
19009            "name": "size",
19010            "class": "p5.File",
19011            "module": "p5.dom",
19012            "submodule": "p5.dom"
19013        },
19014        {
19015            "file": "lib/addons/p5.dom.js",
19016            "line": 2931,
19017            "description": "<p>URL string containing image data.</p>\n",
19018            "itemtype": "property",
19019            "name": "data",
19020            "class": "p5.File",
19021            "module": "p5.dom",
19022            "submodule": "p5.dom"
19023        },
19024        {
19025            "file": "lib/addons/p5.sound.js",
19026            "line": 46,
19027            "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",
19028            "class": "p5.sound",
19029            "module": "p5.sound",
19030            "submodule": "p5.sound"
19031        },
19032        {
19033            "file": "lib/addons/p5.sound.js",
19034            "line": 212,
19035            "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>",
19036            "itemtype": "method",
19037            "name": "getAudioContext",
19038            "return": {
19039                "description": "AudioContext for this sketch",
19040                "type": "Object"
19041            },
19042            "class": "p5.sound",
19043            "module": "p5.sound",
19044            "submodule": "p5.sound"
19045        },
19046        {
19047            "file": "lib/addons/p5.sound.js",
19048            "line": 226,
19049            "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",
19050            "class": "p5.sound",
19051            "module": "p5.sound",
19052            "submodule": "p5.sound"
19053        },
19054        {
19055            "file": "lib/addons/p5.sound.js",
19056            "line": 296,
19057            "description": "<p>Master contains AudioContext and the master sound output.</p>\n",
19058            "class": "p5.sound",
19059            "module": "p5.sound",
19060            "submodule": "p5.sound"
19061        },
19062        {
19063            "file": "lib/addons/p5.sound.js",
19064            "line": 329,
19065            "description": "<p>Returns a number representing the master amplitude (volume) for sound\nin this sketch.</p>\n",
19066            "itemtype": "method",
19067            "name": "getMasterVolume",
19068            "return": {
19069                "description": "Master amplitude (volume) for sound in this sketch.\n                 Should be between 0.0 (silence) and 1.0.",
19070                "type": "Number"
19071            },
19072            "class": "p5.sound",
19073            "module": "p5.sound",
19074            "submodule": "p5.sound"
19075        },
19076        {
19077            "file": "lib/addons/p5.sound.js",
19078            "line": 340,
19079            "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 Env 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>",
19080            "itemtype": "method",
19081            "name": "masterVolume",
19082            "params": [
19083                {
19084                    "name": "volume",
19085                    "description": "<p>Volume (amplitude) between 0.0\n                                   and 1.0 or modulating signal/oscillator</p>\n",
19086                    "type": "Number|Object"
19087                },
19088                {
19089                    "name": "rampTime",
19090                    "description": "<p>Fade for t seconds</p>\n",
19091                    "type": "Number",
19092                    "optional": true
19093                },
19094                {
19095                    "name": "timeFromNow",
19096                    "description": "<p>Schedule this event to happen at\n                               t seconds 
19096in the future</p>\n",
19097                    "type": "Number",
19098                    "optional": true
19099                }
19100            ],
19101            "class": "p5.sound",
19102            "module": "p5.sound",
19103            "submodule": "p5.sound"
19104        },
19105        {
19106            "file": "lib/addons/p5.sound.js",
19107            "line": 382,
19108            "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",
19109            "itemtype": "property",
19110            "name": "soundOut",
19111            "type": "Object",
19112            "class": "p5.sound",
19113            "module": "p5.sound",
19114            "submodule": "p5.sound"
19115        },
19116        {
19117            "file": "lib/addons/p5.sound.js",
19118            "line": 407,
19119            "class": "p5",
19120            "module": "p5.sound",
19121            "submodule": "p5.sound"
19122        },
19123        {
19124            "file": "lib/addons/p5.sound.js",
19125            "line": 410,
19126            "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",
19127            "itemtype": "method",
19128            "name": "sampleRate",
19129            "return": {
19130                "description": "samplerate samples per second",
19131                "type": "Number"
19132            },
19133            "class": "p5",
19134            "module": "p5.sound",
19135            "submodule": "p5.sound"
19136        },
19137        {
19138            "file": "lib/addons/p5.sound.js",
19139            "line": 423,
19140            "description": "<p>Returns the closest MIDI note value for\na given frequency.</p>\n",
19141            "itemtype": "method",
19142            "name": "freqToMidi",
19143            "params": [
19144                {
19145                    "name": "frequency",
19146                    "description": "<p>A freqeuncy, for example, the &quot;A&quot;\n                           above Middle C is 440Hz</p>\n",
19147                    "type": "Number"
19148                }
19149            ],
19150            "return": {
19151                "description": "MIDI note value",
19152                "type": "Number"
19153            },
19154            "class": "p5",
19155            "module": "p5.sound",
19156            "submodule": "p5.sound"
19157        },
19158        {
19159            "file": "lib/addons/p5.sound.js",
19160            "line": 437,
19161            "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",
19162            "itemtype": "method",
19163            "name": "midiToFreq",
19164            "params": [
19165                {
19166                    "name": "midiNote",
19167                    "description": "<p>The number of a MIDI note</p>\n",
19168                    "type": "Number"
19169                }
19170            ],
19171            "return": {
19172                "description": "Frequency value of the given MIDI note",
19173                "type": "Number"
19174            },
19175            "example": [
19176                "\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>"
19177            ],
19178            "class": "p5",
19179            "module": "p5.sound",
19180            "submodule": "p5.sound"
19181        },
19182        {
19183            "file": "lib/addons/p5.sound.js",
19184            "line": 470,
19185            "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",
19186            "itemtype": "method",
19187            "name": "soundFormats",
19188            "params": [
19189                {
19190                    "name": "formats",
19191                    "description": "<p>i.e. &#39;mp3&#39;, &#39;wav&#39;, &#39;ogg&#39;</p>\n",
19192                    "type": "String",
19193                    "optional": true,
19194                    "multiple": true
19195                }
19196            ],
19197            "example": [
19198                "\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>"
19199            ],
19200            "class": "p5",
19201            "module": "p5.sound",
19202            "submodule": "p5.sound"
19203        },
19204        {
19205            "file": "lib/addons/p5.sound.js",
19206            "line": 583,
19207            "description": "<p>Used by Osc and Env to chain signal math</p>\n",
19208            "class": "p5",
19209            "module": "p5.sound",
19210            "submodule": "p5.sound"
19211        },
19212        {
19213            "file": "lib/addons/p5.sound.js",
19214            "line": 855,
19215            "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",
19216            "itemtype": "method",
19217            "name": "loadSound",
19218            "params": [
19219                {
19220                    "name": "path",
19221                    "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",
19222                    "type": "String|Array"
19223                },
19224                {
19225                    "name": "successCallback",
19226                    "description": "<p>Name of a function to call once file loads</p>\n",
19227                    "type": "Function",
19228                    "optional": true
19229                },
19230                {
19231                    "name": "errorCallback",
19232                    "description": "<p>Name of a function to call if there is\n                                    an error loading the file.</p>\n",
19233                    "type": "Function",
19234                    "optional": true
19235                },
19236                {
19237                    "name": "whileLoading",
19238                    "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",
19239                    "type": "Function",
19240                    "optional": true
19241                }
19242            ],
19243            "return": {
19244                "description": "Returns a p5.SoundFile",
19245                "type": "SoundFile"
19246            },
19247            "example": [
19248                "\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>"
19249            ],
19250            "class": "p5.SoundFile",
19251            "module": "p5.sound",
19252            "submodule": "p5.sound"
19253        },
19254        {
19255            "file": "lib/addons/p5.sound.js",
19256            "line": 995,
19257            "description": "<p>Returns true if the sound file finished loading successfully.</p>\n",
19258            "itemtype": "method",
19259            "name": "isLoaded",
19260            "return": {
19261                "description": "",
19262                "type": "Boolean"
19263            },
19264            "class": "p5.SoundFile",
19265            "module": "p5.sound",
19266            "submodule": "p5.sound"
19267        },
19268        {
19269            "file": "lib/addons/p5.sound.js",
19270            "line": 1008,
19271            "description": "<p>Play the p5.SoundFile</p>\n",
19272            "itemtype": "method",
19273            "name": "play",
19274            "params": [
19275                {
19276                    "name": "startTime",
19277                    "description": "<p>(optional) schedule playback to start (in seconds from now).</p>\n",
19278                    "type": "Number",
19279                    "optional": true
19280                },
19281                {
19282                    "name": "rate",
19283                    "description": "<p>(optional) playback rate</p>\n",
19284                    "type": "Number",
19285                    "optional": true
19286                },
19287                {
19288                    "name": "amp",
19289                    "description": "<p>(optional) amplitude (volume)\n                                    of playback</p>\n",
19290                    "type": "Number",
19291                    "optional": true
19292                },
19293                {
19294                    "name": "cueStart",
19295                    "description": "<p>(optional) cue start time in seconds</p>\n",
19296                    "type": "Number",
19297                    "optional": true
19298                },
19299                {
19300                    "name": "duration",
19301                    "description": "<p>(optional) duration of playback in seconds</p>\n",
19302                    "type": "Number",
19303                    "optional": true
19304                }
19305            ],
19306            "class": "p5.SoundFile",
19307            "module": "p5.sound",
19308            "submodule": "p5.sound"
19309        },
19310        {
19311            "file": "lib/addons/p5.sound.js",
19312            "line": 1109,
19313            "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",
19314            "itemtype": "method",
19315            "name": "playMode",
19316            "params": [
19317                {
19318                    "name": "str",
19319                    "description": "<p>&#39;restart&#39; or &#39;sustain&#39; or &#39;untilDone&#39;</p>\n",
19320                    "type": "String"
19321                }
19322            ],
19323            "example": [
19324                "\n<div><code>\nfunction setup(){\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>"
19325            ],
19326            "class": "p5.SoundFile",
19327            "module": "p5.sound",
19328            "submodule": "p5.sound"
19329        },
19330        {
19331            "file": "lib/addons/p5.sound.js",
19332            "line": 1152,
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                {
19338                    "name": "startTime",
19339                    "description": "<p>(optional) schedule event to occur\n                             seconds from now</p>\n",
19340                    "type": "Number",
19341                    "optional": true
19342                }
19343            ],
19344            "example": [
19345                "\n<div><code>\nvar soundFile;\n\nfunction preload() {\n  soundFormats('ogg', 'mp3');\n  soundFile = loadSound('assets/Damscray_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>"
19346            ],
19347            "class": "p5.SoundFile",
19348            "module": "p5.sound",
19349            "submodule": "p5.sound"
19350        },
19351        {
19352            "file": "lib/addons/p5.sound.js",
19353            "line": 1208,
19354            "description": "<p>
19354Loop the p5.SoundFile. Accepts optional parameters to set the\nplayback rate, playback volume, loopStart, loopEnd.</p>\n",
19355            "itemtype": "method",
19356            "name": "loop",
19357            "params": [
19358                {
19359                    "name": "startTime",
19360                    "description": "<p>(optional) schedule event to occur\n                            seconds from now</p>\n",
19361                    "type": "Number",
19362                    "optional": true
19363                },
19364                {
19365                    "name": "rate",
19366                    "description": "<p>(optional) playback rate</p>\n",
19367                    "type": "Number",
19368                    "optional": true
19369                },
19370                {
19371                    "name": "amp",
19372                    "description": "<p>(optional) playback volume</p>\n",
19373                    "type": "Number",
19374                    "optional": true
19375                },
19376                {
19377                    "name": "cueLoopStart",
19378                    "description": "<p>(optional) startTime in seconds</p>\n",
19379                    "type": "Number",
19380                    "optional": true
19381                },
19382                {
19383                    "name": "duration",
19384                    "description": "<p>(optional) loop duration in seconds</p>\n",
19385                    "type": "Number",
19386                    "optional": true
19387                }
19388            ],
19389            "class": "p5.SoundFile",
19390            "module": "p5.sound",
19391            "submodule": "p5.sound"
19392        },
19393        {
19394            "file": "lib/addons/p5.sound.js",
19395            "line": 1224,
19396            "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",
19397            "itemtype": "method",
19398            "name": "setLoop",
19399            "params": [
19400                {
19401                    "name": "Boolean",
19402                    "description": "<p>set looping to true or false</p>\n",
19403                    "type": "Boolean"
19404                }
19405            ],
19406            "class": "p5.SoundFile",
19407            "module": "p5.sound",
19408            "submodule": "p5.sound"
19409        },
19410        {
19411            "file": "lib/addons/p5.sound.js",
19412            "line": 1245,
19413            "description": "<p>Returns &#39;true&#39; if a p5.SoundFile is currently looping and playing, &#39;false&#39; if not.</p>\n",
19414            "itemtype": "method",
19415            "name": "isLooping",
19416            "return": {
19417                "description": "",
19418                "type": "Boolean"
19419            },
19420            "class": "p5.SoundFile",
19421            "module": "p5.sound",
19422            "submodule": "p5.sound"
19423        },
19424        {
19425            "file": "lib/addons/p5.sound.js",
19426            "line": 1260,
19427            "description": "<p>Returns true if a p5.SoundFile is playing, false if not (i.e.\npaused or stopped).</p>\n",
19428            "itemtype": "method",
19429            "name": "isPlaying",
19430            "return": {
19431                "description": "",
19432                "type": "Boolean"
19433            },
19434            "class": "p5.SoundFile",
19435            "module": "p5.sound",
19436            "submodule": "p5.sound"
19437        },
19438        {
19439            "file": "lib/addons/p5.sound.js",
19440            "line": 1270,
19441            "description": "<p>Returns true if a p5.SoundFile is paused, false if not (i.e.\nplaying or stopped).</p>\n",
19442            "itemtype": "method",
19443            "name": "isPaused",
19444            "return": {
19445                "description": "",
19446                "type": "Boolean"
19447            },
19448            "class": "p5.SoundFile",
19449            "module": "p5.sound",
19450            "submodule": "p5.sound"
19451        },
19452        {
19453            "file": "lib/addons/p5.sound.js",
19454            "line": 1280,
19455            "description": "<p>Stop soundfile playback.</p>\n",
19456            "itemtype": "method",
19457            "name": "stop",
19458            "params": [
19459                {
19460                    "name": "startTime",
19461                    "description": "<p>(optional) schedule event to occur\n                            in seconds from now</p>\n",
19462                    "type": "Number",
19463                    "optional": true
19464                }
19465            ],
19466            "class": "p5.SoundFile",
19467            "module": "p5.sound",
19468            "submodule": "p5.sound"
19469        },
19470        {
19471            "file": "lib/addons/p5.sound.js",
19472            "line": 1326,
19473            "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 Env 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",
19474            "itemtype": "method",
19475            "name": "setVolume",
19476            "params": [
19477                {
19478                    "name": "volume",
19479                    "description": "<p>Volume (amplitude) between 0.0\n                                   and 1.0 or modulating signal/oscillator</p>\n",
19480                    "type": "Number|Object"
19481                },
19482                {
19483                    "name": "rampTime",
19484                    "description": "<p>Fade for t seconds</p>\n",
19485                    "type": "Number",
19486                    "optional": true
19487                },
19488                {
19489                    "name": "timeFromNow",
19490                    "description": "<p>Schedule this event to happen at\n                               t seconds 
19490in the future</p>\n",
19491                    "type": "Number",
19492                    "optional": true
19493                }
19494            ],
19495            "class": "p5.SoundFile",
19496            "module": "p5.sound",
19497            "submodule": "p5.sound"
19498        },
19499        {
19500            "file": "lib/addons/p5.sound.js",
19501            "line": 1367,
19502            "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",
19503            "itemtype": "method",
19504            "name": "pan",
19505            "params": [
19506                {
19507                    "name": "panValue",
19508                    "description": "<p>Set the stereo panner</p>\n",
19509                    "type": "Number",
19510                    "optional": true
19511                },
19512                {
19513                    "name": "timeFromNow",
19514                    "description": "<p>schedule this event to happen\n                                seconds from now</p>\n",
19515                    "type": "Number",
19516                    "optional": true
19517                }
19518            ],
19519            "example": [
19520                "\n<div><code>\n\n var ball = {};\n var soundFile;\n\n function setup() {\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>"
19521            ],
19522            "class": "p5.SoundFile",
19523            "module": "p5.sound",
19524            "submodule": "p5.sound"
19525        },
19526        {
19527            "file": "lib/addons/p5.sound.js",
19528            "line": 1406,
19529            "description": "<p>Returns the current stereo pan position (-1.0 to 1.0)</p>\n",
19530            "itemtype": "method",
19531            "name": "getPan",
19532            "return": {
19533                "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.",
19534                "type": "Number"
19535            },
19536            "class": "p5.SoundFile",
19537            "module": "p5.sound",
19538            "submodule": "p5.sound"
19539        },
19540        {
19541            "file": "lib/addons/p5.sound.js",
19542            "line": 1417,
19543            "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",
19544            "itemtype": "method",
19545            "name": "rate",
19546            "params": [
19547                {
19548                    "name": "playbackRate",
19549                    "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",
19550                    "type": "Number",
19551                    "optional": true
19552                }
19553            ],
19554            "example": [
19555                "\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"
19556            ],
19557            "class": "p5.SoundFile",
19558            "module": "p5.sound",
19559            "submodule": "p5.sound"
19560        },
19561        {
19562            "file": "lib/addons/p5.sound.js",
19563            "line": 1490,
19564            "description": "<p>Returns the duration of a sound file in seconds.</p>\n",
19565            "itemtype": "method",
19566            "name": "duration",
19567            "return": {
19568                "description": "The duration of the soundFile in seconds.",
19569                "type": "Number"
19570            },
19571            "class": "p5.SoundFile",
19572            "module": "p5.sound",
19573            "submodule": "p5.sound"
19574        },
19575        {
19576            "file": "lib/addons/p5.sound.js",
19577            "line": 1504,
19578            "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",
19579            "itemtype": "method",
19580            "name": "currentTime",
19581            "return": {
19582                "description": "currentTime of the soundFile in seconds.",
19583                "type": "Number"
19584            },
19585            "class": "p5.SoundFile",
19586            "module": "p5.sound",
19587            "submodule": "p5.sound"
19588        },
19589        {
19590            "file": "lib/addons/p5.sound.js",
19591            "line": 1515,
19592            "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",
19593            "itemtype": "method",
19594            "name": "jump",
19595            "params": [
19596                {
19597                    "name": "cueTime",
19598                    "description": "<p>cueTime of the soundFile in seconds.</p>\n",
19599                    "type": "Number"
19600                },
19601                {
19602                    "name": "duration",
19603                    "description": "<p>duration in seconds.</p>\n",
19604                    "type": "Number"
19605                }
19606            ],
19607            "class": "p5.SoundFile",
19608            "module": "p5.sound",
19609            "submodule": "p5.sound"
19610        },
19611        {
19612            "file": "lib/addons/p5.sound.js",
19613            "line": 1538,
19614            "description": "<p>Return the number of channels in a sound file.\nFor example, Mono = 1, Stereo = 2.</p>\n",
19615            "itemtype": "method",
19616            "name": "channels",
19617            "return": {
19618                "description": "[channels]",
19619                "type": "Number"
19620            },
19621            "class": "p5.SoundFile",
19622            "module": "p5.sound",
19623            "submodule": "p5.sound"
19624        },
19625        {
19626            "file": "lib/addons/p5.sound.js",
19627            "line": 1548,
19628            "description": "<p>Return the sample rate of the sound file.</p>\n",
19629            "itemtype": "method",
19630            "name": "sampleRate",
19631            "return": {
19632                "description": "[sampleRate]",
19633                "type": "Number"
19634            },
19635            "class": "p5.SoundFile",
19636            "module": "p5.sound",
19637            "submodule": "p5.sound"
19638        },
19639        {
19640            "file": "lib/addons/p5.sound.js",
19641            "line": 1557,
19642            "description": "<p>Return the number of samples in a sound file.\nEqual to sampleRate * duration.</p>\n",
19643            "itemtype": "method",
19644            "name": "frames",
19645            "return": {
19646                "description": "[sampleCount]",
19647                "type": "Number"
19648            },
19649            "class": "p5.SoundFile",
19650            "module": "p5.sound",
19651            "submodule": "p5.sound"
19652        },
19653        {
19654            "file": "lib/addons/p5.sound.js",
19655            "line": 1567,
19656            "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",
19657            "itemtype": "method",
19658            "name": "getPeaks",
19659            "params": [
19660                {
19661                    "name": "length",
19662                    "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",
19663                    "type": "Number",
19664                    "optional": true
19665                }
19666            ],
19667            "return": {
19668                "description": "Array of peaks.",
19669                "type": "Float32Array"
19670            },
19671            "class": "p5.SoundFile",
19672            "module": "p5.sound",
19673            "submodule": "p5.sound"
19674        },
19675        {
19676            "file": "lib/addons/p5.sound.js",
19677            "line": 1619,
19678            "description": "<p>Reverses the p5.SoundFile&#39;s buffer source.\nPlayback must be handled separately (see example).</p>\n",
19679            "itemtype": "method",
19680            "name": "reverseBuffer",
19681            "example": [
19682                "\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>"
19683            ],
19684            "class": "p5.SoundFile",
19685            "module": "p5.sound",
19686            "submodule": "p5.sound"
19687        },
19688        {
19689            "file": "lib/addons/p5.sound.js",
19690            "line": 1659,
19691            "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",
19692            "itemtype": "method",
19693            "name": "onended",
19694            "params": [
19695                {
19696                    "name": "callback",
19697                    "description": "<p>function to call when the\n                            soundfile has ended.</p>\n",
19698                    "type": "Function"
19699                }
19700            ],
19701            "class": "p5.SoundFile",
19702            "module": "p5.sound",
19703            "submodule": "p5.sound"
19704        },
19705        {
19706            "file": "lib/addons/p5.sound.js",
19707            "line": 1712,
19708            "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",
19709            "itemtype": "method",
19710            "name": "connect",
19711            "params": [
19712                {
19713                    "name": "object",
19714                    "description": "<p>Audio object that accepts an input</p>\n",
19715                    "type": "Object",
19716                    "optional": true
19717                }
19718            ],
19719            "class": "p5.SoundFile",
19720            "module": "p5.sound",
19721            "submodule": "p5.sound"
19722        },
19723        {
19724            "file": "lib/addons/p5.sound.js",
19725            "line": 1733,
19726            "description": "<p>Disconnects the output of this p5sound object.</p>\n",
19727            "itemtype": "method",
19728            "name": "disconnect",
19729            "class": "p5.SoundFile",
19730            "module": "p5.sound",
19731            "submodule": "p5.sound"
19732        },
19733        {
19734            "file": "lib/addons/p5.sound.js",
19735            "line": 1741,
19736            "class": "p5.SoundFile",
19737            "module": "p5.sound",
19738            "submodule": "p5.sound"
19739        },
19740        {
19741            "file": "lib/addons/p5.sound.js",
19742            "line": 1746,
19743            "description": "<p>
19743Reset the source for this SoundFile to a\nnew path (URL).</p>\n",
19744            "itemtype": "method",
19745            "name": "setPath",
19746            "params": [
19747                {
19748                    "name": "path",
19749                    "description": "<p>path to audio file</p>\n",
19750                    "type": "String"
19751                },
19752                {
19753                    "name": "callback",
19754                    "description": "<p>Callback</p>\n",
19755                    "type": "Function"
19756                }
19757            ],
19758            "class": "p5.SoundFile",
19759            "module": "p5.sound",
19760            "submodule": "p5.sound"
19761        },
19762        {
19763            "file": "lib/addons/p5.sound.js",
19764            "line": 1759,
19765            "description": "<p>Replace the current Audio Buffer with a new Buffer.</p>\n",
19766            "itemtype": "method",
19767            "name": "setBuffer",
19768            "params": [
19769                {
19770                    "name": "buf",
19771                    "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",
19772                    "type": "Array"
19773                }
19774            ],
19775            "class": "p5.SoundFile",
19776            "module": "p5.sound",
19777            "submodule": "p5.sound"
19778        },
19779        {
19780            "file": "lib/addons/p5.sound.js",
19781            "line": 1831,
19782            "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",
19783            "itemtype": "method",
19784            "name": "processPeaks",
19785            "params": [
19786                {
19787                    "name": "callback",
19788                    "description": "<p>a function to call once this data is returned</p>\n",
19789                    "type": "Function"
19790                },
19791                {
19792                    "name": "initThreshold",
19793                    "description": "<p>initial threshold defaults to 0.9</p>\n",
19794                    "type": "Number",
19795                    "optional": true
19796                },
19797                {
19798                    "name": "minThreshold",
19799                    "description": "<p>minimum threshold defaults to 0.22</p>\n",
19800                    "type": "Number",
19801                    "optional": true
19802                },
19803                {
19804                    "name": "minPeaks",
19805                    "description": "<p>minimum number of peaks defaults to 200</p>\n",
19806                    "type": "Number",
19807                    "optional": true
19808                }
19809            ],
19810            "return": {
19811                "description": "Array of timestamped peaks",
19812                "type": "Array"
19813            },
19814            "class": "p5.SoundFile",
19815            "module": "p5.sound",
19816            "submodule": "p5.sound"
19817        },
19818        {
19819            "file": "lib/addons/p5.sound.js",
19820            "line": 2022,
19821            "class": "p5.SoundFile",
19822            "module": "p5.sound",
19823            "submodule": "p5.sound"
19824        },
19825        {
19826            "file": "lib/addons/p5.sound.js",
19827            "line": 2031,
19828            "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",
19829            "itemtype": "method",
19830            "name": "addCue",
19831            "params": [
19832                {
19833                    "name": "time",
19834                    "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",
19835                    "type": "Number"
19836                },
19837                {
19838                    "name": "callback",
19839                    "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",
19840                    "type": "Function"
19841                },
19842                {
19843                    "name": "value",
19844                    "description": "<p>An object to be passed as the\n                           second parameter to the\n                           callback function.</p>\n",
19845                    "type": "Object",
19846                    "optional": true
19847                }
19848            ],
19849            "return": {
19850                "description": "id ID of this cue,\n                    useful for removeCue(id)",
19851                "type": "Number"
19852            },
19853            "example": [
19854                "\n<div><code>\nfunction setup() {\n  background(0);\n  noStroke();\n  fill(255);\n  textAlign(CENTER);\n  text('click to play', width/2, height/2);\n\n  mySound = loadSound('assets/beat.mp3');\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\" );
19854\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>"
19855            ],
19856            "class": "p5.SoundFile",
19857            "module": "p5.sound",
19858            "submodule": "p5.sound"
19859        },
19860        {
19861            "file": "lib/addons/p5.sound.js",
19862            "line": 2106,
19863            "description": "<p>Remove a callback based on its ID. The ID is returned by the\naddCue method.</p>\n",
19864            "itemtype": "method",
19865            "name": "removeCue",
19866            "params": [
19867                {
19868                    "name": "id",
19869                    "description": "<p>ID of the cue, as returned by addCue</p>\n",
19870                    "type": "Number"
19871                }
19872            ],
19873            "class": "p5.SoundFile",
19874            "module": "p5.sound",
19875            "submodule": "p5.sound"
19876        },
19877        {
19878            "file": "lib/addons/p5.sound.js",
19879            "line": 2124,
19880            "description": "<p>Remove all of the callbacks that had originally been scheduled\nvia the addCue method.</p>\n",
19881            "itemtype": "method",
19882            "name": "clearCues",
19883            "class": "p5.SoundFile",
19884            "module": "p5.sound",
19885            "submodule": "p5.sound"
19886        },
19887        {
19888            "file": "lib/addons/p5.sound.js",
19889            "line": 2232,
19890            "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",
19891            "itemtype": "method",
19892            "name": "setInput",
19893            "params": [
19894                {
19895                    "name": "snd",
19896                    "description": "<p>set the sound source\n                                     (optional, defaults to\n                                     master output)</p>\n",
19897                    "type": "SoundObject|undefined",
19898                    "optional": true
19899                },
19900                {
19901                    "name": "smoothing",
19902                    "description": "<p>a range between 0.0 and 1.0\n                                      to smooth amplitude readings</p>\n",
19903                    "type": "Number|undefined",
19904                    "optional": true
19905                }
19906            ],
19907            "example": [
19908                "\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>"
19909            ],
19910            "class": "p5.Amplitude",
19911            "module": "p5.sound",
19912            "submodule": "p5.sound"
19913        },
19914        {
19915            "file": "lib/addons/p5.sound.js",
19916            "line": 2337,
19917            "description": "<p>Returns a single Amplitude reading at the moment it is called.\nFor continuous readings, run in the draw loop.</p>\n",
19918            "itemtype": "method",
19919            "name": "getLevel",
19920            "params": [
19921                {
19922                    "name": "channel",
19923                    "description": "<p>Optionally return only channel 0 (left) or 1 (right)</p>\n",
19924                    "type": "Number",
19925                    "optional": true
19926                }
19927            ],
19928            "return": {
19929                "description": "Amplitude as a number between 0.0 and 1.0",
19930                "type": "Number"
19931            },
19932            "example": [
19933                "\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>"
19934            ],
19935            "class": "p5.Amplitude",
19936            "module": "p5.sound",
19937            "submodule": "p5.sound"
19938        },
19939        {
19940            "file": "lib/addons/p5.sound.js",
19941            "line": 2378,
19942            "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",
19943            "itemtype": "method",
19944            "name": "toggleNormalize",
19945            "params": [
19946                {
19947                    "name": "boolean",
19948                    "description": "<p>set normalize to true (1) or false (0)</p>\n",
19949                    "type": "Boolean",
19950                    "optional": true
19951                }
19952            ],
19953            "class": "p5.Amplitude",
19954            "module": "p5.sound",
19955            "submodule": "p5.sound"
19956        },
19957        {
19958            "file": "lib/addons/p5.sound.js",
19959            "line": 2398,
19960            "description": "<p>Smooth Amplitude analysis by averaging with the last analysis\nframe. Off by default.</p>\n",
19961            "itemtype": "method",
19962            "name": "smooth",
19963            "params": [
19964                {
19965                    "name": "set",
19966                    "description": "<p>smoothing from 0.0 &lt;= 1</p>\n",
19967                    "type": "Number"
19968                }
19969            ],
19970            "class": "p5.Amplitude",
19971            "module": "p5.sound",
19972            "submodule": "p5.sound"
19973        },
19974        {
19975            "file": "lib/addons/p5.sound.js",
19976            "line": 2567,
19977            "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",
19978            "itemtype": "method",
19979            "name": "setInput",
19980            "params": [
19981                {
19982                    "name": "source",
19983                    "description": "<p>p5.sound object (or web audio API source node)</p>\n",
19984                    "type": "Object",
19985                    "optional": true
19986                }
19987            ],
19988            "class": "p5.FFT",
19989            "module": "p5.sound",
19990            "submodule": "p5.sound"
19991        },
19992        {
19993            "file": "lib/addons/p5.sound.js",
19994            "line": 2586,
19995            "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",
19996            "itemtype": "method",
19997            "name": "waveform",
19998            "params": [
19999                {
20000                    "name": "bins",
20001                    "description": "<p>Must be a power of two between\n                          16 and 1024. Defaults to 1024.</p>\n",
20002                    "type": "Number",
20003                    "optional": true
20004                },
20005                {
20006                    "name": "precision",
20007                    "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",
20008                    "type": "String",
20009                    "optional": true
20010                }
20011            ],
20012            "return": {
20013                "description": "Array    Array of amplitude values (-1 to 1)\n                          over time. Array length = bins.",
20014                "type": "Array"
20015            },
20016            "class": "p5.FFT",
20017            "module": "p5.sound",
20018            "submodule": "p5.sound"
20019        },
20020        {
20021            "file": "lib/addons/p5.sound.js",
20022            "line": 2629,
20023            "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",
20024            "itemtype": "method",
20025            "name": "analyze",
20026            "params": [
20027                {
20028                    "name": "bins",
20029                    "description": "<p>Must be a power of two between\n                           16 and 1024. Defaults to 1024.</p>\n",
20030                    "type": "Number",
20031                    "optional": true
20032                },
20033                {
20034                    "name": "scale",
20035                    "description": "<p>If &quot;dB,&quot; returns decibel\n                           float measurements between\n                           -14
200350 and 0 (max).\n                           Otherwise returns integers from 0-255.</p>\n",
20036                    "type": "Number",
20037                    "optional": true
20038                }
20039            ],
20040            "return": {
20041                "description": "spectrum    Array of energy (amplitude/volume)\n                            values across the frequency spectrum.\n                            Lowest energy (silence) = 0, highest\n                            possible is 255.",
20042                "type": "Array"
20043            },
20044            "example": [
20045                "\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"
20046            ],
20047            "class": "p5.FFT",
20048            "module": "p5.sound",
20049            "submodule": "p5.sound"
20050        },
20051        {
20052            "file": "lib/addons/p5.sound.js",
20053            "line": 2721,
20054            "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",
20055            "itemtype": "method",
20056            "name": "getEnergy",
20057            "params": [
20058                {
20059                    "name": "frequency1",
20060                    "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",
20061                    "type": "Number|String"
20062                },
20063                {
20064                    "name": "frequency2",
20065                    "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",
20066                    "type": "Number",
20067                    "optional": true
20068                }
20069            ],
20070            "return": {
20071                "description": "Energy   Energy (volume/amplitude) from\n                            0 and 255.",
20072                "type": "Number"
20073            },
20074            "class": "p5.FFT",
20075            "module": "p5.sound",
20076            "submodule": "p5.sound"
20077        },
20078        {
20079            "file": "lib/addons/p5.sound.js",
20080            "line": 2803,
20081            "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",
20082            "itemtype": "method",
20083            "name": "getCentroid",
20084            "return": {
20085                "description": "Spectral Centroid Frequency   Frequency of the spectral centroid in Hz.",
20086                "type": "Number"
20087            },
20088            "example": [
20089                "\n<div><code>\n\n\nfunction setup(){\ncnv = createCanvas(800,400);\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\n\nfor (var i = 0; i< spectrum.length; i++){\n  var x = map(log(i), 0, log(spectrum.length), 0, width);
20089\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\ntextSize(40);\ntext(\"centroid: \"+round(spectralCentroid)+\" Hz\", 10, 40);\n}\n </code></div>"
20090            ],
20091            "class": "p5.FFT",
20092            "module": "p5.sound",
20093            "submodule": "p5.sound"
20094        },
20095        {
20096            "file": "lib/addons/p5.sound.js",
20097            "line": 2884,
20098            "description": "<p>Smooth FFT analysis by averaging with the last analysis frame.</p>\n",
20099            "itemtype": "method",
20100            "name": "smooth",
20101            "params": [
20102                {
20103                    "name": "smoothing",
20104                    "description": "<p>0.0 &lt; smoothing &lt; 1.0.\n                             Defaults to 0.8.</p>\n",
20105                    "type": "Number"
20106                }
20107            ],
20108            "class": "p5.FFT",
20109            "module": "p5.sound",
20110            "submodule": "p5.sound"
20111        },
20112        {
20113            "file": "lib/addons/p5.sound.js",
20114            "line": 2904,
20115            "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",
20116            "itemtype": "method",
20117            "name": "linAverages",
20118            "params": [
20119                {
20120                    "name": "N",
20121                    "description": "<p>Number of returned frequency groups</p>\n",
20122                    "type": "Number"
20123                }
20124            ],
20125            "return": {
20126                "description": "linearAverages   Array of average amplitude values for each group",
20127                "type": "Array"
20128            },
20129            "class": "p5.FFT",
20130            "module": "p5.sound",
20131            "submodule": "p5.sound"
20132        },
20133        {
20134            "file": "lib/addons/p5.sound.js",
20135            "line": 2934,
20136            "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",
20137            "itemtype": "method",
20138            "name": "logAverages",
20139            "params": [
20140                {
20141                    "name": "octaveBands",
20142                    "description": "<p>Array of Octave Bands objects for grouping</p>\n",
20143                    "type": "Array"
20144                }
20145            ],
20146            "return": {
20147                "description": "logAverages    Array of average amplitude values for each group",
20148                "type": "Array"
20149            },
20150            "class": "p5.FFT",
20151            "module": "p5.sound",
20152            "submodule": "p5.sound"
20153        },
20154        {
20155            "file": "lib/addons/p5.sound.js",
20156            "line": 2964,
20157            "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",
20158            "itemtype": "method",
20159            "name": "getOctaveBands",
20160            "params": [
20161                {
20162                    "name": "N",
20163                    "description": "<p>Specifies the 1/N type of generated octave bands</p>\n",
20164                    "type": "Number"
20165                },
20166                {
20167                    "name": "fCtr0",
20168                    "description": "<p>Minimum central frequency for the lowest band</p>\n",
20169                    "type": "Number"
20170                }
20171            ],
20172            "return": {
20173                "description": "octaveBands   Array of octave band objects with their bounds",
20174                "type": "Array"
20175            },
20176            "class": "p5.FFT",
20177            "module": "p5.sound",
20178            "submodule": "p5.sound"
20179        },
20180        {
20181            "file": "lib/addons/p5.sound.js",
20182            "line": 3022,
20183            "class": "p5.FFT",
20184            "module": "p5.sound",
20185            "submodule": "p5.sound"
20186        },
20187        {
20188            "file": "lib/addons/p5.sound.js",
20189            "line": 3399,
20190            "class": "p5.FFT",
20191            "module": "p5.sound",
20192            "submodule": "p5.sound"
20193        },
20194        {
20195            "file": "lib/addons/p5.sound.js",
20196            "line": 3420,
20197            "class": "p5.FFT",
20198            "module": "p5.sound",
20199            "submodule": "p5.sound"
20200        },
20201        {
20202            "file": "lib/addons/p5.sound.js",
20203            "line": 3479,
20204            "class": "p5.FFT",
20205            "module": "p5.sound",
20206            "submodule": "p5.sound"
20207        },
20208        {
20209            "file": "lib/addons/p5.sound.js",
20210            "line": 3797,
20211            "class": "p5.FFT",
20212            "module": "p5.sound",
20213            "submodule": "p5.sound"
20214        },
20215        {
20216            "file": "lib/addons/p5.sound.js",
20217            "line": 3969,
20218            "class": "p5.FFT",
20219            "module": "p5.sound",
20220            "submodule": "p5.sound"
20221        },
20222        {
20223            "file": "lib/addons/p5.sound.js",
20224            "line": 4127,
20225            "class": "p5.FFT",
20226            "module": "p5.sound",
20227            "submodule": "p5.sound"
20228        },
20229        {
20230            "file": "lib/addons/p5.sound.js",
20231            "line": 4168,
20232            "class": "p5.FFT",
20233            "module": "p5.sound",
20234            "submodule": "p5.sound"
20235        },
20236        {
20237            "file": "lib/addons/p5.sound.js",
20238            "line": 4238,
20239            "class": "p5.FFT",
20240            "module": "p5.sound",
20241            "submodule": "p5.sound"
20242        },
20243        {
20244            "file": "lib/addons/p5.sound.js",
20245            "line": 4426,
20246            "class": "p5.FFT",
20247            "module": "p5.sound",
20248            "submodule": "p5.sound"
20249        },
20250        {
20251            "file": "lib/addons/p5.sound.js",
20252            "line": 4483,
20253            "class": "p5.FFT",
20254            "module": "p5.sound",
20255            "submodule": "p5.sound"
20256        },
20257        {
20258            "file": "lib/addons/p5.sound.js",
20259            "line": 4651,
20260            "class": "p5.FFT",
20261            "module": "p5.sound",
20262            "submodule": "p5.sound"
20263        },
20264        {
20265            "file": "lib/addons/p5.sound.js",
20266            "line": 4699,
20267            "class": "p5.FFT",
20268            "module": "p5.sound",
20269            "submodule": "p5.sound"
20270        },
20271        {
20272            "file": "lib/addons/p5.sound.js",
20273            "line": 4730,
20274            "class": "p5.FFT",
20275            "module": "p5.sound",
20276            "submodule": "p5.sound"
20277        },
20278        {
20279            "file": "lib/addons/p5.sound.js",
20280            "line": 4751,
20281            "class": "p5.FFT",
20282            "module": "p5.sound",
20283            "submodule": "p5.sound"
20284        },
20285        {
20286            "file": "lib/addons/p5.sound.js",
20287            "line": 4771,
20288            "class": "p5.FFT",
20289            "module": "p5.sound",
20290            "submodule": "p5.sound"
20291        },
20292        {
20293            "file": "lib/addons/p5.sound.js",
20294            "line": 4873,
20295            "description": "<p>Fade to value, for smooth transitions</p>\n",
20296            "itemtype": "method",
20297            "name": "fade",
20298            "params": [
20299                {
20300                    "name": "value",
20301                    "description": "<p>Value to set this signal</p>\n",
20302                    "type": "Number"
20303                },
20304                {
20305                    "name": "secondsFromNow",
20306                    "description": "<p>Length of fade, in seconds from now</p>\n",
20307                    "type": "Number",
20308                    "optional": true
20309                }
20310            ],
20311            "class": "p5.Signal",
20312            "module": "p5.sound",
20313            "submodule": "p5.sound"
20314        },
20315        {
20316            "file": "lib/addons/p5.sound.js",
20317            "line": 4884,
20318            "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",
20319            "itemtype": "method",
20320            "name": "setInput",
20321            "params": [
20322                {
20323                    "name": "input",
20324                    "description": "",
20325                    "type": "Object"
20326                }
20327            ],
20328            "class": "p5.Signal",
20329            "module": "p5.sound",
20330            "submodule": "p5.sound"
20331        },
20332        {
20333            "file": "lib/addons/p5.sound.js",
20334            "line": 4898,
20335            "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",
20336            "itemtype": "method",
20337            "name": "add",
20338            "params": [
20339                {
20340                    "name": "number",
20341                    "description": "",
20342                    "type": "Number"
20343                }
20344            ],
20345            "return": {
20346                "description": "object",
20347                "type": "p5.Signal"
20348            },
20349            "class": "p5.Signal",
20350            "module": "p5.sound",
20351            "submodule": "p5.sound"
20352        },
20353        {
20354            "file": "lib/addons/p5.sound.js",
20355            "line": 4917,
20356            "description": "<p>
20356Multiply 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",
20357            "itemtype": "method",
20358            "name": "mult",
20359            "params": [
20360                {
20361                    "name": "number",
20362                    "description": "<p>to multiply</p>\n",
20363                    "type": "Number"
20364                }
20365            ],
20366            "return": {
20367                "description": "object",
20368                "type": "p5.Signal"
20369            },
20370            "class": "p5.Signal",
20371            "module": "p5.sound",
20372            "submodule": "p5.sound"
20373        },
20374        {
20375            "file": "lib/addons/p5.sound.js",
20376            "line": 4936,
20377            "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",
20378            "itemtype": "method",
20379            "name": "scale",
20380            "params": [
20381                {
20382                    "name": "number",
20383                    "description": "<p>to multiply</p>\n",
20384                    "type": "Number"
20385                },
20386                {
20387                    "name": "inMin",
20388                    "description": "<p>input range minumum</p>\n",
20389                    "type": "Number"
20390                },
20391                {
20392                    "name": "inMax",
20393                    "description": "<p>input range maximum</p>\n",
20394                    "type": "Number"
20395                },
20396                {
20397                    "name": "outMin",
20398                    "description": "<p>input range minumum</p>\n",
20399                    "type": "Number"
20400                },
20401                {
20402                    "name": "outMax",
20403                    "description": "<p>input range maximum</p>\n",
20404                    "type": "Number"
20405                }
20406            ],
20407            "return": {
20408                "description": "object",
20409                "type": "p5.Signal"
20410            },
20411            "class": "p5.Signal",
20412            "module": "p5.sound",
20413            "submodule": "p5.sound"
20414        },
20415        {
20416            "file": "lib/addons/p5.sound.js",
20417            "line": 5070,
20418            "description": "<p>Start an oscillator. Accepts an optional parameter to\ndetermine how long (in seconds from now) until the\noscillator starts.</p>\n",
20419            "itemtype": "method",
20420            "name": "start",
20421            "params": [
20422                {
20423                    "name": "time",
20424                    "description": "<p>startTime in seconds from now.</p>\n",
20425                    "type": "Number",
20426                    "optional": true
20427                },
20428                {
20429                    "name": "frequency",
20430                    "description": "<p>frequency in Hz.</p>\n",
20431                    "type": "Number",
20432                    "optional": true
20433                }
20434            ],
20435            "class": "p5.Oscillator",
20436            "module": "p5.sound",
20437            "submodule": "p5.sound"
20438        },
20439        {
20440            "file": "lib/addons/p5.sound.js",
20441            "line": 5110,
20442            "description": "<p>Stop an oscillator. Accepts an optional parameter\nto determine how long (in seconds from now) until the\noscillator stops.</p>\n",
20443            "itemtype": "method",
20444            "name": "stop",
20445            "params": [
20446                {
20447                    "name": "secondsFromNow",
20448                    "description": "<p>Time, in seconds from now.</p>\n",
20449                    "type": "Number"
20450                }
20451            ],
20452            "class": "p5.Oscillator",
20453            "module": "p5.sound",
20454            "submodule": "p5.sound"
20455        },
20456        {
20457            "file": "lib/addons/p5.sound.js",
20458            "line": 5126,
20459            "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",
20460            "itemtype": "method",
20461            "name": "amp",
20462            "params": [
20463                {
20464                    "name": "vol",
20465                    "description": "<p>between 0 and 1.0\n                            or a modulating signal/oscillator</p>\n",
20466                    "type": "Number|Object"
20467                },
20468                {
20469                    "name": "rampTime",
20470                    "description": "<p>create a fade that lasts rampTime</p>\n",
20471                    "type": "Number",
20472                    "optional": true
20473                },
20474                {
20475                    "name": "timeFromNow",
20476                    "description": "<p>schedule this event to happen\n                              seconds from now</p>\n",
20477                    "type": "Number",
20478                    "optional": true
20479                }
20480            ],
20481            "return": {
20482                "description": "gain  If no value is provided,\n                            returns the Web Audio API\n                            AudioParam that c
20482ontrols\n                            this oscillator's\n                            gain/amplitude/volume)",
20483                "type": "AudioParam"
20484            },
20485            "class": "p5.Oscillator",
20486            "module": "p5.sound",
20487            "submodule": "p5.sound"
20488        },
20489        {
20490            "file": "lib/addons/p5.sound.js",
20491            "line": 5161,
20492            "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",
20493            "itemtype": "method",
20494            "name": "freq",
20495            "params": [
20496                {
20497                    "name": "Frequency",
20498                    "description": "<p>Frequency in Hz\n                                      or modulating signal/oscillator</p>\n",
20499                    "type": "Number|Object"
20500                },
20501                {
20502                    "name": "rampTime",
20503                    "description": "<p>Ramp time (in seconds)</p>\n",
20504                    "type": "Number",
20505                    "optional": true
20506                },
20507                {
20508                    "name": "timeFromNow",
20509                    "description": "<p>Schedule this event to happen\n                                 at x seconds from now</p>\n",
20510                    "type": "Number",
20511                    "optional": true
20512                }
20513            ],
20514            "return": {
20515                "description": "Frequency If no value is provided,\n                                returns the Web Audio API\n                                AudioParam that controls\n                                this oscillator's frequency",
20516                "type": "AudioParam"
20517            },
20518            "example": [
20519                "\n<div><code>\nvar osc = new p5.Oscillator(300);\nosc.start();\nosc.freq(40, 10);\n</code></div>"
20520            ],
20521            "class": "p5.Oscillator",
20522            "module": "p5.sound",
20523            "submodule": "p5.sound"
20524        },
20525        {
20526            "file": "lib/addons/p5.sound.js",
20527            "line": 5220,
20528            "description": "<p>Set type to &#39;sine&#39;, &#39;triangle&#39;, &#39;sawtooth&#39; or &#39;square&#39;.</p>\n",
20529            "itemtype": "method",
20530            "name": "setType",
20531            "params": [
20532                {
20533                    "name": "type",
20534                    "description": "<p>&#39;sine&#39;, &#39;triangle&#39;, &#39;sawtooth&#39; or &#39;square&#39;.</p>\n",
20535                    "type": "String"
20536                }
20537            ],
20538            "class": "p5.Oscillator",
20539            "module": "p5.sound",
20540            "submodule": "p5.sound"
20541        },
20542        {
20543            "file": "lib/addons/p5.sound.js",
20544            "line": 5232,
20545            "description": "<p>Connect to a p5.sound / Web Audio object.</p>\n",
20546            "itemtype": "method",
20547            "name": "connect",
20548            "params": [
20549                {
20550                    "name": "unit",
20551                    "description": "<p>A p5.sound or Web Audio object</p>\n",
20552                    "type": "Object"
20553                }
20554            ],
20555            "class": "p5.Oscillator",
20556            "module": "p5.sound",
20557            "submodule": "p5.sound"
20558        },
20559        {
20560            "file": "lib/addons/p5.sound.js",
20561            "line": 5249,
20562            "description": "<p>Disconnect all outputs</p>\n",
20563            "itemtype": "method",
20564            "name": "disconnect",
20565            "class": "p5.Oscillator",
20566            "module": "p5.sound",
20567            "submodule": "p5.sound"
20568        },
20569        {
20570            "file": "lib/addons/p5.sound.js",
20571            "line": 5260,
20572            "description": "<p>Pan between Left (-1) and Right (1)</p>\n",
20573            "itemtype": "method",
20574            "name": "pan",
20575            "params": [
20576                {
20577                    "name": "panning",
20578                    "description": "<p>Number between -1 and 1</p>\n",
20579                    "type": "Number"
20580                },
20581                {
20582                    "name": "timeFromNow",
20583                    "description": "<p>schedule this event to happen\n                              seconds from now</p>\n",
20584                    "type": "Number"
20585                }
20586            ],
20587            "class": "p5.Oscillator",
20588            "module": "p5.sound",
20589            "submodule": "p5.sound"
20590        },
20591        {
20592            "file": "lib/addons/p5.sound.js",
20593            "line": 5292,
20594            "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",
20595            "itemtype": "method",
20596            "name": "phase",
20597            "params": [
20598                {
20599                    "name": "phase",
20600                    "description": "<p>float between 0.0 and 1.0</p>\n",
20601                    "type": "Number"
20602                }
20603            ],
20604            "class": "p5.Oscillator",
20605            "module": "p5.sound",
20606            "submodule": "p5.sound"
20607        },
20608        {
20609            "file": "lib/addons/p5.sound.js",
20610            "line": 5346,
20611            "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",
20612            "itemtype": "method",
20613            "name": "add",
20614            "params": [
20615                {
20616                    "name": "number",
20617                    "description": "<p>Constant number to add</p>\n",
20618                    "type": "Number"
20619                }
20620            ],
20621            "return": {
20622                "description": "Oscillator Returns this oscillator\n                                   with scaled output",
20623                "type": "p5.Oscillator"
20624            },
20625            "class": "p5.Oscillator",
20626            "module": "p5.sound",
20627            "submodule": "p5.sound"
20628        },
20629        {
20630            "file": "lib/addons/p5.sound.js",
20631            "line": 5363,
20632            "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",
20633            "itemtype": "method",
20634            "name": "mult",
20635            "params": [
20636                {
20637                    "name": "number",
20638                    "description": "<p>Constant number to multiply</p>\n",
20639                    "type": "Number"
20640                }
20641            ],
20642            "return": {
20643                "description": "Oscillator Returns this oscillator\n                                   with multiplied output",
20644                "type": "p5.Oscillator"
20645            },
20646            "class": "p5.Oscillator",
20647            "module": "p5.sound",
20648            "submodule": "p5.sound"
20649        },
20650        {
20651            "file": "lib/addons/p5.sound.js",
20652            "line": 5379,
20653            "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",
20654            "itemtype": "method",
20655            "name": "scale",
20656            "params": [
20657                {
20658                    "name": "inMin",
20659                    "description": "<p>input range minumum</p>\n",
20660                    "type": "Number"
20661                },
20662                {
20663                    "name": "inMax",
20664                    "description": "<p>input range maximum</p>\n",
20665                    "type": "Number"
20666                },
20667                {
20668                    "name": "outMin",
20669                    "description": "<p>input range minumum</p>\n",
20670                    "type": "Number"
20671                },
20672                {
20673                    "name": "outMax",
20674                    "description": "<p>input range maximum</p>\n",
20675                    "type": "Number"
20676                }
20677            ],
20678            "return": {
20679                "description": "Oscillator Returns this oscillator\n                                   with scaled output",
20680                "type": "p5.Oscillator"
20681            },
20682            "class": "p5.Oscillator",
20683            "module": "p5.sound",
20684            "submodule": "p5.sound"
20685        },
20686        {
20687            "file": "lib/addons/p5.sound.js",
20688            "line": 5478,
20689            "class": "p5.SqrOsc",
20690            "module": "p5.sound",
20691            "submodule": "p5.sound"
20692        },
20693        {
20694            "file": "lib/addons/p5.sound.js",
20695            "line": 5681,
20696            "class": "p5.SqrOsc",
20697            "module": "p5.sound",
20698            "submodule": "p5.sound"
20699        },
20700        {
20701            "file": "lib/addons/p5.sound.js",
20702            "line": 5970,
20703            "description": "<p>Time until envelope reaches attackLevel</p>\n",
20704            "itemtype": "property",
20705            "name": "attackTime",
20706            "class": "p5.Env",
20707            "module": "p5.sound",
20708            "submodule": "p5.sound"
20709        },
20710        {
20711            "file": "lib/addons/p5.sound.js",
20712            "line": 5975,
20713            "description": "<p>Level once attack is complete.</p>\n",
20714            "itemtype": "property",
20715            "name": "attackLevel",
20716            "class": "p5.Env",
20717            "module": "p5.sound",
20718            "submodule": "p5.sound"
20719        },
20720        {
20721            "file": "lib/addons/p5.sound.js",
20722            "line": 5980,
20723            "description": "<p>Time until envelope reaches decayLevel.</p>\n",
20724            "itemtype": "property",
20725            "name": "decayTime",
20726            "class": "p5.Env",
20727            "module": "p5.sound",
20728            "submodule": "p5.sound"
20729        },
20730        {
20731            "file": "lib/addons/p5.sound.js",
20732            "line": 5985,
20733            "description": "<p>Level after decay. The envelope will sustain here until it is released.</p>\n",
20734            "itemtype": "property",
20735            "name": "decayLevel",
20736            "class": "p5.Env",
20737            "module": "p5.sound",
20738            "submodule": "p5.sound"
20739        },
20740        {
20741            "file": "lib/addons/p5.sound.js",
20742            "line": 5990,
20743            "description": "<p>Duration of the release portion of the envelope.</p>\n",
20744            "itemtype": "property",
20745            "name": "releaseTime",
20746            "class": "p5.Env",
20747            "module": "p5.sound",
20748            "submodule": "p5.sound"
20749        },
20750        {
20751            "file": "lib/addons/p5.sound.js",
20752            "line": 5995,
20753            "description": "<p>Level at the end of the release.</p>\n",
20754            "itemtype": "property",
20755            "name": "releaseLevel",
20756            "class": "p5.Env",
20757            "module": "p5.sound",
20758            "submodule": "p5.sound"
20759        },
20760        {
20761            "file": "lib/addons/p5.sound.js",
20762            "line": 6031,
20763            "description": "<p>Reset the envelope with a series of time/value pairs.</p>\n",
20764            "itemtype": "method",
20765            "name": "set",
20766            "params": [
20767                {
20768                    "name": "attackTime",
20769                    "description": "<p>Time (in seconds) before level\n                               reaches attackLevel</p>\n",
20770                    "type": "Number"
20771                },
20772                {
20773                    "name": "attackLevel",
20774                    "description": "<p>Typically an amplitude between\n                               0.0 and 1.0</p>\n",
20775                    "type": "Number"
20776                },
20777                {
20778                    "name": "decayTime",
20779                    "description": "<p>Time</p>\n",
20780                    "type": "Number"
20781                },
20782                {
20783                    "name": "decayLevel",
20784                    "description": "<p>Amplitude (In a standard ADSR envelope,\n                               decayLevel = sustainLevel)</p>\n",
20785                    "type": "Number"
20786                },
20787                {
20788                    "name": "releaseTime",
20789                    "description": "<p>Release Time (in seconds)</p>\n",
20790                    "type": "Number"
20791                },
20792                {
20793                    "name": "releaseLevel",
20794                    "description": "<p>Amplitude</p>\n",
20795                    "type": "Number"
20796                }
20797            ],
20798            "example": [
20799                "\n<div><code>\nvar t1 = 0.1;
20799 // 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.2; // 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.Env(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"
20800            ],
20801            "class": "p5.Env",
20802            "module": "p5.sound",
20803            "submodule": "p5.sound"
20804        },
20805        {
20806            "file": "lib/addons/p5.sound.js",
20807            "line": 6090,
20808            "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",
20809            "itemtype": "method",
20810            "name": "setADSR",
20811            "params": [
20812                {
20813                    "name": "attackTime",
20814                    "description": "<p>Time (in seconds before envelope\n                              reaches Attack Level</p>\n",
20815                    "type": "Number"
20816                },
20817                {
20818                    "name": "decayTime",
20819                    "description": "<p>Time (in seconds) before envelope\n                              reaches Decay/Sustain Level</p>\n",
20820                    "type": "Number",
20821                    "optional": true
20822                },
20823                {
20824                    "name": "susRatio",
20825                    "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",
20826                    "type": "Number",
20827                    "optional": true
20828                },
20829                {
20830                    "name": "releaseTime",
20831                    "description": "<p>Time in seconds from now (defaults to 0)</p>\n",
20832                    "type": "Number",
20833                    "optional": true
20834                }
20835            ],
20836            "example": [
20837                "\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.Env();\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>"
20838            ],
20839            "class": "p5.Env",
20840            "module": "p5.sound",
20841            "submodule": "p5.sound"
20842        },
20843        {
20844            "file": "lib/addons/p5.sound.js",
20845            "line": 6155,
20846            "description": "<p>Set max (attackLevel) and min (releaseLevel) of envelope.</p>\n",
20847            "itemtype": "method",
20848            "name": "setRange",
20849            "params": [
20850                {
20851                    "name": "aLevel",
20852                    "description": "<p>attack level (defaults to 1)</p>\n",
20853                    "type": "Number"
20854                },
20855                {
20856                    "name": "rLevel",
20857                    "description": "<p>release level (defaults to 0)</p>\n",
20858                    "type": "Number"
20859                }
20860            ],
20861            "example": [
20862                "\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.Env();\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>"
20863            ],
20864            "class": "p5.Env",
20865            "module": "p5.sound",
20866            "submodule": "p5.sound"
20867        },
20868        {
20869            "file": "lib/addons/p5.sound.js",
20870            "line": 6234,
20871            "description": "<p>Assign a parameter to be controlled by this envelope.\nIf a p5.Sound object is given, then the p5.Env will c
20871ontrol its\noutput gain. If multiple inputs are provided, the env will\ncontrol all of them.</p>\n",
20872            "itemtype": "method",
20873            "name": "setInput",
20874            "params": [
20875                {
20876                    "name": "inputs",
20877                    "description": "<p>A p5.sound object or\n                              Web Audio Param.</p>\n",
20878                    "type": "Object",
20879                    "optional": true,
20880                    "multiple": true
20881                }
20882            ],
20883            "class": "p5.Env",
20884            "module": "p5.sound",
20885            "submodule": "p5.sound"
20886        },
20887        {
20888            "file": "lib/addons/p5.sound.js",
20889            "line": 6249,
20890            "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",
20891            "itemtype": "method",
20892            "name": "setExp",
20893            "params": [
20894                {
20895                    "name": "isExp",
20896                    "description": "<p>true is exponential, false is linear</p>\n",
20897                    "type": "Boolean"
20898                }
20899            ],
20900            "class": "p5.Env",
20901            "module": "p5.sound",
20902            "submodule": "p5.sound"
20903        },
20904        {
20905            "file": "lib/addons/p5.sound.js",
20906            "line": 6267,
20907            "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 Env 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",
20908            "itemtype": "method",
20909            "name": "play",
20910            "params": [
20911                {
20912                    "name": "unit",
20913                    "description": "<p>A p5.sound object or\n                              Web Audio Param.</p>\n",
20914                    "type": "Object"
20915                },
20916                {
20917                    "name": "startTime",
20918                    "description": "<p>time from now (in seconds) at which to play</p>\n",
20919                    "type": "Number",
20920                    "optional": true
20921                },
20922                {
20923                    "name": "sustainTime",
20924                    "description": "<p>time to sustain before releasing the envelope</p>\n",
20925                    "type": "Number",
20926                    "optional": true
20927                }
20928            ],
20929            "example": [
20930                "\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.Env();\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>"
20931            ],
20932            "class": "p5.Env",
20933            "module": "p5.sound",
20934            "submodule": "p5.sound"
20935        },
20936        {
20937            "file": "lib/addons/p5.sound.js",
20938            "line": 6328,
20939            "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",
20940            "itemtype": "method",
20941            "name": "triggerAttack",
20942            "params": [
20943                {
20944                    "name": "unit",
20945                    "description": "<p>p5.sound Object or Web Audio Param</p>\n",
20946                    "type": "Object"
20947                },
20948                {
20949                    "name": "secondsFromNow",
20950                    "description": "<p>time from now (in seconds)</p>\n",
20951                    "type": "Number"
20952                }
20953            ],
20954            "example": [
20955                "\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.Env();\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>"
20956            ],
20957            "class": "p5.Env",
20958            "module": "p5.sound",
20959            "submodule": "p5.sound"
20960        },
20961        {
20962            "file": "lib/addons/p5.sound.js",
20963            "line": 6435,
20964            "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",
20965            "itemtype": "method",
20966            "name": "triggerRelease",
20967            "params": [
20968                {
20969                    "name": "unit",
20970                    "description": "<p>p5.sound Object or Web Audio Param</p>\n",
20971                    "type": "Object"
20972                },
20973                {
20974                    "name": "secondsFromNow",
20975                    "description": "<p>time to trigger the release</p>\n",
20976                    "type": "Number"
20977                }
20978            ],
20979            "example": [
20980                "\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.Env();\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>"
20981            ],
20982            "class": "p5.Env",
20983            "module": "p5.sound",
20984            "submodule": "p5.sound"
20985        },
20986        {
20987            "file": "lib/addons/p5.sound.js",
20988            "line": 6532,
20989            "description": "<p>Exponentially ramp to a value using the first two\nvalues from <code><a href=\"#/p5.Env/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",
20990            "itemtype": "method",
20991            "name": "ramp",
20992            "params": [
20993                {
20994                    "name": "unit",
20995                    "description": "<p>p5.sound Object or Web Audio Param</p>\n",
20996                    "type": "Object"
20997                },
20998                {
20999                    "name": "secondsFromNow",
21000                    "description": "<p>When to trigger the ramp</p>\n",
21001                    "type": "Number"
21002                },
21003                {
21004                    "name": "v",
21005                    "description": "<p>Target value</p>\n",
21006                    "type": "Number"
21007                },
21008                {
21009                    "name": "v2",
21010                    "description": "<p>Second target value (optional)</p>\n",
21011                    "type": "Number",
21012                    "optional": true
21013                }
21014            ],
21015            "example": [
21016                "\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.Env();\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);
21016\n  var h = map(amp.getLevel(), 0, 0.4, 0, height);;\n\n  rect(0, height, width, -h);\n}\n</code></div>"
21017            ],
21018            "class": "p5.Env",
21019            "module": "p5.sound",
21020            "submodule": "p5.sound"
21021        },
21022        {
21023            "file": "lib/addons/p5.sound.js",
21024            "line": 6637,
21025            "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",
21026            "itemtype": "method",
21027            "name": "add",
21028            "params": [
21029                {
21030                    "name": "number",
21031                    "description": "<p>Constant number to add</p>\n",
21032                    "type": "Number"
21033                }
21034            ],
21035            "return": {
21036                "description": "Envelope Returns this envelope\n                                   with scaled output",
21037                "type": "p5.Env"
21038            },
21039            "class": "p5.Env",
21040            "module": "p5.sound",
21041            "submodule": "p5.sound"
21042        },
21043        {
21044            "file": "lib/addons/p5.sound.js",
21045            "line": 6653,
21046            "description": "<p>Multiply the p5.Env&#39;s output amplitude\nby a fixed value. Calling this method\nagain will override the initial mult() with new values.</p>\n",
21047            "itemtype": "method",
21048            "name": "mult",
21049            "params": [
21050                {
21051                    "name": "number",
21052                    "description": "<p>Constant number to multiply</p>\n",
21053                    "type": "Number"
21054                }
21055            ],
21056            "return": {
21057                "description": "Envelope Returns this envelope\n                                   with scaled output",
21058                "type": "p5.Env"
21059            },
21060            "class": "p5.Env",
21061            "module": "p5.sound",
21062            "submodule": "p5.sound"
21063        },
21064        {
21065            "file": "lib/addons/p5.sound.js",
21066            "line": 6669,
21067            "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",
21068            "itemtype": "method",
21069            "name": "scale",
21070            "params": [
21071                {
21072                    "name": "inMin",
21073                    "description": "<p>input range minumum</p>\n",
21074                    "type": "Number"
21075                },
21076                {
21077                    "name": "inMax",
21078                    "description": "<p>input range maximum</p>\n",
21079                    "type": "Number"
21080                },
21081                {
21082                    "name": "outMin",
21083                    "description": "<p>input range minumum</p>\n",
21084                    "type": "Number"
21085                },
21086                {
21087                    "name": "outMax",
21088                    "description": "<p>input range maximum</p>\n",
21089                    "type": "Number"
21090                }
21091            ],
21092            "return": {
21093                "description": "Envelope Returns this envelope\n                                   with scaled output",
21094                "type": "p5.Env"
21095            },
21096            "class": "p5.Env",
21097            "module": "p5.sound",
21098            "submodule": "p5.sound"
21099        },
21100        {
21101            "file": "lib/addons/p5.sound.js",
21102            "line": 6773,
21103            "description": "<p>Set the width of a Pulse object (an oscillator that implements\nPulse Width Modulation).</p>\n",
21104            "itemtype": "method",
21105            "name": "width",
21106            "params": [
21107                {
21108                    "name": "width",
21109                    "description": "<p>Width between the pulses (0 to 1.0,\n                       defaults to 0)</p>\n",
21110                    "type": "Number",
21111                    "optional": true
21112                }
21113            ],
21114            "class": "p5.Pulse",
21115            "module": "p5.sound",
21116            "submodule": "p5.sound"
21117        },
21118        {
21119            "file": "lib/addons/p5.sound.js",
21120            "line": 6958,
21121            "description": "<p>Set type of noise to &#39;white&#39;, &#39;pink&#39; or &#39;brown&#39;.\nWhite is the default.</p>\n",
21122            "itemtype": "method",
21123            "name": "setType",
21124            "params": [
21125                {
21126                    "name": "type",
21127                    "description": "<p>&#39;white&#39;, &#39;pink&#39; or &#39;brown&#39;</p>\n",
21128                    "type": "String",
21129                    "optional": true
21130                }
21131            ],
21132            "class": "p5.Noise",
21133            "module": "p5.sound",
21134            "submodule": "p5.sound"
21135        },
21136        {
21137            "file": "lib/addons/p5.sound.js",
21138            "line": 6988,
21139            "description": "<p>Start the noise</p>\n",
21140            "itemtype": "method",
21141            "name": "start",
21142            "class": "p5.Noise",
21143            "module": "p5.sound",
21144            "submodule": "p5.sound"
21145        },
21146        {
21147            "file": "lib/addons/p5.sound.js",
21148            "line": 7005,
21149            "description": "<p>Stop the noise.</p>\n",
21150            "itemtype": "method",
21151            "name": "stop",
21152            "class": "p5.Noise",
21153            "module": "p5.sound",
21154            "submodule": "p5.sound"
21155        },
21156        {
21157            "file": "lib/addons/p5.sound.js",
21158            "line": 7017,
21159            "description": "<p>Pan the noise.</p>\n",
21160            "itemtype": "method",
21161            "name": "pan",
21162            "params": [
21163                {
21164                    "name": "panning",
21165                    "description": "<p>Number between -1 (left)\n                         and 1 (right)</p>\n",
21166                    "type": "Number"
21167                },
21168                {
21169                    "name": "timeFromNow",
21170                    "description": "<p>schedule this event to happen\n                              seconds from now</p>\n",
21171                    "type": "Number"
21172                }
21173            ],
21174            "class": "p5.Noise",
21175            "module": "p5.sound",
21176            "submodule": "p5.sound"
21177        },
21178        {
21179            "file": "lib/addons/p5.sound.js",
21180            "line": 7026,
21181            "description": "<p>Set the amplitude of the noise between 0 and 1.0. Or,\nmodulate amplitude with an audio signal such as an oscillator.</p>\n",
21182            "itemtype": "method",
21183            "name": "amp",
21184            "params": [
21185                {
21186                    "name": "volume",
21187                    "description": "<p>amplitude between 0 and 1.0\n                                   or modulating signal/oscillator</p>\n",
21188                    "type": "Number|Object"
21189                },
21190                {
21191                    "name": "rampTime",
21192                    "description": "<p>create a fade that lasts rampTime</p>\n",
21193                    "type": "Number",
21194                    "optional": true
21195                },
21196                {
21197                    "name": "timeFromNow",
21198                    "description": "<p>schedule this event to happen\n                              seconds from now</p>\n",
21199                    "type": "Number",
21200                    "optional": true
21201                }
21202            ],
21203            "class": "p5.Noise",
21204            "module": "p5.sound",
21205            "submodule": "p5.sound"
21206        },
21207        {
21208            "file": "lib/addons/p5.sound.js",
21209            "line": 7037,
21210            "description": "<p>Send output to a p5.sound or web audio object</p>\n",
21211            "itemtype": "method",
21212            "name": "connect",
21213            "params": [
21214                {
21215                    "name": "unit",
21216                    "description": "",
21217                    "type": "Object"
21218                }
21219            ],
21220            "class": "p5.Noise",
21221            "module": "p5.sound",
21222            "submodule": "p5.sound"
21223        },
21224        {
21225            "file": "lib/addons/p5.sound.js",
21226            "line": 7043,
21227            "description": "<p>Disconnect all output.</p>\n",
21228            "itemtype": "method",
21229            "name": "disconnect",
21230            "class": "p5.Noise",
21231            "module": "p5.sound",
21232            "submodule": "p5.sound"
21233        },
21234        {
21235            "file": "lib/addons/p5.sound.js",
21236            "line": 7117,
21237            "description": "<p>Client must allow browser to access their microphone / audioin source.\nDefault: false. Will become true when the client enables acces.</p>\n",
21238            "itemtype": "property",
21239            "name": "enabled",
21240            "type": "Boolean",
21241            "class": "p5.AudioIn",
21242            "module": "p5.sound",
21243            "submodule": "p5.sound"
21244        },
21245        {
21246            "file": "lib/addons/p5.sound.js",
21247            "line": 7133,
21248            "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 
21248in case\nthe browser won&#39;t provide mic access.</p>\n",
21249            "itemtype": "method",
21250            "name": "start",
21251            "params": [
21252                {
21253                    "name": "successCallback",
21254                    "description": "<p>Name of a function to call on\n                                  success.</p>\n",
21255                    "type": "Function",
21256                    "optional": true
21257                },
21258                {
21259                    "name": "errorCallback",
21260                    "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",
21261                    "type": "Function",
21262                    "optional": true
21263                }
21264            ],
21265            "class": "p5.AudioIn",
21266            "module": "p5.sound",
21267            "submodule": "p5.sound"
21268        },
21269        {
21270            "file": "lib/addons/p5.sound.js",
21271            "line": 7186,
21272            "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",
21273            "itemtype": "method",
21274            "name": "stop",
21275            "class": "p5.AudioIn",
21276            "module": "p5.sound",
21277            "submodule": "p5.sound"
21278        },
21279        {
21280            "file": "lib/addons/p5.sound.js",
21281            "line": 7202,
21282            "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",
21283            "itemtype": "method",
21284            "name": "connect",
21285            "params": [
21286                {
21287                    "name": "unit",
21288                    "description": "<p>An object that accepts audio input,\n                        such as an FFT</p>\n",
21289                    "type": "Object",
21290                    "optional": true
21291                }
21292            ],
21293            "class": "p5.AudioIn",
21294            "module": "p5.sound",
21295            "submodule": "p5.sound"
21296        },
21297        {
21298            "file": "lib/addons/p5.sound.js",
21299            "line": 7223,
21300            "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",
21301            "itemtype": "method",
21302            "name": "disconnect",
21303            "class": "p5.AudioIn",
21304            "module": "p5.sound",
21305            "submodule": "p5.sound"
21306        },
21307        {
21308            "file": "lib/addons/p5.sound.js",
21309            "line": 7235,
21310            "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",
21311            "itemtype": "method",
21312            "name": "getLevel",
21313            "params": [
21314                {
21315                    "name": "smoothing",
21316                    "description": "<p>Smoothing is 0.0 by default.\n                             Smooths values based on previous values.</p>\n",
21317                    "type": "Number",
21318                    "optional": true
21319                }
21320            ],
21321            "return": {
21322                "description": "Volume level (between 0.0 and 1.0)",
21323                "type": "Number"
21324            },
21325            "class": "p5.AudioIn",
21326            "module": "p5.sound",
21327            "submodule": "p5.sound"
21328        },
21329        {
21330            "file": "lib/addons/p5.sound.js",
21331            "line": 7253,
21332            "description": "<p>Set amplitude (volume) of a mic input between 0 and 1.0. <br/></p>\n",
21333            "itemtype": "method",
21334            "name": "amp",
21335            "params": [
21336                {
21337                    "name": "vol",
21338                    "description": "<p>between 0 and 1.0</p>\n",
21339                    "type": "Number"
21340                },
21341                {
21342                    "name": "time",
21343                    "description": "<p>ramp time (optional)</p>\n",
21344                    "type": "Number",
21345                    "optional": true
21346                }
21347            ],
21348            "class": "p5.AudioIn",
21349            "module": "p5.sound",
21350            "submodule": "p5.sound"
21351        },
21352        {
21353            "file": "lib/addons/p5.sound.js",
21354            "line": 7272,
21355            "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",
21356            "itemtype": "method",
21357            "name": "getSources",
21358            "params": [
21359                {
21360                    "name": "successCallback",
21361                    "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",
21362                    "type": "Function",
21363                    "optional": true
21364                },
21365                {
21366                    "name": "errorCallback",
21367                    "description": "<p>This optional callback receives the error\n                                   message as its argument.</p>\n",
21368                    "type": "Function",
21369                    "optional": true
21370                }
21371            ],
21372            "return": {
21373                "description": "Returns a Promise that can be used in place of the callbacks, similar\n                           to the enumerateDevices() method",
21374                "type": "Object"
21375            },
21376            "example": [
21377                "\n <div><code>\n var audiograb;
21377\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>"
21378            ],
21379            "class": "p5.AudioIn",
21380            "module": "p5.sound",
21381            "submodule": "p5.sound"
21382        },
21383        {
21384            "file": "lib/addons/p5.sound.js",
21385            "line": 7323,
21386            "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",
21387            "itemtype": "method",
21388            "name": "setSource",
21389            "params": [
21390                {
21391                    "name": "num",
21392                    "description": "<p>position of input source in the array</p>\n",
21393                    "type": "Number"
21394                }
21395            ],
21396            "class": "p5.AudioIn",
21397            "module": "p5.sound",
21398            "submodule": "p5.sound"
21399        },
21400        {
21401            "file": "lib/addons/p5.sound.js",
21402            "line": 7363,
21403            "class": "p5.AudioIn",
21404            "module": "p5.sound",
21405            "submodule": "p5.sound"
21406        },
21407        {
21408            "file": "lib/addons/p5.sound.js",
21409            "line": 7379,
21410            "class": "p5.AudioIn",
21411            "module": "p5.sound",
21412            "submodule": "p5.sound"
21413        },
21414        {
21415            "file": "lib/addons/p5.sound.js",
21416            "line": 7403,
21417            "class": "p5.AudioIn",
21418            "module": "p5.sound",
21419            "submodule": "p5.sound"
21420        },
21421        {
21422            "file": "lib/addons/p5.sound.js",
21423            "line": 7429,
21424            "class": "p5.AudioIn",
21425            "module": "p5.sound",
21426            "submodule": "p5.sound"
21427        },
21428        {
21429            "file": "lib/addons/p5.sound.js",
21430            "line": 7451,
21431            "class": "p5.AudioIn",
21432            "module": "p5.sound",
21433            "submodule": "p5.sound"
21434        },
21435        {
21436            "file": "lib/addons/p5.sound.js",
21437            "line": 7473,
21438            "class": "p5.AudioIn",
21439            "module": "p5.sound",
21440            "submodule": "p5.sound"
21441        },
21442        {
21443            "file": "lib/addons/p5.sound.js",
21444            "line": 7519,
21445            "class": "p5.AudioIn",
21446            "module": "p5.sound",
21447            "submodule": "p5.sound"
21448        },
21449        {
21450            "file": "lib/addons/p5.sound.js",
21451            "line": 7550,
21452            "class": "p5.AudioIn",
21453            "module": "p5.sound",
21454            "submodule": "p5.sound"
21455        },
21456        {
21457            "file": "lib/addons/p5.sound.js",
21458            "line": 7568,
21459            "class": "p5.AudioIn",
21460            "module": "p5.sound",
21461            "submodule": "p5.sound"
21462        },
21463        {
21464            "file": "lib/addons/p5.sound.js",
21465            "line": 7905,
21466            "class": "p5.AudioIn",
21467            "module": "p5.sound",
21468            "submodule": "p5.sound"
21469        },
21470        {
21471            "file": "lib/addons/p5.sound.js",
21472            "line": 7927,
21473            "class": "p5.AudioIn",
21474            "module": "p5.sound",
21475            "submodule": "p5.sound"
21476        },
21477        {
21478            "file": "lib/addons/p5.sound.js",
21479            "line": 8003,
21480            "description": "<p>In classes that extend\np5.Effect, connect effect nodes\nto the wet parameter</p>\n",
21481            "class": "p5.Effect",
21482            "module": "p5.sound",
21483            "submodule": "p5.sound"
21484        },
21485        {
21486            "file": "lib/addons/p5.sound.js",
21487            "line": 8016,
21488            "description": "<p>Set the output volume of the filter.</p>\n",
21489            "itemtype": "method",
21490            "name": "amp",
21491            "params": [
21492                {
21493                    "name": "vol",
21494                    "description": "<p>amplitude between 0 and 1.0</p>\n",
21495                    "type": "Number",
21496                    "optional": true
21497                },
21498                {
21499                    "name": "rampTime",
21500                    "description": "<p>create a fade that lasts until rampTime</p>\n",
21501                    "type": "Number",
21502                    "optional": true
21503                },
21504                {
21505                    "name": "tFromNow",
21506                    "description": "<p>schedule this event to happen in tFromNow seconds</p>\n",
21507                    "type": "Number",
21508                    "optional": true
21509                }
21510            ],
21511            "class": "p5.Effect",
21512            "module": "p5.sound",
21513            "submodule": "p5.sound"
21514        },
21515        {
21516            "file": "lib/addons/p5.sound.js",
21517            "line": 8033,
21518            "description": "<p>Link effects together in a chain\nExample usage: filter.chain(reverb, delay, panner);\nMay be used with an open-ended number of arguments</p>\n",
21519            "itemtype": "method",
21520            "name": "chain",
21521            "params": [
21522                {
21523                    "name": "arguments",
21524                    "description": "<p>Chain together multiple sound objects</p>\n",
21525                    "type": "Object",
21526                    "optional": true
21527                }
21528            ],
21529            "class": "p5.Effect",
21530            "module": "p5.sound",
21531            "submodule": "p5.sound"
21532        },
21533        {
21534            "file": "lib/addons/p5.sound.js",
21535            "line": 8050,
21536            "description": "<p>Adjust the dry/wet value.</p>\n",
21537            "itemtype": "method",
21538            "name": "drywet",
21539            "params": [
21540                {
21541                    "name": "fade",
21542                    "description": "<p>The desired drywet value (0 - 1.0)</p>\n",
21543                    "type": "Number",
21544                    "optional": true
21545                }
21546            ],
21547            "class": "p5.Effect",
21548            "module": "p5.sound",
21549            "submodule": "p5.sound"
21550        },
21551        {
21552            "file": "lib/addons/p5.sound.js",
21553            "line": 8062,
21554            "description": "<p>Send output to a p5.js-sound, Web Audio Node, or use signal to\ncontrol an AudioParam</p>\n",
21555            "itemtype": "method",
21556            "name": "connect",
21557            "params": [
21558                {
21559                    "name": "unit",
21560                    "description": "",
21561                    "type": "Object"
21562                }
21563            ],
21564            "class": "p5.Effect",
21565            "module": "p5.sound",
21566            "submodule": "p5.sound"
21567        },
21568        {
21569            "file": "lib/addons/p5.sound.js",
21570            "line": 8073,
21571            "description": "<p>Disconnect all output.</p>\n",
21572            "itemtype": "method",
21573            "name": "disconnect",
21574            "class": "p5.Effect",
21575            "module": "p5.sound",
21576            "submodule": "p5.sound"
21577        },
21578        {
21579            "file": "lib/addons/p5.sound.js",
21580            "line": 8181,
21581            "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",
21582            "itemtype": "property",
21583            "name": "biquadFilter",
21584            "type": "DelayNode",
21585            "class": "p5.Filter",
21586            "module": "p5.sound",
21587            "submodule": "p5.sound"
21588        },
21589        {
21590            "file": "lib/addons/p5.sound.js",
21591            "line": 8199,
21592            "description": "<p>Filter an audio signal according to a set\nof filter parameters.</p>\n",
21593            "itemtype": "method",
21594            "name": "process",
21595            "params": [
21596                {
21597                    "name": "Signal",
21598                    "description": "<p>An object that outputs audio</p>\n",
21599                    "type": "Object"
21600                },
21601                {
21602                    "name": "freq",
21603                    "description": "<p>Frequency in Hz, from 10 to 22050</p>\n",
21604                    "type": "Number",
21605                    "optional": true
21606                },
21607                {
21608                    "name": "res",
21609                    "description": "<p>Resonance/Width of the filter frequency\n                      from 0.001 to 1000</p>\n",
21610                    "type": "Number",
21611                    "optional": true
21612                }
21613            ],
21614            "class": "p5.Filter",
21615            "module": "p5.sound",
21616            "submodule": "p5.sound"
21617        },
21618        {
21619            "file": "lib/addons/p5.sound.js",
21620            "line": 8213,
21621            "description": "<p>Set the frequency and the resonance of the filter.</p>\n",
21622            "itemtype": "method",
21623            "name": "set",
21624            "params": [
21625                {
21626                    "name": "freq",
21627                    "description": "<p>Frequency in Hz, from 10 to 22050</p>\n",
21628                    "type": "Number",
21629                    "optional": true
21630                },
21631                {
21632                    "name": "res",
21633                    "description": "<p>Resonance (Q) from 0.001 to 1000</p>\n",
21634                    "type": "Number",
21635                    "optional": true
21636                },
21637                {
21638                    "name": "timeFromNow",
21639                    "description": "<p>schedule this event to happen\n                              seconds from now</p>\n",
21640                    "type": "Number",
21641                    "optional": true
21642                }
21643            ],
21644            "class": "p5.Filter",
21645            "module": "p5.sound",
21646            "submodule": "p5.sound"
21647        },
21648        {
21649            "file": "lib/addons/p5.sound.js",
21650            "line": 8230,
21651            "description": "<p>Set the filter frequency, in Hz, from 10 to 22050 (the range of\
21651nhuman hearing, although in reality most people hear in a narrower\nrange).</p>\n",
21652            "itemtype": "method",
21653            "name": "freq",
21654            "params": [
21655                {
21656                    "name": "freq",
21657                    "description": "<p>Filter Frequency</p>\n",
21658                    "type": "Number"
21659                },
21660                {
21661                    "name": "timeFromNow",
21662                    "description": "<p>schedule this event to happen\n                              seconds from now</p>\n",
21663                    "type": "Number",
21664                    "optional": true
21665                }
21666            ],
21667            "return": {
21668                "description": "value  Returns the current frequency value",
21669                "type": "Number"
21670            },
21671            "class": "p5.Filter",
21672            "module": "p5.sound",
21673            "submodule": "p5.sound"
21674        },
21675        {
21676            "file": "lib/addons/p5.sound.js",
21677            "line": 8255,
21678            "description": "<p>Controls either width of a bandpass frequency,\nor the resonance of a low/highpass cutoff frequency.</p>\n",
21679            "itemtype": "method",
21680            "name": "res",
21681            "params": [
21682                {
21683                    "name": "res",
21684                    "description": "<p>Resonance/Width of filter freq\n                     from 0.001 to 1000</p>\n",
21685                    "type": "Number"
21686                },
21687                {
21688                    "name": "timeFromNow",
21689                    "description": "<p>schedule this event to happen\n                              seconds from now</p>\n",
21690                    "type": "Number",
21691                    "optional": true
21692                }
21693            ],
21694            "return": {
21695                "description": "value Returns the current res value",
21696                "type": "Number"
21697            },
21698            "class": "p5.Filter",
21699            "module": "p5.sound",
21700            "submodule": "p5.sound"
21701        },
21702        {
21703            "file": "lib/addons/p5.sound.js",
21704            "line": 8277,
21705            "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",
21706            "itemtype": "method",
21707            "name": "gain",
21708            "params": [
21709                {
21710                    "name": "gain",
21711                    "description": "",
21712                    "type": "Number"
21713                }
21714            ],
21715            "return": {
21716                "description": "Returns the current or updated gain value",
21717                "type": "Number"
21718            },
21719            "class": "p5.Filter",
21720            "module": "p5.sound",
21721            "submodule": "p5.sound"
21722        },
21723        {
21724            "file": "lib/addons/p5.sound.js",
21725            "line": 8298,
21726            "description": "<p>Toggle function. Switches between the specified type and allpass</p>\n",
21727            "itemtype": "method",
21728            "name": "toggle",
21729            "return": {
21730                "description": "[Toggle value]",
21731                "type": "Boolean"
21732            },
21733            "class": "p5.Filter",
21734            "module": "p5.sound",
21735            "submodule": "p5.sound"
21736        },
21737        {
21738            "file": "lib/addons/p5.sound.js",
21739            "line": 8313,
21740            "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",
21741            "itemtype": "method",
21742            "name": "setType",
21743            "params": [
21744                {
21745                    "name": "t",
21746                    "description": "",
21747                    "type": "String"
21748                }
21749            ],
21750            "class": "p5.Filter",
21751            "module": "p5.sound",
21752            "submodule": "p5.sound"
21753        },
21754        {
21755            "file": "lib/addons/p5.sound.js",
21756            "line": 8516,
21757            "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",
21758            "itemtype": "property",
21759            "name": "bands",
21760            "type": "Array",
21761            "class": "p5.EQ",
21762            "module": "p5.sound",
21763            "submodule": "p5.sound"
21764        },
21765        {
21766            "file": "lib/addons/p5.sound.js",
21767            "line": 8551,
21768            "description": "<p>Process an input by connecting it to the EQ</p>\n",
21769            "itemtype": "method",
21770            "name": "process",
21771            "params": [
21772                {
21773                    "name": "src",
21774                    "description": "<p>Audio source</p>\n",
21775                    "type": "Object"
21776                }
21777            ],
21778            "class": "p5.EQ",
21779            "module": "p5.sound",
21780            "submodule": "p5.sound"
21781        },
21782        {
21783            "file": "lib/addons/p5.sound.js",
21784            "line": 8637,
21785            "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",
21786            "itemtype": "property",
21787            "name": "panner",
21788            "type": "AudioNode",
21789            "class": "p5.Panner3D",
21790            "module": "p5.sound",
21791            "submodule": "p5.sound"
21792        },
21793        {
21794            "file": "lib/addons/p5.sound.js",
21795            "line": 8660,
21796            "description": "<p>Connect an audio sorce</p>\n",
21797            "itemtype": "method",
21798            "name": "process",
21799            "params": [
21800                {
21801                    "name": "src",
21802                    "description": "<p>Input source</p>\n",
21803                    "type": "Object"
21804                }
21805            ],
21806            "class": "p5.Panner3D",
21807            "module": "p5.sound",
21808            "submodule": "p5.sound"
21809        },
21810        {
21811            "file": "lib/addons/p5.sound.js",
21812            "line": 8669,
21813            "description": "<p>Set the X,Y,Z position of the Panner</p>\n",
21814            "itemtype": "method",
21815            "name": "set",
21816            "params": [
21817                {
21818                    "name": "xVal",
21819                    "description": "",
21820                    "type": "Number"
21821                },
21822                {
21823                    "name": "yVal",
21824                    "description": "",
21825                    "type": "Number"
21826                },
21827                {
21828                    "name": "zVal",
21829                    "description": "",
21830                    "type": "Number"
21831                },
21832                {
21833                    "name": "time",
21834                    "description": "",
21835                    "type": "Number"
21836                }
21837            ],
21838            "return": {
21839                "description": "Updated x, y, z values as an array",
21840                "type": "Array"
21841            },
21842            "class": "p5.Panner3D",
21843            "module": "p5.sound",
21844            "submodule": "p5.sound"
21845        },
21846        {
21847            "file": "lib/addons/p5.sound.js",
21848            "line": 8688,
21849            "description": "<p>Getter and setter methods for position coordinates</p>\n",
21850            "itemtype": "method",
21851            "name": "positionX",
21852            "return": {
21853                "description": "updated coordinate value",
21854                "type": "Number"
21855            },
21856            "class": "p5.Panner3D",
21857            "module": "p5.sound",
21858            "submodule": "p5.sound"
21859        },
21860        {
21861            "file": "lib/addons/p5.sound.js",
21862            "line": 8693,
21863            "description": "<p>Getter and setter methods for position coordinates</p>\n",
21864            "itemtype": "method",
21865            "name": "positionY",
21866            "return": {
21867                "description": "updated coordinate value",
21868                "type": "Number"
21869            },
21870            "class": "p5.Panner3D",
21871            "module": "p5.sound",
21872            "submodule": "p5.sound"
21873        },
21874        {
21875            "file": "lib/addons/p5.sound.js",
21876            "line": 8698,
21877            "description": "<p>Getter and setter methods for position coordinates</p>\n",
21878            "itemtype": "method",
21879            "name": "positionZ",
21880            "return": {
21881                "description": "updated coordinate value",
21882                "type": "Number"
21883            },
21884            "class": "p5.Panner3D",
21885            "module": "p5.sound",
21886            "submodule": "p5.sound"
21887        },
21888        {
21889            "file": "lib/addons/p5.sound.js",
21890            "line": 8736,
21891            "description": "<p>Set the X,Y,Z position of the Panner</p>\n",
21892            "itemtype": "method",
21893            "name": "orient",
21894            "params": [
21895                {
21896                    "name": "xVal",
21897                    "description": "",
21898                    "type": "Number"
21899                },
21900                {
21901                    "name": "yVal",
21902                    "description": "",
21903                    "type": "Number"
21904                },
21905                {
21906                    "name": "zVal",
21907                    "description": "",
21908                    "type": "Number"
21909                },
21910                {
21911                    "name": "time",
21912                    "description": "",
21913                    "type": "Number"
21914                }
21915            ],
21916            "return": {
21917                "description": "Updated x, y, z values as an array",
21918                "type": "Array"
21919            },
21920            "class": "p5.Panner3D",
21921            "module": "p5.sound",
21922            "submodule": "p5.sound"
21923        },
21924        {
21925            "file": "lib/addons/p5.sound.js",
21926            "line": 8755,
21927            "description": "<p>Getter and setter methods for orient coordinates</p>\n",
21928            "itemtype": "method",
21929            "name": "orientX",
21930            "return": {
21931                "description": "updated coordinate value",
21932                "type": "Number"
21933            },
21934            "class": "p5.Panner3D",
21935            "module": "p5.sound",
21936            "submodule": "p5.sound"
21937        },
21938        {
21939            "file": "lib/addons/p5.sound.js",
21940            "line": 8760,
21941            "description": "<p>Getter and setter methods for orient coordinates</p>\n",
21942            "itemtype": "method",
21943            "name": "orientY",
21944            "return": {
21945                "description": "updated coordinate value",
21946                "type": "Number"
21947            },
21948            "class": "p5.Panner3D",
21949            "module": "p5.sound",
21950            "submodule": "p5.sound"
21951        },
21952        {
21953            "file": "lib/addons/p5.sound.js",
21954            "line": 8765,
21955            "description": "<p>Getter and setter methods for orient coordinates</p>\n",
21956            "itemtype": "method",
21957            "name": "orientZ",
21958            "return": {
21959                "description": "updated coordinate value",
21960                "type": "Number"
21961            },
21962            "class": "p5.Panner3D",
21963            "module": "p5.sound",
21964            "submodule": "p5.sound"
21965        },
21966        {
21967            "file": "lib/addons/p5.sound.js",
21968            "line": 8803,
21969            "description": "<p>Set the rolloff factor and max distance</p>\n",
21970            "itemtype": "method",
21971            "name": "setFalloff",
21972            "params": [
21973                {
21974                    "name": "maxDistance",
21975                    "description": "",
21976                    "type": "Number",
21977                    "optional": true
21978                },
21979                {
21980                    "name": "rolloffFactor",
21981                    "description": "",
21982                    "type": "Number",
21983                    "optional": true
21984                }
21985            ],
21986            "class": "p5.Panner3D",
21987            "module": "p5.sound",
21988            "submodule": "p5.sound"
21989        },
21990        {
21991            "file": "lib/addons/p5.sound.js",
21992            "line": 8813,
21993            "description": "<p>Maxium distance between the source and the listener</p>\n",
21994            "itemtype": "method",
21995            "name": "maxDist",
21996            "params": [
21997                {
21998                    "name": "maxDistance",
21999                    "description": "",
22000                    "type": "Number"
22001                }
22002            ],
22003            "return": {
22004                "description": "updated value",
22005                "type": "Number"
22006            },
22007            "class": "p5.Panner3D",
22008            "module": "p5.sound",
22009            "submodule": "p5.sound"
22010        },
22011        {
22012            "file": "lib/addons/p5.sound.js",
22013            "line": 8825,
22014            "description": "<p>How quickly the volume is reduced as the source moves away from the listener</p>\n",
22015            "itemtype": "method",
22016            "name": "rollof",
22017            "params": [
22018                {
22019                    "name": "rolloffFactor",
22020                    "description": "",
22021                    "type": "Number"
22022                }
22023            ],
22024            "return": {
22025                "description": "updated value",
22026                "type": "Number"
22027            },
22028            "class": "p5.Panner3D",
22029            "module": "p5.sound",
22030            "submodule": "p5.sound"
22031        },
22032        {
22033            "file": "lib/addons/p5.sound.js",
22034            "line": 9128,
22035            "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",
22036            "itemtype": "property",
22037            "name": "leftDelay",
22038            "type": "DelayNode",
22039            "class": "p5.Delay",
22040            "module": "p5.sound",
22041            "submodule": "p5.sound"
22042        },
22043        {
22044            "file": "lib/addons/p5.sound.js",
22045            "line": 9136,
22046            "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",
22047            "itemtype": "property",
22048            "name": "rightDelay",
22049            "type": "DelayNode",
22050            "class": "p5.Delay",
22051            "module": "p5.sound",
22052            "submodule": "p5.sound"
22053        },
22054        {
22055            "file": "lib/addons/p5.sound.js",
22056            "line": 9168,
22057            "description": "<p>Add delay to an audio signal according to a set\nof delay parameters.</p>\n",
22058            "itemtype": "method",
22059            "name": "process",
22060            "params": [
22061                {
22062                    "name": "Signal",
22063                    "description": "<p>An object that outputs audio</p>\n",
22064                    "type": "Object"
22065                },
22066                {
22067                    "name": "delayTime",
22068                    "description": "<p>Time (in seconds) of the delay/echo.\n                             Some browsers limit delayTime to\n                             1 second.</p>\n",
22069                    "type": "Number",
22070                    "optional": true
22071                },
22072                {
22073                    "name": "feedback",
22074                    "description": "<p>sends the delay back through itself\n                             in a loop that decreases in volume\n                             each time.</p>\n",
22075                    "type": "Number",
22076                    "optional": true
22077                },
22078                {
22079                    "name": "lowPass",
22080     
22080               "description": "<p>Cutoff frequency. Only frequencies\n                             below the lowPass will be part of the\n                             delay.</p>\n",
22081                    "type": "Number",
22082                    "optional": true
22083                }
22084            ],
22085            "class": "p5.Delay",
22086            "module": "p5.sound",
22087            "submodule": "p5.sound"
22088        },
22089        {
22090            "file": "lib/addons/p5.sound.js",
22091            "line": 9203,
22092            "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",
22093            "itemtype": "method",
22094            "name": "delayTime",
22095            "params": [
22096                {
22097                    "name": "delayTime",
22098                    "description": "<p>Time (in seconds) of the delay</p>\n",
22099                    "type": "Number"
22100                }
22101            ],
22102            "class": "p5.Delay",
22103            "module": "p5.sound",
22104            "submodule": "p5.sound"
22105        },
22106        {
22107            "file": "lib/addons/p5.sound.js",
22108            "line": 9222,
22109            "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",
22110            "itemtype": "method",
22111            "name": "feedback",
22112            "params": [
22113                {
22114                    "name": "feedback",
22115                    "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",
22116                    "type": "Number|Object"
22117                }
22118            ],
22119            "return": {
22120                "description": "Feedback value",
22121                "type": "Number"
22122            },
22123            "class": "p5.Delay",
22124            "module": "p5.sound",
22125            "submodule": "p5.sound"
22126        },
22127        {
22128            "file": "lib/addons/p5.sound.js",
22129            "line": 9250,
22130            "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",
22131            "itemtype": "method",
22132            "name": "filter",
22133            "params": [
22134                {
22135                    "name": "cutoffFreq",
22136                    "description": "<p>A lowpass filter will cut off any\n                            frequencies higher than the filter frequency.</p>\n",
22137                    "type": "Number|Object"
22138                },
22139                {
22140                    "name": "res",
22141                    "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",
22142                    "type": "Number|Object"
22143                }
22144            ],
22145            "class": "p5.Delay",
22146            "module": "p5.sound",
22147            "submodule": "p5.sound"
22148        },
22149        {
22150            "file": "lib/addons/p5.sound.js",
22151            "line": 9267,
22152            "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",
22153            "itemtype": "method",
22154            "name": "setType",
22155            "params": [
22156                {
22157                    "name": "type",
22158                    "description": "<p>&#39;pingPong&#39; (1) or &#39;default&#39; (0)</p>\n",
22159                    "type": "String|Number"
22160                }
22161            ],
22162            "class": "p5.Delay",
22163            "module": "p5.sound",
22164            "submodule": "p5.sound"
22165        },
22166        {
22167            "file": "lib/addons/p5.sound.js",
22168            "line": 9300,
22169            "description": "<p>Set the output level of the delay effect.</p>\n",
22170            "itemtype": "method",
22171            "name": "amp",
22172            "params": [
22173                {
22174                    "name": "volume",
22175                    "description": "<p>amplitude between 0 and 1.0</p>\n",
22176                    "type": "Number"
22177                },
22178                {
22179                    "name": "rampTime",
22180                    "description": "<p>create a fade that lasts rampTime</p>\n",
22181                    "type": "Number",
22182                    "optional": true
22183                },
22184                {
22185                    "name": "timeFromNow",
22186                    "description": "<p>schedule this event to happen\n                              seconds from now</p>\n",
22187                    "type": "Number",
22188                    "optional": true
22189                }
22190            ],
22191            "class": "p5.Delay",
22192            "module": "p5.sound",
22193            "submodule": "p5.sound"
22194        },
22195        {
22196            "file": "lib/addons/p5.sound.js",
22197            "line": 9309,
22198            "description": "<p>Send output to a p5.sound or web audio object</p>\n",
22199            "itemtype": "method",
22200            "name": "connect",
22201            "params": [
22202                {
22203                    "name": "unit",
22204                    "description": "",
22205                    "type": "Object"
22206                }
22207            ],
22208            "class": "p5.Delay",
22209            "module": "p5.sound",
22210            "submodule": "p5.sound"
22211        },
22212        {
22213            "file": "lib/addons/p5.sound.js",
22214            "line": 9315,
22215            "description": "<p>Disconnect all output.</p>\n",
22216            "itemtype": "method",
22217            "name": "disconnect",
22218            "class": "p5.Delay",
22219            "module": "p5.sound",
22220            "submodule": "p5.sound"
22221        },
22222        {
22223            "file": "lib/addons/p5.sound.js",
22224            "line": 9394,
22225            "description": "<p>Connect a source to the reverb, and assign reverb parameters.</p>\n",
22226            "itemtype": "method",
22227            "name": "process",
22228            "params": [
22229                {
22230                    "name": "src",
22231                    "description": "<p>p5.sound / Web Audio object with a sound\n                         output.</p>\n",
22232                    "type": "Object"
22233                },
22234                {
22235                    "name": "seconds",
22236                    "description": "<p>Duration of the reverb, in seconds.\n                         Min: 0, Max: 10. Defaults to 3.</p>\n",
22237                    "type": "Number",
22238                    "optional": true
22239                },
22240                {
22241                    "name": "decayRate",
22242                    "description": "<p>Percentage of decay with each echo.\n                          Min: 0, Max: 100. Defaults to 2.</p>\n",
22243                    "type": "Number",
22244                    "optional": true
22245                },
22246                {
22247                    "name": "reverse",
22248                    "description": "<p>Play the reverb backwards or forwards.</p>\n",
22249                    "type": "Boolean",
22250                    "optional": true
22251                }
22252            ],
22253            "class": "p5.Reverb",
22254            "module": "p5.sound",
22255            "submodule": "p5.sound"
22256        },
22257        {
22258            "file": "lib/addons/p5.sound.js",
22259            "line": 9423,
22260            "description": "<p>Set the reverb settings. Similar to .process(), but without\nassigning a new input.</p>\n",
22261            "itemtype": "method",
22262            "name": "set",
22263            "params": [
22264                {
22265                    "name": "seconds",
22266                    "description": "<p>Duration of the reverb, in seconds.\n                         Min: 0, Max: 10. Defaults to 3.</p>\n",
22267                    "type": "Number",
22268                    "optional": true
22269                },
22270                {
22271                    "name": "decayRate",
22272                    "description": "<p>Percentage of decay with each echo.\n                          Min: 0, Max: 100. Defaults to 2.</p>\n",
22273                    "type": "Number",
22274                    "optional": true
22275                },
22276                {
22277                    "name": "reverse",
22278                    "description": "<p>Play the reverb backwards or forwards.</p>\n",
22279                    "type": "Boolean",
22280                    "optional": true
22281                }
22282            ],
22283            "class": "p5.Reverb",
22284            "module": "p5.sound",
22285            "submodule": "p5.sound"
22286        },
22287        {
22288            "file": "lib/addons/p5.sound.js",
22289            "line": 9451,
22290            "description": "<p>Set the output level of the reverb effect.</p>\n",
22291            "itemtype": "method",
22292            "name": "amp",
22293            "params": [
22294                {
22295                    "name": "volume",
22296                    "description": "<p>amplitude between 0 and 1.0</p>\n",
22297                    "type": "Number"
22298                },
22299                {
22300                    "name": "rampTime",
22301                    "description": "<p>create a fade that lasts rampTime</p>\n",
22302                    "type": "Number",
22303                    "optional": true
22304                },
22305                {
22306                    "name": "timeFromNow",
22307                    "description": "<p>schedule this event to happen\n                              seconds from now</p>\n",
22308                    "type": "Number",
22309                    "optional": true
22310                }
22311            ],
22312            "class": "p5.Reverb",
22313            "module": "p5.sound",
22314            "submodule": "p5.sound"
22315        },
22316        {
22317            "file": "lib/addons/p5.sound.js",
22318            "line": 9460,
22319            "description": "<p>Send output to a p5.sound or web audio object</p>\n",
22320            "itemtype": "method",
22321            "name": "connect",
22322            "params": [
22323                {
22324                    "name": "unit",
22325                    "description": "",
22326                    "type": "Object"
22327                }
22328            ],
22329            "class": "p5.Reverb",
22330            "module": "p5.sound",
22331            "submodule": "p5.sound"
22332        },
22333        {
22334            "file": "lib/addons/p5.sound.js",
22335            "line": 9466,
22336            "description": "<p>Disconnect all output.</p>\n",
22337            "itemtype": "method",
22338            "name": "disconnect",
22339            "class": "p5.Reverb",
22340            "module": "p5.sound",
22341            "submodule": "p5.sound"
22342        },
22343        {
22344            "file": "lib/addons/p5.sound.js",
22345            "line": 9560,
22346            "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",
22347            "itemtype": "property",
22348            "name": "convolverNod",
22349            "type": "ConvolverNode",
22350            "class": "p5.Convolver",
22351            "module": "p5.sound",
22352            "submodule": "p5.sound"
22353        },
22354        {
22355            "file": "lib/addons/p5.sound.js",
22356            "line": 9585,
22357            "description": "<p>Create a p5.Convolver. Accepts a path to a soundfile\nthat will be used to generate an impulse response.</p>\n",
22358            "itemtype": "method",
22359            "name": "createConvolver",
22360            "params": [
22361                {
22362                    "name": "path",
22363                    "description": "<p>
22363path to a sound file</p>\n",
22364                    "type": "String"
22365                },
22366                {
22367                    "name": "callback",
22368                    "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",
22369                    "type": "Function",
22370                    "optional": true
22371                },
22372                {
22373                    "name": "errorCallback",
22374                    "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",
22375                    "type": "Function",
22376                    "optional": true
22377                }
22378            ],
22379            "return": {
22380                "description": "",
22381                "type": "p5.Convolver"
22382            },
22383            "example": [
22384                "\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'\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>"
22385            ],
22386            "class": "p5.Convolver",
22387            "module": "p5.sound",
22388            "submodule": "p5.sound"
22389        },
22390        {
22391            "file": "lib/addons/p5.sound.js",
22392            "line": 9701,
22393            "description": "<p>Connect a source to the reverb, and assign reverb parameters.</p>\n",
22394            "itemtype": "method",
22395            "name": "process",
22396            "params": [
22397                {
22398                    "name": "src",
22399                    "description": "<p>p5.sound / Web Audio object with a sound\n                         output.</p>\n",
22400                    "type": "Object"
22401                }
22402            ],
22403            "example": [
22404                "\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>"
22405            ],
22406            "class": "p5.Convolver",
22407            "module": "p5.sound",
22408            "submodule": "p5.sound"
22409        },
22410        {
22411            "file": "lib/addons/p5.sound.js",
22412            "line": 9733,
22413            "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",
22414            "itemtype": "property",
22415            "name": "impulses",
22416            "type": "Array",
22417            "class": "p5.Convolver",
22418            "module": "p5.sound",
22419            "submodule": "p5.sound"
22420        },
22421        {
22422            "file": "lib/addons/p5.sound.js",
22423            "line": 9741,
22424            "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",
22425            "itemtype": "method",
22426            "name": "addImpulse",
22427            "params": [
22428                {
22429                    "name": "path",
22430                    "description": "<p>path to a sound file</p>\n",
22431                    "type": "String"
22432                },
22433                {
22434                    "name": "callback",
22435                    "description": "<p>function (optional)</p>\n",
22436                    "type": "Function"
22437                },
22438                {
22439                    "name": "errorCallback",
22440                    "description": "<p>function (optional)</p>\n",
22441                    "type": "Function"
22442                }
22443            ],
22444            "class": "p5.Convolver",
22445            "module": "p5.sound",
22446            "submodule": "p5.sound"
22447        },
22448        {
22449            "file": "lib/addons/p5.sound.js",
22450            "line": 9759,
22451            "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",
22452            "itemtype": "method",
22453            "name": "resetImpulse",
22454            "params": [
22455                {
22456                    "name": "path",
22457                    "description": "<p>
22457path to a sound file</p>\n",
22458                    "type": "String"
22459                },
22460                {
22461                    "name": "callback",
22462                    "description": "<p>function (optional)</p>\n",
22463                    "type": "Function"
22464                },
22465                {
22466                    "name": "errorCallback",
22467                    "description": "<p>function (optional)</p>\n",
22468                    "type": "Function"
22469                }
22470            ],
22471            "class": "p5.Convolver",
22472            "module": "p5.sound",
22473            "submodule": "p5.sound"
22474        },
22475        {
22476            "file": "lib/addons/p5.sound.js",
22477            "line": 9777,
22478            "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",
22479            "itemtype": "method",
22480            "name": "toggleImpulse",
22481            "params": [
22482                {
22483                    "name": "id",
22484                    "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",
22485                    "type": "String|Number"
22486                }
22487            ],
22488            "class": "p5.Convolver",
22489            "module": "p5.sound",
22490            "submodule": "p5.sound"
22491        },
22492        {
22493            "file": "lib/addons/p5.sound.js",
22494            "line": 9821,
22495            "class": "p5.Convolver",
22496            "module": "p5.sound",
22497            "submodule": "p5.sound"
22498        },
22499        {
22500            "file": "lib/addons/p5.sound.js",
22501            "line": 9846,
22502            "class": "p5.Convolver",
22503            "module": "p5.sound",
22504            "submodule": "p5.sound"
22505        },
22506        {
22507            "file": "lib/addons/p5.sound.js",
22508            "line": 10041,
22509            "description": "<p>Set the global tempo, in beats per minute, for all\np5.Parts. This method will impact all active p5.Parts.</p>\n",
22510            "itemtype": "method",
22511            "name": "setBPM",
22512            "params": [
22513                {
22514                    "name": "BPM",
22515                    "description": "<p>Beats Per Minute</p>\n",
22516                    "type": "Number"
22517                },
22518                {
22519                    "name": "rampTime",
22520                    "description": "<p>Seconds from now</p>\n",
22521                    "type": "Number"
22522                }
22523            ],
22524            "class": "p5.Convolver",
22525            "module": "p5.sound",
22526            "submodule": "p5.sound"
22527        },
22528        {
22529            "file": "lib/addons/p5.sound.js",
22530            "line": 10131,
22531            "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",
22532            "itemtype": "property",
22533            "name": "sequence",
22534            "type": "Array",
22535            "class": "p5.Phrase",
22536            "module": "p5.sound",
22537            "submodule": "p5.sound"
22538        },
22539        {
22540            "file": "lib/addons/p5.sound.js",
22541            "line": 10219,
22542            "description": "<p>Set the tempo of this part, in Beats Per Minute.</p>\n",
22543            "itemtype": "method",
22544            "name": "setBPM",
22545            "params": [
22546                {
22547                    "name": "BPM",
22548                    "description": "<p>Beats Per Minute</p>\n",
22549                    "type": "Number"
22550                },
22551                {
22552                    "name": "rampTime",
22553                    "description": "<p>Seconds from now</p>\n",
22554                    "type": "Number",
22555                    "optional": true
22556                }
22557            ],
22558            "class": "p5.Part",
22559            "module": "p5.sound",
22560            "submodule": "p5.sound"
22561        },
22562        {
22563            "file": "lib/addons/p5.sound.js",
22564            "line": 10229,
22565            "description": "<p>Returns the Beats Per Minute of this currently part.</p>\n",
22566            "itemtype": "method",
22567            "name": "getBPM",
22568            "return": {
22569                "description": "",
22570                "type": "Number"
22571            },
22572            "class": "p5.Part",
22573            "module": "p5.sound",
22574            "submodule": "p5.sound"
22575        },
22576        {
22577            "file": "lib/addons/p5.sound.js",
22578            "line": 10238,
22579            "description": "<p>Start playback of this part. It will play\nthrough all of its phrases at a speed\ndetermined by setBPM.</p>\n",
22580            "itemtype": "method",
22581            "name": "start",
22582            "params": [
22583                {
22584                    "name": "time",
22585                    "description": "<p>seconds from now</p>\n",
22586                    "type": "Number",
22587                    "optional": true
22588                }
22589            ],
22590            "class": "p5.Part",
22591            "module": "p5.sound",
22592            "submodule": "p5.sound"
22593        },
22594        {
22595            "file": "lib/addons/p5.sound.js",
22596            "line": 10254,
22597            "description": "<p>Loop playback of this part. It will begin\nlooping through all of its phrases at a speed\ndetermined by setBPM.</p>\n",
22598            "itemtype": "method",
22599            "name": "loop",
22600            "params": [
22601                {
22602                    "name": "time",
22603                    "description": "<p>seconds from now</p>\n",
22604                    "type": "Number",
22605                    "optional": true
22606                }
22607            ],
22608            "class": "p5.Part",
22609            "module": "p5.sound",
22610            "submodule": "p5.sound"
22611        },
22612        {
22613            "file": "lib/addons/p5.sound.js",
22614            "line": 10271,
22615            "description": "<p>Tell the part to stop looping.</p>\n",
22616            "itemtype": "method",
22617            "name": "noLoop",
22618            "class": "p5.Part",
22619            "module": "p5.sound",
22620            "submodule": "p5.sound"
22621        },
22622        {
22623            "file": "lib/addons/p5.sound.js",
22624            "line": 10283,
22625            "description": "<p>Stop the part and cue it to step 0.</p>\n",
22626            "itemtype": "method",
22627            "name": "stop",
22628            "params": [
22629                {
22630                    "name": "time",
22631                    "description": "<p>seconds from now</p>\n",
22632                    "type": "Number",
22633                    "optional": true
22634                }
22635            ],
22636            "class": "p5.Part",
22637            "module": "p5.sound",
22638            "submodule": "p5.sound"
22639        },
22640        {
22641            "file": "lib/addons/p5.sound.js",
22642            "line": 10293,
22643            "description": "<p>Pause the part. Playback will resume\nfrom the current step.</p>\n",
22644            "itemtype": "method",
22645            "name": "pause",
22646            "params": [
22647                {
22648                    "name": "time",
22649                    "description": "<p>seconds from now</p>\n",
22650                    "type": "Number"
22651                }
22652            ],
22653            "class": "p5.Part",
22654            "module": "p5.sound",
22655            "submodule": "p5.sound"
22656        },
22657        {
22658            "file": "lib/addons/p5.sound.js",
22659            "line": 10305,
22660            "description": "<p>Add a p5.Phrase to this Part.</p>\n",
22661            "itemtype": "method",
22662            "name": "addPhrase",
22663            "params": [
22664                {
22665                    "name": "phrase",
22666                    "description": "<p>reference to a p5.Phrase</p>\n",
22667                    "type": "p5.Phrase"
22668                }
22669            ],
22670            "class": "p5.Part",
22671            "module": "p5.sound",
22672            "submodule": "p5.sound"
22673        },
22674        {
22675            "file": "lib/addons/p5.sound.js",
22676            "line": 10326,
22677            "description": "<p>Remove a phrase from this part, based on the name it was\ngiven when it was created.</p>\n",
22678            "itemtype": "method",
22679            "name": "removePhrase",
22680            "params": [
22681                {
22682                    "name": "phraseName",
22683                    "description": "",
22684                    "type": "String"
22685                }
22686            ],
22687            "class": "p5.Part",
22688            "module": "p5.sound",
22689            "submodule": "p5.sound"
22690        },
22691        {
22692            "file": "lib/addons/p5.sound.js",
22693            "line": 10340,
22694            "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",
22695            "itemtype": "method",
22696            "name": "getPhrase",
22697            "params": [
22698                {
22699                    "name": "phraseName",
22700                    "description": "",
22701                    "type": "String"
22702                }
22703            ],
22704            "class": "p5.Part",
22705            "module": "p5.sound",
22706            "submodule": "p5.sound"
22707        },
22708        {
22709            "file": "lib/addons/p5.sound.js",
22710            "line": 10354,
22711            "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",
22712            "itemtype": "method",
22713            "name": "replaceSequence",
22714            "params": [
22715                {
22716                    "name": "phraseName",
22717                    "description": "",
22718                    "type": "String"
22719                },
22720                {
22721                    "name": "sequence",
22722                    "description": "<p>Array of values to pass into the callback\n                          at each step of the phrase.</p>\n",
22723                    "type": "Array"
22724                }
22725            ],
22726            "class": "p5.Part",
22727            "module": "p5.sound",
22728            "submodule": "p5.sound"
22729        },
22730        {
22731            "file": "lib/addons/p5.sound.js",
22732            "line": 10382,
22733            "description": "<p>Fire a callback function at every step.</p>\n",
22734            "itemtype": "method",
22735            "name": "onStep",
22736            "params": [
22737                {
22738                    "name": "callback",
22739                    "description": "<p>The name of the callback\n                            you want to fire\n                            on every beat/tatum.</p>\n",
22740                    "type": "Function"
22741                }
22742            ],
22743            "class": "p5.Part",
22744            "module": "p5.sound",
22745            "submodule": "p5.sound"
22746        },
22747        {
22748            "file": "lib/addons/p5.sound.js",
22749            "line": 10435,
22750            "description": "<p>Start playback of the score.</p>\n",
22751            "itemtype": "method",
22752            "name": "start",
22753            "class": "p5.Score",
22754            "module": "p5.sound",
22755            "submodule": "p5.sound"
22756        },
22757        {
22758            "file": "lib/addons/p5.sound.js",
22759            "line": 10444,
22760            "description": "<p>Stop playback of the score.</p>\n",
22761            "itemtype": "method",
22762            "name": "stop",
22763            "class": "p5.Score",
22764            "module": "p5.sound",
22765            "submodule": "p5.sound"
22766        },
22767        {
22768            "file": "lib/addons/p5.sound.js",
22769            "line": 10454,
22770            "description": "<p>Pause playback of the score.</p>\n",
22771            "itemtype": "method",
22772            "name": "pause",
22773            "class": "p5.Score",
22774            "module": "p5.sound",
22775            "submodule": "p5.sound"
22776        },
22777        {
22778            "file": "lib/addons/p5.sound.js",
22779            "line": 10462,
22780            "description": "<p>Loop playback of the score.</p>\n",
22781            "itemtype": "method",
22782            "name": "loop",
22783            "class": "p5.Score",
22784            "module": "p5.sound",
22785            "submodule": "p5.sound"
22786        },
22787        {
22788            "file": "lib/addons/p5.sound.js",
22789            "line": 10471,
22790            "description": "<p>Stop looping playback of the score. If it\nis currently playing, this will go into effect\nafter the current roun
22790d of playback completes.</p>\n",
22791            "itemtype": "method",
22792            "name": "noLoop",
22793            "class": "p5.Score",
22794            "module": "p5.sound",
22795            "submodule": "p5.sound"
22796        },
22797        {
22798            "file": "lib/addons/p5.sound.js",
22799            "line": 10496,
22800            "description": "<p>Set the tempo for all parts in the score</p>\n",
22801            "itemtype": "method",
22802            "name": "setBPM",
22803            "params": [
22804                {
22805                    "name": "BPM",
22806                    "description": "<p>Beats Per Minute</p>\n",
22807                    "type": "Number"
22808                },
22809                {
22810                    "name": "rampTime",
22811                    "description": "<p>Seconds from now</p>\n",
22812                    "type": "Number"
22813                }
22814            ],
22815            "class": "p5.Score",
22816            "module": "p5.sound",
22817            "submodule": "p5.sound"
22818        },
22819        {
22820            "file": "lib/addons/p5.sound.js",
22821            "line": 10564,
22822            "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",
22823            "itemtype": "property",
22824            "name": "musicalTimeMode",
22825            "type": "Boolean",
22826            "class": "p5.SoundLoop",
22827            "module": "p5.sound",
22828            "submodule": "p5.sound"
22829        },
22830        {
22831            "file": "lib/addons/p5.sound.js",
22832            "line": 10571,
22833            "description": "<p>musicalTimeMode variables\nmodify these only when the interval is specified in musicalTime format as a string</p>\n",
22834            "class": "p5.SoundLoop",
22835            "module": "p5.sound",
22836            "submodule": "p5.sound"
22837        },
22838        {
22839            "file": "lib/addons/p5.sound.js",
22840            "line": 10578,
22841            "description": "<p>Set a limit to the number of loops to play. defaults to Infinity</p>\n",
22842            "itemtype": "property",
22843            "name": "maxIterations",
22844            "type": "Number",
22845            "class": "p5.SoundLoop",
22846            "module": "p5.sound",
22847            "submodule": "p5.sound"
22848        },
22849        {
22850            "file": "lib/addons/p5.sound.js",
22851            "line": 10587,
22852            "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",
22853            "class": "p5.SoundLoop",
22854            "module": "p5.sound",
22855            "submodule": "p5.sound"
22856        },
22857        {
22858            "file": "lib/addons/p5.sound.js",
22859            "line": 10601,
22860            "description": "<p>Start the loop</p>\n",
22861            "itemtype": "method",
22862            "name": "start",
22863            "params": [
22864                {
22865                    "name": "timeFromNow",
22866                    "description": "<p>schedule a starting time</p>\n",
22867                    "type": "Number",
22868                    "optional": true
22869                }
22870            ],
22871            "class": "p5.SoundLoop",
22872            "module": "p5.sound",
22873            "submodule": "p5.sound"
22874        },
22875        {
22876            "file": "lib/addons/p5.sound.js",
22877            "line": 10614,
22878            "description": "<p>Stop the loop</p>\n",
22879            "itemtype": "method",
22880            "name": "stop",
22881            "params": [
22882                {
22883                    "name": "timeFromNow",
22884                    "description": "<p>schedule a stopping time</p>\n",
22885                    "type": "Number",
22886                    "optional": true
22887                }
22888            ],
22889            "class": "p5.SoundLoop",
22890            "module": "p5.sound",
22891            "submodule": "p5.sound"
22892        },
22893        {
22894            "file": "lib/addons/p5.sound.js",
22895            "line": 10627,
22896            "description": "<p>Pause the loop</p>\n",
22897            "itemtype": "method",
22898            "name": "pause",
22899            "params": [
22900                {
22901                    "name": "timeFromNow",
22902                    "description": "<p>schedule a pausing time</p>\n",
22903                    "type": "Number",
22904                    "optional": true
22905                }
22906            ],
22907            "class": "p5.SoundLoop",
22908            "module": "p5.sound",
22909            "submodule": "p5.sound"
22910        },
22911        {
22912            "file": "lib/addons/p5.sound.js",
22913            "line": 10639,
22914            "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",
22915            "itemtype": "method",
22916            "name": "syncedStart",
22917            "params": [
22918                {
22919                    "name": "otherLoop",
22920                    "description": "<p>a p5.SoundLoop to sync with</p>\n",
22921                    "type": "Object"
22922                },
22923                {
22924                    "name": "timeFromNow",
22925                    "description": "<p>Start the loops in sync after timeFromNow seconds</p>\n",
22926                    "type": "Number",
22927                    "optional": true
22928                }
22929            ],
22930            "class": "p5.SoundLoop",
22931            "module": "p5.sound",
22932            "submodule": "p5.sound"
22933        },
22934        {
22935            "file": "lib/addons/p5.sound.js",
22936            "line": 10720,
22937            "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",
22938            "itemtype": "property",
22939            "name": "bpm",
22940            "type": "Number",
22941            "class": "p5.SoundLoop",
22942            "module": "p5.sound",
22943            "submodule": "p5.sound"
22944        },
22945        {
22946            "file": "lib/addons/p5.sound.js",
22947            "line": 10738,
22948            "description": "<p>number of quarter notes in a measure (defaults to 4)</p>\n",
22949            "itemtype": "property",
22950            "name": "timeSignature",
22951            "type": "Number",
22952            "class": "p5.SoundLoop",
22953            "module": "p5.sound",
22954            "submodule": "p5.sound"
22955        },
22956        {
22957            "file": "lib/addons/p5.sound.js",
22958            "line": 10754,
22959            "description": "<p>length of the loops interval</p>\n",
22960            "itemtype": "property",
22961            "name": "interval",
22962            "type": "Number|String",
22963            "class": "p5.SoundLoop",
22964            "module": "p5.sound",
22965            "submodule": "p5.sound"
22966        },
22967        {
22968            "file": "lib/addons/p5.sound.js",
22969            "line": 10768,
22970            "description": "<p>how many times the callback has been called so far</p>\n",
22971            "itemtype": "property",
22972            "name": "iterations",
22973            "type": "Number",
22974            "readonly": "",
22975            "class": "p5.SoundLoop",
22976            "module": "p5.sound",
22977            "submodule": "p5.sound"
22978        },
22979        {
22980            "file": "lib/addons/p5.sound.js",
22981            "line": 10809,
22982            "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\">
22982Web Audio Dynamics Compressor Node\n  </a></p>\n",
22983            "itemtype": "property",
22984            "name": "compressor",
22985            "type": "AudioNode",
22986            "class": "p5.Compressor",
22987            "module": "p5.sound",
22988            "submodule": "p5.sound"
22989        },
22990        {
22991            "file": "lib/addons/p5.sound.js",
22992            "line": 10820,
22993            "description": "<p>Performs the same function as .connect, but also accepts\noptional parameters to set compressor&#39;s audioParams</p>\n",
22994            "itemtype": "method",
22995            "name": "process",
22996            "params": [
22997                {
22998                    "name": "src",
22999                    "description": "<p>Sound source to be connected</p>\n",
23000                    "type": "Object"
23001                },
23002                {
23003                    "name": "attack",
23004                    "description": "<p>The amount of time (in seconds) to reduce the gain by 10dB,\n                           default = .003, range 0 - 1</p>\n",
23005                    "type": "Number",
23006                    "optional": true
23007                },
23008                {
23009                    "name": "knee",
23010                    "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",
23011                    "type": "Number",
23012                    "optional": true
23013                },
23014                {
23015                    "name": "ratio",
23016                    "description": "<p>The amount of dB change in input for a 1 dB change in output\n                           default = 12, range 1 - 20</p>\n",
23017                    "type": "Number",
23018                    "optional": true
23019                },
23020                {
23021                    "name": "threshold",
23022                    "description": "<p>The decibel value above which the compression will start taking effect\n                           default = -24, range -100 - 0</p>\n",
23023                    "type": "Number",
23024                    "optional": true
23025                },
23026                {
23027                    "name": "release",
23028                    "description": "<p>The amount of time (in seconds) to increase the gain by 10dB\n                           default = .25, range 0 - 1</p>\n",
23029                    "type": "Number",
23030                    "optional": true
23031                }
23032            ],
23033            "class": "p5.Compressor",
23034            "module": "p5.sound",
23035            "submodule": "p5.sound"
23036        },
23037        {
23038            "file": "lib/addons/p5.sound.js",
23039            "line": 10843,
23040            "description": "<p>Set the paramters of a compressor.</p>\n",
23041            "itemtype": "method",
23042            "name": "set",
23043            "params": [
23044                {
23045                    "name": "attack",
23046                    "description": "<p>The amount of time (in seconds) to reduce the gain by 10dB,\n                           default = .003, range 0 - 1</p>\n",
23047                    "type": "Number"
23048                },
23049                {
23050                    "name": "knee",
23051                    "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",
23052                    "type": "Number"
23053                },
23054                {
23055                    "name": "ratio",
23056                    "description": "<p>The amount of dB change in input for a 1 dB change in output\n                           default = 12, range 1 - 20</p>\n",
23057                    "type": "Number"
23058                },
23059                {
23060                    "name": "threshold",
23061                    "description": "<p>The decibel value above which the compression will start taking effect\n                           default = -24, range -100 - 0</p>\n",
23062                    "type": "Number"
23063                },
23064                {
23065                    "name": "release",
23066                    "description": "<p>The amount of time (in seconds) to increase the gain by 10dB\n                           default = .25, range 0 - 1</p>\n",
23067                    "type": "Number"
23068                }
23069            ],
23070            "class": "p5.Compressor",
23071            "module": "p5.sound",
23072            "submodule": "p5.sound"
23073        },
23074        {
23075            "file": "lib/addons/p5.sound.js",
23076            "line": 10875,
23077            "description": "<p>Get current attack or set value w/ time ramp</p>\n",
23078            "itemtype": "method",
23079            "name": "attack",
23080            "params": [
23081                {
23082                    "name": "attack",
23083                    "description": "<p>Attack is the amount of time (in seconds) to reduce the gain by 10dB,\n                         default = .003, range 0 - 1</p>\n",
23084                    "type": "Number",
23085                    "optional": true
23086                },
23087                {
23088                    "name": "time",
23089                    "description": "<p>Assign time value to schedule the change in value</p>\n",
23090                    "type": "Number",
23091                    "optional": true
23092                }
23093            ],
23094            "class": "p5.Compressor",
23095            "module": "p5.sound",
23096            "submodule": "p5.sound"
23097        },
23098        {
23099            "file": "lib/addons/p5.sound.js",
23100            "line": 10895,
23101            "description": "<p>Get current knee or set value w/ time ramp</p>\n",
23102            "itemtype": "method",
23103            "name": "knee",
23104            "params": [
23105                {
23106                    "name": "knee",
23107                    "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",
23108                    "type": "Number",
23109                    "optional": true
23110                },
23111                {
23112                    "name": "time",
23113                    "description": "<p>Assign time value to schedule the change in value</p>\n",
23114                    "type": "Number",
23115                    "optional": true
23116                }
23117            ],
23118            "class": "p5.Compressor",
23119            "module": "p5.sound",
23120            "submodule": "p5.sound"
23121        },
23122        {
23123            "file": "lib/addons/p5.sound.js",
23124            "line": 10915,
23125            "description": "<p>Get current ratio or set value w/ time ramp</p>\n",
23126            "itemtype": "method",
23127            "name": "ratio",
23128            "params": [
23129                {
23130                    "name": "ratio",
23131                    "description": "<p>The amount of dB change in input for a 1 dB change in output\n                           default = 12, range 1 - 20</p>\n",
23132                    "type": "Number",
23133                    "optional": true
23134                },
23135                {
23136                    "name": "time",
23137                    "description": "<p>Assign time value to schedule the change in value</p>\n",
23138                    "type": "Number",
23139                    "optional": true
23140                }
23141            ],
23142            "class": "p5.Compressor",
23143            "module": "p5.sound",
23144            "submodule": "p5.sound"
23145        },
23146        {
23147            "file": "lib/addons/p5.sound.js",
23148            "line": 10934,
23149            "description": "<p>Get current threshold or set value w/ time ramp</p>\n",
23150            "itemtype": "method",
23151            "name": "threshold",
23152            "params": [
23153                {
23154                    "name": "threshold",
23155                    "description": "<p>The decibel value above which the compression will start taking effect\n                           default = -24, range -100 - 0</p>\n",
23156                    "type": "Number"
23157                },
23158                {
23159                    "name": "time",
23160                    "description": "<p>Assign time value to schedule the change in value</p>\n",
23161                    "type": "Number",
23162                    "optional": true
23163                }
23164            ],
23165            "class": "p5.Compressor",
23166            "module": "p5.sound",
23167            "submodule": "p5.sound"
23168        },
23169        {
23170            "file": "lib/addons/p5.sound.js",
23171            "line": 10953,
23172            "description": "<p>Get current release or set value w/ time ramp</p>\n",
23173            "itemtype": "method",
23174            "name": "release",
23175            "params": [
23176                {
23177                    "name": "release",
23178                    "description": "<p>The amount of time (in seconds) to increase the gain by 10dB\n                           default = .25, range 0 - 1</p>\n",
23179                    "type": "Number"
23180                },
23181                {
23182                    "name": "time",
23183                    "description": "<p>Assign time value to schedule the change in value</p>\n",
23184                    "type": "Number",
23185                    "optional": true
23186                }
23187            ],
23188            "class": "p5.Compressor",
23189            "module": "p5.sound",
23190            "submodule": "p5.sound"
23191        },
23192        {
23193            "file": "lib/addons/p5.sound.js",
23194            "line": 10973,
23195            "description": "<p>Return the current reduction value</p>\n",
23196            "itemtype": "method",
23197            "name": "reduction",
23198            "return": {
23199                "description": "Value of the amount of gain reduction that is applied to the signal",
23200                "type": "Number"
23201            },
23202            "class": "p5.Compressor",
23203            "module": "p5.sound",
23204            "submodule": "p5.sound"
23205        },
23206        {
23207            "file": "lib/addons/p5.sound.js",
23208            "line": 11085,
23209            "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",
23210            "itemtype": "method",
23211            "name": "setInput",
23212            "params": [
23213                {
23214                    "name": "unit",
23215                    "description": "<p>p5.sound object or a web audio unit\n                       that outputs sound</p>\n",
23216                    "type": "Object",
23217                    "optional": true
23218                }
23219            ],
23220            "class": "p5.SoundRecorder",
23221            "module": "p5.sound",
23222            "submodule": "p5.sound"
23223        },
23224        {
23225            "file": "lib/addons/p5.sound.js",
23226            "line": 11106,
23227            "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",
23228            "itemtype": "method",
23229            "name": "record",
23230            "params": [
23231                {
23232                    "name": "soundFile",
23233                    "description": "<p>p5.SoundFile</p>\n",
23234                    "type": "p5.SoundFile"
23235                },
23236                {
23237                    "name": "duration",
23238                    "description": "<p>Time (in seconds)</p>\n",
23239                    "type": "Number",
23240                    "optional": true
23241                },
23242                {
23243                    "name": "callback",
23244                    "description": "<p>The name of a function that will be\n                              called once the recording completes</p>\n",
23245                    "type": "Function",
23246                    "optional": true
23247                }
23248            ],
23249            "class": "p5.SoundRecorder",
23250            "module": "p5.sound",
23251            "submodule": "p5.sound"
23252        },
23253        {
23254            "file": "lib/addons/p5.sound.js",
23255            "line": 11139,
23256            "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",
23257            "itemtype": "method",
23258            "name": "stop",
23259            "class": "p5.SoundRecorder",
23260            "module": "p5.sound",
23261            "submodule": "p5.sound"
23262        },
23263        {
23264            "file": "lib/addons/p5.sound.js",
23265            "line": 11212,
23266            "description": "<p>Save a p5.SoundFile as a .wav audio file.</p>\n",
23267            "itemtype": "method",
23268            "name": "saveSound",
23269            "params": [
23270                {
23271                    "name": "soundFile",
23272                    "description": "<p>
23272p5.SoundFile that you wish to save</p>\n",
23273                    "type": "p5.SoundFile"
23274                },
23275                {
23276                    "name": "name",
23277                    "description": "<p>name of the resulting .wav file.</p>\n",
23278                    "type": "String"
23279                }
23280            ],
23281            "class": "p5.SoundRecorder",
23282            "module": "p5.sound",
23283            "submodule": "p5.sound"
23284        },
23285        {
23286            "file": "lib/addons/p5.sound.js",
23287            "line": 11388,
23288            "description": "<p>isDetected is set to true when a peak is detected.</p>\n",
23289            "itemtype": "attribute",
23290            "name": "isDetected",
23291            "type": "Boolean",
23292            "default": "false",
23293            "class": "p5.PeakDetect",
23294            "module": "p5.sound",
23295            "submodule": "p5.sound"
23296        },
23297        {
23298            "file": "lib/addons/p5.sound.js",
23299            "line": 11401,
23300            "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",
23301            "itemtype": "method",
23302            "name": "update",
23303            "params": [
23304                {
23305                    "name": "fftObject",
23306                    "description": "<p>A p5.FFT object</p>\n",
23307                    "type": "p5.FFT"
23308                }
23309            ],
23310            "class": "p5.PeakDetect",
23311            "module": "p5.sound",
23312            "submodule": "p5.sound"
23313        },
23314        {
23315            "file": "lib/addons/p5.sound.js",
23316            "line": 11432,
23317            "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",
23318            "itemtype": "method",
23319            "name": "onPeak",
23320            "params": [
23321                {
23322                    "name": "callback",
23323                    "description": "<p>Name of a function that will\n                            be called when a peak is\n                            detected.</p>\n",
23324                    "type": "Function"
23325                },
23326                {
23327                    "name": "val",
23328                    "description": "<p>Optional value to pass\n                            into the function when\n                            a peak is detected.</p>\n",
23329                    "type": "Object",
23330                    "optional": true
23331                }
23332            ],
23333            "example": [
23334                "\n<div><code>\nvar cnv, soundFile, fft, peakDetect;\nvar ellipseWidth = 0;\n\nfunction setup() {\n  cnv = createCanvas(100,100);\n  textAlign(CENTER);\n\n  soundFile = loadSound('assets/beat.mp3');\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>"
23335            ],
23336            "class": "p5.PeakDetect",
23337            "module": "p5.sound",
23338            "submodule": "p5.sound"
23339        },
23340        {
23341            "file": "lib/addons/p5.sound.js",
23342            "line": 11578,
23343            "description": "<p>Connect a source to the gain node.</p>\n",
23344            "itemtype": "method",
23345            "name": "setInput",
23346            "params": [
23347                {
23348                    "name": "src",
23349                    "description": "<p>p5.sound / Web Audio object with a sound\n                         output.</p>\n",
23350                    "type": "Object"
23351                }
23352            ],
23353            "class": "p5.Gain",
23354            "module": "p5.sound",
23355            "submodule": "p5.sound"
23356        },
23357        {
23358            "file": "lib/addons/p5.sound.js",
23359            "line": 11588,
23360            "description": "<p>Send output to a p5.sound or web audio object</p>\n",
23361            "itemtype": "method",
23362            "name": "connect",
23363            "params": [
23364                {
23365                    "name": "unit",
23366                    "description": "",
23367                    "type": "Object"
23368                }
23369            ],
23370            "class": "p5.Gain",
23371            "module": "p5.sound",
23372            "submodule": "p5.sound"
23373        },
23374        {
23375            "file": "lib/addons/p5.sound.js",
23376            "line": 11598,
23377            "description": "<p>Disconnect all output.</p>\n",
23378            "itemtype": "method",
23379            "name": "disconnect",
23380            "class": "p5.Gain",
23381            "module": "p5.sound",
23382            "submodule": "p5.sound"
23383        },
23384        {
23385            "file": "lib/addons/p5.sound.js",
23386            "line": 11606,
23387            "description": "<p>Set the output level of the gain node.</p>\n",
23388            "itemtype": "method",
23389            "name": "amp",
23390            "params": [
23391                {
23392                    "name": "volume",
23393                    "description": "<p>amplitude between 0 and 1.0</p>\n",
23394                    "type": "Number"
23395                },
23396                {
23397                    "name": "rampTime",
23398                    "description": "<p>create a fade that lasts rampTime</p>\n",
23399                    "type": "Number",
23400                    "optional": true
23401                },
23402                {
23403                    "name": "timeFromNow",
23404                    "description": "<p>schedule this event to happen\n                              seconds from now</p>\n",
23405                    "type": "Number",
23406                    "optional": true
23407                }
23408            ],
23409            "class": "p5.Gain",
23410            "module": "p5.sound",
23411            "submodule": "p5.sound"
23412        },
23413        {
23414            "file": "lib/addons/p5.sound.js",
23415            "line": 11684,
23416            "description": "<p>Connect to p5 objects or Web Audio Nodes</p>\n",
23417            "itemtype": "method",
23418            "name": "connect",
23419            "params": [
23420                {
23421                    "name": "unit",
23422                    "description": "",
23423                    "type": "Object"
23424                }
23425            ],
23426            "class": "p5.AudioVoice",
23427            "module": "p5.sound",
23428            "submodule": "p5.sound"
23429        },
23430        {
23431            "file": "lib/addons/p5.sound.js",
23432            "line": 11693,
23433            "description": "<p>Disconnect from soundOut</p>\n",
23434            "itemtype": "method",
23435            "name": "disconnect",
23436            "class": "p5.AudioVoice",
23437            "module": "p5.sound",
23438            "submodule": "p5.sound"
23439        },
23440        {
23441            "file": "lib/addons/p5.sound.js",
23442            "line": 11761,
23443            "description": "<p>Play tells the MonoSynth to start playing a note. This method schedules\nthe calling of .triggerAttack and .triggerRelease.</p>\n",
23444            "itemtype": "method",
23445            "name": "play",
23446            "params": [
23447                {
23448                    "name": "note",
23449                    "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",
23450                    "type": "String | Number"
23451                },
23452                {
23453                    "name": "velocity",
23454                    "description": "<p>velocity of the note to play (ranging from 0 to 1)</p>\n",
23455                    "type": "Number",
23456                    "optional": true
23457                },
23458                {
23459                    "name": "secondsFromNow",
23460                    "description": "<p>time from now (in seconds) at which to play</p>\n",
23461                    "type": "Number",
23462                    "optional": true
23463                },
23464                {
23465                    "name": "sustainTime",
23466                    "description": "<p>time to sustain before releasing the envelope</p>\n",
23467                    "type": "Number",
23468                    "optional": true
23469                }
23470            ],
23471            "class": "p5.MonoSynth",
23472            "module": "p5.sound",
23473            "submodule": "p5.sound"
23474        },
23475        {
23476            "file": "lib/addons/p5.sound.js",
23477            "line": 11783,
23478            "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",
23479            "params": [
23480                {
23481                    "name": "note",
23482                    "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",
23483                    "type": "String | Number"
23484                },
23485                {
23486                    "name": "velocity",
23487                    "description": "<p>velocity of the note to play (ranging from 0 to 1)</p>\n",
23488                    "type": "Number",
23489                    "optional": true
23490                },
23491                {
23492                    "name": "secondsFromNow",
23493                    "description": "<p>time from now (in seconds) at which to play</p>\n",
23494                    "type": "Number",
23495                    "optional": true
23496                }
23497            ],
23498            "itemtype": "method",
23499            "name": "triggerAttack",
23500            "class": "p5.MonoSynth",
23501            "module": "p5.sound",
23502            "submodule": "p5.sound"
23503        },
23504        {
23505            "file": "lib/addons/p5.sound.js",
23506            "line": 11806,
23507            "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",
23508            "params": [
23509                {
23510                    "name": "secondsFromNow",
23511                    "description": "<p>time to trigger the release</p>\n",
23512                    "type": "Number"
23513                }
23514            ],
23515            "itemtype": "method",
23516            "name": "triggerRelease",
23517            "class": "p5.MonoSynth",
23518            "module": "p5.sound",
23519            "submodule": "p5.sound"
23520        },
23521        {
23522            "file": "lib/addons/p5.sound.js",
23523            "line": 11819,
23524            "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",
23525            "itemtype": "method",
23526            "name": "setADSR",
23527            "params": [
23528                {
23529                    "name": "attackTime",
23530                    "description": "<p>Time (in seconds before envelope\n                              reaches Attack Level</p>\n",
23531                    "type": "Number"
23532                },
23533                {
23534                    "name": "decayTime",
23535                    "description": "<p>Time (in seconds) before envelope\n                              reaches Decay/Sustain Level</p>\n",
23536                    "type": "Number",
23537                    "optional": true
23538                },
23539                {
23540                    "name": "susRatio",
23541                    "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",
23542                    "type": "Number",
23543                    "optional": true
23544                },
23545                {
23546                    "name": "releaseTime",
23547                    "description": "<p>Time in seconds from now (defaults to 0)</p>\n",
23548                    "type": "Number",
23549                    "optional": true
23550                }
23551            ],
23552            "class": "p5.MonoSynth",
23553            "module": "p5.sound",
23554            "submodule": "p5.sound"
23555        },
23556        {
23557            "file": "lib/addons/p5.sound.js",
23558            "line": 11843,
23559            "description": "<p>Getters and Setters</p>\n",
23560            "itemtype": "property",
23561            "name": "attack",
23562            "type": "Number",
23563            "class": "p5.MonoSynth",
23564            "module": "p5.sound",
23565            "submodule": "p5.sound"
23566        },
23567        {
23568            "file": "lib/addons/p5.sound.js",
23569            "line": 11847,
23570            "itemtype": "property",
23571            "name": "decay",
23572            "type": "Number",
23573            "class": "p5.MonoSynth",
23574            "module": "p5.sound",
23575            "submodule": "p5.sound"
23576        },
23577        {
23578            "file": "lib/addons/p5.sound.js",
23579            "line": 11850,
23580            "itemtype": "property",
23581            "name": "sustain",
23582            "type": "Number",
23583            "class": "p5.MonoSynth",
23584            "module": "p5.sound",
23585            "submodule": "p5.sound"
23586        },
23587        {
23588            "file": "lib/addons/p5.sound.js",
23589            "line": 11853,
23590            "itemtype": "property",
23591            "name": "release",
23592            "type": "Number",
23593            "class": "p5.MonoSynth",
23594            "module": "p5.sound",
23595            "submodule": "p5.sound"
23596        },
23597        {
23598            "file": "lib/addons/p5.sound.js",
23599            "line": 11890,
23600            "description": "<p>MonoSynth amp</p>\n",
23601            "itemtype": "method",
23602            "name": "amp",
23603            "params": [
23604                {
23605                    "name": "vol",
23606                    "description": "<p>desired volume</p>\n",
23607                    "type": "Number"
23608                },
23609                {
23610                    "name": "rampTime",
23611                    "description": "<p>Time to reach new volume</p>\n",
23612                    "type": "Number",
23613                    "optional": true
23614                }
23615            ],
23616            "return": {
23617                "description": "new volume value",
23618                "type": "Number"
23619            },
23620            "class": "p5.MonoSynth",
23621            "module": "p5.sound",
23622            "submodule": "p5.sound"
23623        },
23624        {
23625            "file": "lib/addons/p5.sound.js",
23626            "line": 11904,
23627            "description": "<p>Connect to a p5.sound / Web Audio object.</p>\n",
23628            "itemtype": "method",
23629            "name": "connect",
23630            "params": [
23631                {
23632                    "name": "unit",
23633                    "description": "<p>A p5.sound or Web Audio object</p>\n",
23634                    "type": "Object"
23635                }
23636            ],
23637            "class": "p5.MonoSynth",
23638            "module": "p5.sound",
23639            "submodule": "p5.sound"
23640        },
23641        {
23642            "file": "lib/addons/p5.sound.js",
23643            "line": 11914,
23644            "description": "<p>Disconnect all outputs</p>\n",
23645            "itemtype": "method",
23646            "name": "disconnect",
23647            "class": "p5.MonoSynth",
23648            "module": "p5.sound",
23649            "submodule": "p5.sound"
23650        },
23651        {
23652            "file": "lib/addons/p5.sound.js",
23653            "line": 11922,
23654            "description": "<p>Get rid of the MonoSynth an
23654d free up its resources / memory.</p>\n",
23655            "itemtype": "method",
23656            "name": "dispose",
23657            "class": "p5.MonoSynth",
23658            "module": "p5.sound",
23659            "submodule": "p5.sound"
23660        },
23661        {
23662            "file": "lib/addons/p5.sound.js",
23663            "line": 11974,
23664            "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",
23665            "itemtype": "property",
23666            "name": "notes",
23667            "class": "p5.PolySynth",
23668            "module": "p5.sound",
23669            "submodule": "p5.sound"
23670        },
23671        {
23672            "file": "lib/addons/p5.sound.js",
23673            "line": 11986,
23674            "description": "<p>A PolySynth must have at least 1 voice, defaults to 8</p>\n",
23675            "itemtype": "property",
23676            "name": "polyvalue",
23677            "class": "p5.PolySynth",
23678            "module": "p5.sound",
23679            "submodule": "p5.sound"
23680        },
23681        {
23682            "file": "lib/addons/p5.sound.js",
23683            "line": 11991,
23684            "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",
23685            "itemtype": "property",
23686            "name": "AudioVoice",
23687            "class": "p5.PolySynth",
23688            "module": "p5.sound",
23689            "submodule": "p5.sound"
23690        },
23691        {
23692            "file": "lib/addons/p5.sound.js",
23693            "line": 12022,
23694            "description": "<p>Play a note by triggering noteAttack and noteRelease with sustain time</p>\n",
23695            "itemtype": "method",
23696            "name": "play",
23697            "params": [
23698                {
23699                    "name": "note",
23700                    "description": "<p>midi note to play (ranging from 0 to 127 - 60 being a middle C)</p>\n",
23701                    "type": "Number",
23702                    "optional": true
23703                },
23704                {
23705                    "name": "velocity",
23706                    "description": "<p>velocity of the note to play (ranging from 0 to 1)</p>\n",
23707                    "type": "Number",
23708                    "optional": true
23709                },
23710                {
23711                    "name": "secondsFromNow",
23712                    "description": "<p>time from now (in seconds) at which to play</p>\n",
23713                    "type": "Number",
23714                    "optional": true
23715                },
23716                {
23717                    "name": "sustainTime",
23718                    "description": "<p>time to sustain before releasing the envelope</p>\n",
23719                    "type": "Number",
23720                    "optional": true
23721                }
23722            ],
23723            "class": "p5.PolySynth",
23724            "module": "p5.sound",
23725            "submodule": "p5.sound"
23726        },
23727        {
23728            "file": "lib/addons/p5.sound.js",
23729            "line": 12036,
23730            "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",
23731            "itemtype": "method",
23732            "name": "noteADSR",
23733            "params": [
23734                {
23735                    "name": "note",
23736                    "description": "<p>Midi note on which ADSR should be set.</p>\n",
23737                    "type": "Number",
23738                    "optional": true
23739                },
23740                {
23741                    "name": "attackTime",
23742                    "description": "<p>Time (in seconds before envelope\n                              reaches Attack Level</p>\n",
23743                    "type": "Number",
23744                    "optional": true
23745                },
23746                {
23747                    "name": "decayTime",
23748                    "description": "<p>Time (in seconds) before envelope\n                              reaches Decay/Sustain Level</p>\n",
23749                    "type": "Number",
23750                    "optional": true
23751                },
23752                {
23753                    "name": "susRatio",
23754                    "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",
23755                    "type": "Number",
23756                    "optional": true
23757                },
23758                {
23759                    "name": "releaseTime",
23760                    "description": "<p>Time in seconds from now (defaults to 0)</p>\n",
23761                    "type": "Number",
23762                    "optional": true
23763                }
23764            ],
23765            "class": "p5.PolySynth",
23766            "module": "p5.sound",
23767            "submodule": "p5.sound"
23768        },
23769        {
23770            "file": "lib/addons/p5.sound.js",
23771            "line": 12064,
23772            "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",
23773            "itemtype": "method",
23774            "name": "setADSR",
23775            "params": [
23776                {
23777                    "name": "note",
23778                    "description": "<p>Midi note on which ADSR should be set.</p>\n",
23779                    "type": "Number",
23780                    "optional": true
23781                },
23782                {
23783                    "name": "attackTime",
23784                    "description": "<p>Time (in seconds before envelope\n                               reaches Attack Level</p>\n",
23785                    "type": "Number",
23786                    "optional": true
23787                },
23788                {
23789                    "name": "decayTime",
23790                    "description": "<p>Time (in seconds) before envelope\n                               reaches Decay/Sustain Level</p>\n",
23791                    "type": "Number",
23792                    "optional": true
23793                },
23794                {
23795                    "name": "susRatio",
23796                    "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",
23797                    "type": "Number",
23798                    "optional": true
23799                },
23800                {
23801                    "name": "releaseTime",
23802                    "description": "<p>Time in seconds from now (defaults to 0)</p>\n",
23803                    "type": "Number",
23804                    "optional": true
23805                }
23806            ],
23807            "class": "p5.PolySynth",
23808            "module": "p5.sound",
23809            "submodule": "p5.sound"
23810        },
23811        {
23812            "file": "lib/addons/p5.sound.js",
23813            "line": 12089,
23814            "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",
23815            "itemtype": "method",
23816            "name": "noteAttack",
23817            "params": [
23818                {
23819                    "name": "note",
23820                    "description": "<p>midi note on which attack should be triggered.</p>\n",
23821                    "type": "Number",
23822                    "optional": true
23823                },
23824                {
23825                    "name": "velocity",
23826                    "description": "<p>velocity of the note to play (ranging from 0 to 1)/</p>\n",
23827                    "type": "Number",
23828                    "optional": true
23829                },
23830                {
23831                    "name": "secondsFromNow",
23832                    "description": "<p>time from now (in seconds)</p>\n",
23833                    "type": "Number",
23834                    "optional": true
23835                }
23836            ],
23837            "class": "p5.PolySynth",
23838            "module": "p5.sound",
23839            "submodule": "p5.sound"
23840        },
23841        {
23842            "file": "lib/addons/p5.sound.js",
23843            "line": 12162,
23844            "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",
23845            "itemtype": "method",
23846            "name": "noteRelease",
23847            "params": [
23848                {
23849                    "name": "note",
23850                    "description": "<p>midi note on which attack should be triggered.</p>\n",
23851                    "type": "Number",
23852                    "optional": true
23853                },
23854                {
23855                    "name": "secondsFromNow",
23856                    "description": "<p>time to trigger the release</p>\n",
23857                    "type": "Number",
23858                    "optional": true
23859                }
23860            ],
23861            "class": "p5.PolySynth",
23862            "module": "p5.sound",
23863            "submodule": "p5.sound"
23864        },
23865        {
23866            "file": "lib/addons/p5.sound.js",
23867            "line": 12192,
23868            "description": "<p>Connect to a p5.sound / Web Audio object.</p>\n",
23869            "itemtype": "method",
23870            "name": "connect",
23871            "params": [
23872                {
23873                    "name": "unit",
23874                    "description": "<p>A p5.sound or Web Audio object</p>\n",
23875                    "type": "Object"
23876                }
23877            ],
23878            "class": "p5.PolySynth",
23879            "module": "p5.sound",
23880            "submodule": "p5.sound"
23881        },
23882        {
23883            "file": "lib/addons/p5.sound.js",
23884            "line": 12202,
23885            "description": "<p>Disconnect all outputs</p>\n",
23886            "itemtype": "method",
23887            "name": "disconnect",
23888            "class": "p5.PolySynth",
23889            "module": "p5.sound",
23890            "submodule": "p5.sound"
23891        },
23892        {
23893            "file": "lib/addons/p5.sound.js",
23894            "line": 12210,
23895            "description": "<p>Get rid of the MonoSynth and free up its resources / memory.</p>\n",
23896            "itemtype": "method",
23897            "name": "dispose",
23898            "class": "p5.PolySynth",
23899            "module": "p5.sound",
23900            "submodule": "p5.sound"
23901        },
23902        {
23903            "file": "lib/addons/p5.sound.js",
23904            "line": 12276,
23905            "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",
23906            "itemtype": "property",
23907            "name": "WaveShaperNode",
23908            "type": "AudioNode",
23909            "class": "p5.Distortion",
23910            "module": "p5.sound",
23911            "submodule": "p5.sound"
23912        },
23913        {
23914            "file": "lib/addons/p5.sound.js",
23915            "line": 12291,
23916            "description": "<p>Process a sound source, optionally specify amount and oversample values.</p>\n",
23917            "itemtype": "method",
23918            "name": "process",
23919            "params": [
23920                {
23921                    "name": "amount",
23922                    "description": "<p>Unbounded distortion amount.\n                               Normal values range from 0-1.</p>\n",
23923                    "type": "Number",
23924                    "optional": true,
23925                    "optdefault": "0.25"
23926                },
23927                {
23928                    "name": "oversample",
23929                    "description": "<p>&#39;none&#39;, &#39;2x&#39;, or &#39;4x&#39;.</p>\n",
23930                    "type": "String",
23931                    "optional": true,
23932                    "optdefault": "'none'"
23933                }
23934            ],
23935            "class": "p5.Distortion",
23936            "module": "p5.sound",
23937            "submodule": "p5.sound"
23938        },
23939        {
23940            "file": "lib/addons/p5.sound.js",
23941            "line": 12303,
23942            "description": "<p>Set the amount and oversample of the waveshaper distortion.</p>\n",
23943            "itemtype": "method",
23944            "name": "set",
23945            "params": [
23946                {
23947                    "name": "amount",
23948                    "description": "<p>Unbounded distortion amount.\n                               Normal values range from 0-1.</p>\n",
23949                    "type": "Number",
23950                    "optional": true,
23951                    "optdefault": "0.25"
23952                },
23953                {
23954                    "name": "oversample",
23955                    "description": "<p>&#39;none&#39;, &#39;2x&#39;, or &#39;4x&#39;.</p>\n",
23956                    "type": "String",
23957                    "optional": true,
23958                    "optdefault": "'none'"
23959                }
23960            ],
23961            "class": "p5.Distortion",
23962            "module": "p5.sound",
23963            "submodule": "p5.sound"
23964        },
23965        {
23966            "file": "lib/addons/p5.sound.js",
23967            "line": 12321,
23968            "description": "<p>Return the distortion amount, typically between 0-1.</p>\n",
23969            "itemtype": "method",
23970            "name": "getAmount",
23971            "return": {
23972                "description": "Unbounded distortion amount.\n                 Normal values range from 0-1.",
23973                "type": "Number"
23974            },
23975            "class": "p5.Distortion",
23976            "module": "p5.sound",
23977            "submodule": "p5.sound"
23978        },
23979        {
23980            "file": "lib/addons/p5.sound.js",
23981            "line": 12331,
23982            "description": "<p>Return the oversampling.</p>\n",
23983            "itemtype": "method",
23984            "name": "getOversample",
23985            "return": {
23986                "description": "Oversample can either be 'none', '2x', or '4x'.",
23987                "type": "String"
23988            },
23989            "class": "p5.Distortion",
23990            "module": "p5.sound",
23991            "submodule": "p5.sound"
23992        }
23993    ],
23994    "warnings": [
23995        {
23996            "message": "unknown tag: alt",
23997            "line": " src/color/creating_reading.js:16"
23998        },
23999        {
24000            "message": "unknown tag: alt",
24001            "line": " src/color/creating_reading.js:61"
24002        },
24003        {
24004            "message": "unknown tag: alt",
24005            "line": " src/color/creating_reading.js:91"
24006        },
24007        {
24008            "message": "unknown tag: alt",
24009            "line": " src/color/creating_reading.js:121"
24010        },
24011        {
24012            "message": "unknown tag: alt",
24013            "line": " src/color/creating_reading.js:319"
24014        },
24015        {
24016            "message": "unknown tag: alt",
24017            "line": " src/color/creating_reading.js:350"
24018        },
24019        {
24020            "message": "unknown tag: alt",
24021            "line": " src/color/creating_reading.js:387"
24022        },
24023        {
24024            "message": "unknown tag: alt",
24025            "line": " src/color/creating_reading.js:484"
24026        },
24027        {
24028            "message": "unknown tag: alt",
24029            "line": " src/color/creating_reading.js:514"
24030        },
24031        {
24032            "message": "unknown tag: alt",
24033            "line": " src/color/creating_reading.js:554"
24034        },
24035        {
24036            "message": "unknown tag: alt",
24037            "line": " src/color/p5.Color.js:52"
24038        },
24039        {
24040            "message": "unknown tag: alt",
24041            "line": " src/color/p5.Color.js:247"
24042        },
24043        {
24044            "message": "unknown tag: alt",
24045            "line": " src/color/p5.Color.js:274"
24046        },
24047        {
24048            "message": "unknown tag: alt",
24049            "line": " src/color/p5.Color.js:301"
24050        },
24051        {
24052            "message": "unknown tag: alt",
24053            "line": " src/color/p5.Color.js:328"
24054        },
24055        {
24056            "message": "unknown tag: alt",
24057            "line": " src/color/p5.Color.js:759"
24058        },
24059        {
24060            "message": "unknown tag: alt",
24061            "line": " src/color/setting.js:15"
24062        },
24063        {
24064            "message": "unknown tag: alt",
24065            "line": " src/color/setting.js:185"
24066        },
24067        {
24068            "message": "unknown tag: alt",
24069            "line": " src/color/setting.js:223"
24070        },
24071        {
24072            "message": "unknown tag: alt",
24073            "line": " src/color/setting.js:344"
24074        },
24075        {
24076            "message": "unknown tag: alt",
24077            "line": " src/color/setting.js:501"
24078        },
24079        {
24080            "message": "unknown tag: alt",
24081            "line": " src/color/setting.js:542"
24082        },
24083        {
24084            "message": "unknown tag: alt",
24085            "line": " src/color/setting.js:582"
24086        },
24087        {
24088            "message": "unknown tag: alt",
24089            "line": " src/core/2d_primitives.js:16"
24090        },
24091        {
24092            "message": "unknown tag: alt",
24093            "line": " src/core/2d_primitives.js:133"
24094        },
24095        {
24096            "message": "unknown tag: alt",
24097            "line": " src/core/2d_primitives.js:188"
24098        },
24099        {
24100            "message": "unknown tag: alt",
24101            "line": " src/core/2d_primitives.js:244"
24102        },
24103        {
24104            "message": "unknown tag: alt",
24105            "line": " src/core/2d_primitives.js:279"
24106        },
24107        {
24108            "message": "unknown tag: alt",
24109            "line": " src/core/2d_primitives.js:333"
24110        },
24111        {
24112            "message": "unknown tag: alt",
24113            "line": " src/core/2d_primitives.js:416"
24114        },
24115        {
24116            "message": "unknown tag: alt",
24117            "line": " src/core/attributes.js:14"
24118        },
24119        {
24120            "message": "unknown tag: alt",
24121            "line": " src/core/attributes.js:83"
24122        },
24123        {
24124            "message": "unknown tag: alt",
24125            "line": " src/core/attributes.js:111"
24126        },
24127        {
24128            "message": "unknown tag: alt",
24129            "line": " src/core/attributes.js:180"
24130        },
24131        {
24132            "message": "unknown tag: alt",
24133            "line": " src/core/attributes.js:209"
24134        },
24135        {
24136            "message": "unknown tag: alt",
24137            "line": " src/core/attributes.js:246"
24138        },
24139        {
24140            "message": "unknown tag: alt",
24141            "line": " src/core/attributes.js:313"
24142        },
24143        {
24144            "message": "unknown tag: alt",
24145            "line": " src/core/constants.js:34"
24146        },
24147        {
24148            "message": "unknown tag: alt",
24149            "line": " src/core/constants.js:53"
24150        },
24151        {
24152            "message": "unknown tag: alt",
24153            "line": " src/core/constants.js:72"
24154        },
24155        {
24156            "message": "unknown tag: alt",
24157            "line": " src/core/constants.js:91"
24158        },
24159        {
24160            "message": "unknown tag: alt",
24161            "line": " src/core/constants.js:110"
24162        },
24163        {
24164            "message": "unknown tag: alt",
24165            "line": " src/core/core.js:49"
24166        },
24167        {
24168            "message": "unknown tag: alt",
24169            "line": " src/core/core.js:90"
24170        },
24171        {
24172            "message": "unknown tag: alt",
24173            "line": " src/core/core.js:121"
24174        },
24175        {
24176            "message": "unknown tag: alt",
24177            "line": " src/core/core.js:407"
24178        },
24179        {
24180            "message": "unknown tag: alt",
24181            "line": " src/core/curves.js:13"
24182        },
24183        {
24184            "message": "unknown tag: alt",
24185            "line": " src/core/curves.js:92"
24186        },
24187        {
24188            "message": "unknown tag: alt",
24189            "line": " src/core/curves.js:135"
24190        },
24191        {
24192            "message": "unknown tag: alt",
24193            "line": " src/core/curves.js:190"
24194        },
24195        {
24196            "message": "unknown tag: alt",
24197            "line": " src/core/curves.js:269"
24198        },
24199        {
24200            "message": "unknown tag: alt",
24201            "line": " src/core/curves.js:360"
24202        },
24203        {
24204            "message": "unknown tag: alt",
24205            "line": " src/core/curves.js:402"
24206        },
24207        {
24208            "message": "unknown tag: alt",
24209            "line": " src/core/curves.js:497"
24210        },
24211        {
24212            "message": "unknown tag: alt",
24213            "line": " src/core/environment.js:22"
24214        },
24215        {
24216            "message": "unknown tag: alt",
24217            "line": " src/core/environment.js:49"
24218        },
24219        {
24220            "message": "unknown tag: alt",
24221            "line": " src/core/environment.js:77"
24222        },
24223        {
24224            "message": "unknown tag: alt",
24225            "line": " src/core/environment.js:109"
24226        },
24227        {
24228            "message": "unknown tag: alt",
24229            "line": " src/core/environment.js:170"
24230        },
24231        {
24232            "message": "unknown tag: alt",
24233            "line": " src/core/environment.js:268"
24234        },
24235        {
24236            "message": "unknown tag: alt",
24237            "line": " src/core/environment.js:293"
24238        },
24239        {
24240            "message": "unknown tag: alt",
24241            "line": " src/core/environment.js:310"
24242        },
24243        {
24244            "message": "unknown tag: alt",
24245            "line": " src/core/environment.js:327"
24246        },
24247        {
24248            "message": "unknown tag: alt",
24249            "line": " src/core/environment.js:343"
24250        },
24251        {
24252            "message": "unknown tag: alt",
24253            "line": " src/core/environment.js:359"
24254        },
24255        {
24256            "message": "unknown tag: alt",
24257            "line": " src/core/environment.js:437"
24258        },
24259        {
24260            "message": "replacing incorrect tag: returns with return",
24261            "line": " src/core/environment.js:488"
24262        },
24263        {
24264            "message": "unknown tag: alt",
24265            "line": " src/core/environment.js:488"
24266        },
24267        {
24268            "message": "replacing incorrect tag: returns with return",
24269            "line": " src/core/environment.js:534"
24270        },
24271        {
24272            "message": "unknown tag: alt",
24273            "line": " src/core/environment.js:534"
24274        },
24275        {
24276            "message": "unknown tag: alt",
24277            "line": " src/core/environment.js:591"
24278        },
24279        {
24280            "message": "unknown tag: alt",
24281            "line": " src/core/environment.js:622"
24282        },
24283        {
24284            "message": "unknown tag: alt",
24285            "line": " src/core/environment.js:645"
24286        },
24287        {
24288            "message": "unknown tag: alt",
24289            "line": " src/core/p5.Element.js:51"
24290        },
24291        {
24292            "message": "unknown tag: alt",
24293            "line": " src/core/p5.Element.js:116"
24294        },
24295        {
24296            "message": "unknown tag: alt",
24297            "line": " src/core/p5.Element.js:153"
24298        },
24299        {
24300            "message": "unknown tag: alt",
24301            "line": " src/core/p5.Element.js:188"
24302        },
24303        {
24304            "message": "unknown tag: alt",
24305            "line": " src/core/p5.Element.js:238"
24306        },
24307        {
24308            "message": "unknown tag: alt",
24309            "line": " src/core/p5.Element.js:287"
24310        },
24311        {
24312            "message": "unknown tag: alt",
24313            "line": " src/core/p5.Element.js:353"
24314        },
24315        {
24316            "message": "unknown tag: alt",
24317            "line": " src/core/p5.Element.js:406"
24318        },
24319        {
24320            "message": "unknown tag: alt",
24321            "line": " src/core/p5.Element.js:460"
24322        },
24323        {
24324            "message": "unknown tag: alt",
24325            "line": " src/core/p5.Element.js:519"
24326        },
24327        {
24328            "message": "unknown tag: alt",
24329            "line": " src/core/p5.Element.js:562"
24330        },
24331        {
24332            "message": "unknown tag: alt",
24333            "line": " src/core/p5.Element.js:629"
24334        },
24335        {
24336            "message": "unknown tag: alt",
24337            "line": " src/core/p5.Element.js:664"
24338        },
24339        {
24340            "message": "unknown tag: alt",
24341            "line": " src/core/p5.Element.js:706"
24342        },
24343        {
24344            "message": "unknown tag: alt",
24345            "line": " src/core/p5.Element.js:755"
24346        },
24347        {
24348            "message": "unknown tag: alt",
24349            "line": " src/core/p5.Element.js:796"
24350        },
24351        {
24352            "message": "unknown tag: alt",
24353            "line": " src/core/p5.Element.js:846"
24354        },
24355        {
24356            "message": "unknown tag: alt",
24357            "line": " src/core/p5.Element.js:884"
24358        },
24359        {
24360            "message": "unknown tag: alt",
24361            "line": " src/core/p5.Element.js:922"
24362        },
24363        {
24364            "message": "unknown tag: alt",
24365            "line": " src/core/p5.Graphics.js:65"
24366        },
24367        {
24368            "message": "unknown tag: alt",
24369            "line": " src/core/rendering.js:17"
24370        },
24371        {
24372            "message": "unknown tag: alt",
24373            "line": " src/core/rendering.js:119"
24374        },
24375        {
24376            "message": "unknown tag: alt",
24377            "line": " src/core/rendering.js:172"
24378        },
24379        {
24380            "message": "unknown tag: alt",
24381            "line": " src/core/rendering.js:195"
24382        },
24383        {
24384            "message": "unknown tag: alt",
24385            "line": " src/core/rendering.js:234"
24386        },
24387        {
24388            "message": "unknown tag: alt",
24389            "line": " src/core/structure.js:15"
24390        },
24391        {
24392            "message": "unknown tag: alt",
24393            "line": " src/core/structure.js:77"
24394        },
24395        {
24396            "message": "unknown tag: alt",
24397            "line": " src/core/structure.js:132"
24398        },
24399        {
24400            "message": "unknown tag: alt",
24401            "line": " src/core/structure.js:197"
24402        },
24403        {
24404            "message": "unknown tag: alt",
24405            "line": " src/core/structure.js:271"
24406        },
24407        {
24408            "message": "unknown tag: alt",
24409            "line": " src/core/transform.js:13"
24410        },
24411        {
24412            "message": "unknown tag: alt",
24413            "line": " src/core/transform.js:135"
24414        },
24415        {
24416            "message": "unknown tag: alt",
24417            "line": " src/core/transform.js:161"
24418        },
24419        {
24420            "message": "unknown tag: alt",
24421            "line": " src/core/transform.js:201"
24422        },
24423        {
24424            "message": "unknown tag: alt",
24425            "line": " src/core/transform.js:231"
24426        },
24427        {
24428            "message": "unknown tag: alt",
24429            "line": " src/core/transform.js:261"
24430        },
24431        {
24432            "message": "unknown tag: alt",
24433            "line": " src/core/transform.js:291"
24434        },
24435        {
24436            "message": "unknown tag: alt",
24437            "line": " src/core/transform.js:366"
24438        },
24439        {
24440            "message": "unknown tag: alt",
24441            "line": " src/core/transform.js:405"
24442        },
24443        {
24444            "message": "unknown tag: alt",
24445            "line": " src/core/transform.js:444"
24446        },
24447        {
24448            "message": "unknown tag: alt",
24449            "line": " src/core/vertex.js:22"
24450        },
24451        {
24452            "message": "unknown tag: alt",
24453            "line": " src/core/vertex.js:70"
24454        },
24455        {
24456            "message": "unknown tag: alt",
24457            "line": " src/core/vertex.js:270"
24458        },
24459        {
24460            "message": "unknown tag: alt",
24461            "line": " src/core/vertex.js:356"
24462        },
24463        {
24464            "message": "unknown tag: alt",
24465            "line": " src/core/vertex.js:407"
24466        },
24467        {
24468            "message": "unknown tag: alt",
24469            "line": " src/core/vertex.js:467"
24470        },
24471        {
24472            "message": "unknown tag: alt",
24473            "line": " src/core/vertex.js:553"
24474        },
24475        {
24476            "message": "unknown tag: alt",
24477            "line": " src/core/vertex.js:645"
24478        },
24479        {
24480            "message": "unknown tag: alt",
24481            "line": " src/core/vertex.js:645"
24482        },
24483        {
24484            "message": "unknown tag: alt",
24485            "line": " src/core/vertex.js:645"
24486        },
24487        {
24488            "message": "unknown tag: alt",
24489            "line": " src/core/vertex.js:645"
24490        },
24491        {
24492            "message": "unknown tag: alt",
24493            "line": " src/events/acceleration.js:91"
24494        },
24495        {
24496            "message": "unknown tag: alt",
24497            "line": " src/events/acceleration.js:125"
24498        },
24499        {
24500            "message": "unknown tag: alt",
24501            "line": " src/events/acceleration.js:158"
24502        },
24503        {
24504            "message": "unknown tag: alt",
24505            "line": " src/events/acceleration.js:194"
24506        },
24507        {
24508            "message": "unknown tag: alt",
24509            "line": " src/events/acceleration.js:239"
24510        },
24511        {
24512            "message": "unknown tag: alt",
24513            "line": " src/events/acceleration.js:283"
24514        },
24515        {
24516            "message": "unknown tag: alt",
24517            "line": " src/events/acceleration.js:374"
24518        },
24519        {
24520            "message": "unknown tag: alt",
24521            "line": " src/events/acceleration.js:405"
24522        },
24523        {
24524            "message": "unknown tag: alt",
24525            "line": " src/events/acceleration.js:464"
24526        },
24527        {
24528            "message": "unknown tag: alt",
24529            "line": " src/events/keyboard.js:18"
24530        },
24531        {
24532            "message": "unknown tag: alt",
24533            "line": " src/events/keyboard.js:45"
24534        },
24535        {
24536            "message": "unknown tag: alt",
24537            "line": " src/events/keyboard.js:74"
24538        },
24539        {
24540            "message": "unknown tag: alt",
24541            "line": " src/events/keyboard.js:107"
24542        },
24543        {
24544            "message": "unknown tag: alt",
24545            "line": " src/events/keyboard.js:198"
24546        },
24547        {
24548            "message": "unknown tag: alt",
24549            "line": " src/events/keyboard.js:254"
24550        },
24551        {
24552            "message": "unknown tag: alt",
24553            "line": " src/events/keyboard.js:318"
24554        },
24555        {
24556            "message": "unknown tag: alt",
24557            "line": " src/events/mouse.js:22"
24558        },
24559        {
24560            "message": "unknown tag: alt",
24561            "line": " src/events/mouse.js:48"
24562        },
24563        {
24564            "message": "unknown tag: alt",
24565            "line": " src/events/mouse.js:74"
24566        },
24567        {
24568            "message": "unknown tag: alt",
24569            "line": " src/events/mouse.js:105"
24570        },
24571        {
24572            "message": "unknown tag: alt",
24573            "line": " src/events/mouse.js:135"
24574        },
24575        {
24576            "message": "unknown tag: alt",
24577            "line": " src/events/mouse.js:172"
24578        },
24579        {
24580            "message": "unknown tag: alt",
24581            "line": " src/events/mouse.js:209"
24582        },
24583        {
24584            "message": "unknown tag: alt",
24585            "line": " src/events/mouse.js:249"
24586        },
24587        {
24588            "message": "unknown tag: alt",
24589            "line": " src/events/mouse.js:290"
24590        },
24591        {
24592            "message": "unknown tag: alt",
24593            "line": " src/events/mouse.js:329"
24594        },
24595        {
24596            "message": "unknown tag: alt",
24597            "line": " src/events/mouse.js:418"
24598        },
24599        {
24600            "message": "unknown tag: alt",
24601            "line": " src/events/mouse.js:462"
24602        },
24603        {
24604            "message": "unknown tag: alt",
24605            "line": " src/events/mouse.js:532"
24606        },
24607        {
24608            "message": "unknown tag: alt",
24609            "line": " src/events/mouse.js:598"
24610        },
24611        {
24612            "message": "unknown tag: alt",
24613            "line": " src/events/mouse.js:665"
24614        },
24615        {
24616            "message": "unknown tag: alt",
24617            "line": " src/events/mouse.js:724"
24618        },
24619        {
24620            "message": "unknown tag: alt",
24621            "line": " src/events/mouse.js:782"
24622        },
24623        {
24624            "message": "unknown tag: alt",
24625            "line": " src/events/touch.js:57"
24626        },
24627        {
24628            "message": "unknown tag: alt",
24629            "line": " src/events/touch.js:120"
24630        },
24631        {
24632            "message": "unknown tag: alt",
24633            "line": " src/events/touch.js:182"
24634        },
24635        {
24636            "message": "unknown tag: alt",
24637            "line": " src/image/image.js:18"
24638        },
24639        {
24640            "message": "unknown tag: alt",
24641            "line": " src/image/image.js:98"
24642        },
24643        {
24644            "message": "unknown tag: alt",
24645            "line": " src/image/image.js:193"
24646        },
24647        {
24648            "message": "unknown tag: alt",
24649            "line": " src/image/loading_displaying.js:17"
24650        },
24651        {
24652            "message": "replacing incorrect tag: returns with return",
24653            "line": " src/image/loading_displaying.js:108"
24654        },
24655        {
24656            "message": "unknown tag: alt",
24657            "line": " src/image/loading_displaying.js:125"
24658        },
24659        {
24660            "message": "unknown tag: alt",
24661            "line": " src/image/loading_displaying.js:296"
24662        },
24663        {
24664            "message": "unknown tag: alt",
24665            "line": " src/image/loading_displaying.js:396"
24666        },
24667        {
24668            "message": "unknown tag: alt",
24669            "line": " src/image/loading_displaying.js:462"
24670        },
24671        {
24672            "message": "unknown tag: alt",
24673            "line": " src/image/p5.Image.js:90"
24674        },
24675        {
24676            "message": "unknown tag: alt",
24677            "line": " src/image/p5.Image.js:117"
24678        },
24679        {
24680            "message": "unknown tag: alt",
24681            "line": " src/image/p5.Image.js:151"
24682        },
24683        {
24684            "message": "unknown tag: alt",
24685            "line": " src/image/p5.Image.js:230"
24686        },
24687        {
24688            "message": "unknown tag: alt",
24689            "line": " src/image/p5.Image.js:266"
24690        },
24691        {
24692            "message": "unknown tag: alt",
24693            "line": " src/image/p5.Image.js:314"
24694        },
24695        {
24696            "message": "unknown tag: alt",
24697            "line": " src/image/p5.Image.js:359"
24698        },
24699        {
24700            "message": "unknown tag: alt",
24701            "line": " src/image/p5.Image.js:397"
24702        },
24703        {
24704            "message": "unknown tag: alt",
24705            "line": " src/image/p5.Image.js:481"
24706        },
24707        {
24708            "message": "unknown tag: alt",
24709            "line": " src/image/p5.Image.js:561"
24710        },
24711        {
24712            "message": "unknown tag: alt",
24713            "line": " src/image/p5.Image.js:624"
24714        },
24715        {
24716            "message": "unknown tag: alt",
24717            "line": " src/image/p5.Image.js:660"
24718        },
24719        {
24720            "message": "unknown tag: alt",
24721            "line": " src/image/p5.Image.js:782"
24722        },
24723        {
24724            "message": "unknown tag: alt",
24725            "line": " src/image/pixels.js:14"
24726        },
24727        {
24728            "message": "unknown tag: alt",
24729            "line": " src/image/pixels.js:83"
24730        },
24731        {
24732            "message": "unknown tag: alt",
24733            "line": " src/image/pixels.js:177"
24734        },
24735        {
24736            "message": "unknown tag: alt",
24737            "line": " src/image/pixels.js:236"
24738        },
24739        {
24740            "message": "unknown tag: alt",
24741            "line": " src/image/pixels.js:415"
24742        },
24743        {
24744            "message": "unknown tag: alt",
24745            "line": " src/image/pixels.js:491"
24746        },
24747        {
24748            "message": "unknown tag: alt",
24749            "line": " src/image/pixels.js:528"
24750        },
24751        {
24752            "message": "unknown tag: alt",
24753            "line": " src/image/pixels.js:602"
24754        },
24755        {
24756            "message": "unknown tag: alt",
24757            "line": " src/io/files.js:19"
24758        },
24759        {
24760            "message": "unknown tag: alt",
24761            "line": " src/io/files.js:170"
24762        },
24763        {
24764            "message": "unknown tag: alt",
24765            "line": " src/io/files.js:271"
24766        },
24767        {
24768            "message": "unknown tag: alt",
24769            "line": " src/io/files.js:603"
24770        },
24771        {
24772            "message": "replacing incorrect tag: returns with return",
24773            "line": " src/io/files.js:704"
24774        },
24775        {
24776            "message": "unknown tag: alt",
24777            "line": " src/io/files.js:704"
24778        },
24779        {
24780            "message": "unknown tag: alt",
24781            "line": " src/io/files.js:1457"
24782        },
24783        {
24784            "message": "unknown tag: alt",
24785            "line": " src/io/files.js:1509"
24786        },
24787        {
24788            "message": "unknown tag: alt",
24789            "line": " src/io/files.js:1571"
24790        },
24791        {
24792            "message": "unknown tag: alt",
24793            "line": " src/io/p5.Table.js:56"
24794        },
24795        {
24796            "message": "unknown tag: alt",
24797            "line": " src/io/p5.Table.js:119"
24798        },
24799        {
24800            "message": "unknown tag: alt",
24801            "line": " src/io/p5.Table.js:167"
24802        },
24803        {
24804            "message": "unknown tag: alt",
24805            "line": " src/io/p5.Table.js:213"
24806        },
24807        {
24808            "message": "unknown tag: alt",
24809            "line": " src/io/p5.Table.js:262"
24810        },
24811        {
24812            "message": "unknown tag: alt",
24813            "line": " src/io/p5.Table.js:327"
24814        },
24815        {
24816            "message": "unknown tag: alt",
24817            "line": " src/io/p5.Table.js:522"
24818        },
24819        {
24820            "message": "unknown tag: alt",
24821            "line": " src/io/p5.Table.js:575"
24822        },
24823        {
24824            "message": "unknown tag: alt",
24825            "line": " src/io/p5.Table.js:617"
24826        },
24827        {
24828            "message": "unknown tag: alt",
24829            "line": " src/io/p5.Table.js:878"
24830        },
24831        {
24832            "message": "unknown tag: alt",
24833            "line": " src/io/p5.Table.js:944"
24834        },
24835        {
24836            "message": "unknown tag: alt",
24837            "line": " src/io/p5.Table.js:994"
24838        },
24839        {
24840            "message": "unknown tag: alt",
24841            "line": " src/io/p5.Table.js:1040"
24842        },
24843        {
24844            "message": "unknown tag: alt",
24845            "line": " src/io/p5.Table.js:1085"
24846        },
24847        {
24848            "message": "unknown tag: alt",
24849            "line": " src/io/p5.Table.js:1132"
24850        },
24851        {
24852            "message": "unknown tag: alt",
24853            "line": " src/io/p5.Table.js:1177"
24854        },
24855        {
24856            "message": "unknown tag: alt",
24857            "line": " src/io/p5.Table.js:1230"
24858        },
24859        {
24860            "message": "unknown tag: alt",
24861            "line": " src/io/p5.Table.js:1294"
24862        },
24863        {
24864            "message": "unknown tag: alt",
24865            "line": " src/io/p5.TableRow.js:42"
24866        },
24867        {
24868            "message": "unknown tag: alt",
24869            "line": " src/io/p5.TableRow.js:104"
24870        },
24871        {
24872            "message": "unknown tag: alt",
24873            "line": " src/io/p5.TableRow.js:148"
24874        },
24875        {
24876            "message": "unknown tag: alt",
24877            "line": " src/io/p5.TableRow.js:193"
24878        },
24879        {
24880            "message": "unknown tag: alt",
24881            "line": " src/io/p5.TableRow.js:241"
24882        },
24883        {
24884            "message": "unknown tag: alt",
24885            "line": " src/io/p5.TableRow.js:297"
24886        },
24887        {
24888            "message": "unknown tag: alt",
24889            "line": " src/io/p5.XML.js:11"
24890        },
24891        {
24892            "message": "unknown tag: alt",
24893            "line": " src/math/calculation.js:12"
24894        },
24895        {
24896            "message": "unknown tag: alt",
24897            "line": " src/math/calculation.js:36"
24898        },
24899        {
24900            "message": "unknown tag: alt",
24901            "line": " src/math/calculation.js:76"
24902        },
24903        {
24904            "message": "unknown tag: alt",
24905            "line": " src/math/calculation.js:121"
24906        },
24907        {
24908            "message": "unknown tag: alt",
24909            "line": " src/math/calculation.js:190"
24910        },
24911        {
24912            "message": "unknown tag: alt",
24913            "line": " src/math/calculation.js:240"
24914        },
24915        {
24916            "message": "unknown tag: alt",
24917            "line": " src/math/calculation.js:279"
24918        },
24919        {
24920            "message": "unknown tag: alt",
24921            "line": " src/math/calculation.js:324"
24922        },
24923        {
24924            "message": "unknown tag: alt",
24925            "line": " src/math/calculation.js:379"
24926        },
24927        {
24928            "message": "unknown tag: alt",
24929            "line": " src/math/calculation.js:418"
24930        },
24931        {
24932            "message": "unknown tag: alt",
24933            "line": " src/math/calculation.js:474"
24934        },
24935        {
24936            "message": "unknown tag: alt",
24937            "line": " src/math/calculation.js:524"
24938        },
24939        {
24940            "message": "unknown tag: alt",
24941            "line": " src/math/calculation.js:574"
24942        },
24943        {
24944            "message": "unknown tag: alt",
24945            "line": " src/math/calculation.js:627"
24946        },
24947        {
24948            "message": "unknown tag: alt",
24949            "line": " src/math/calculation.js:661"
24950        },
24951        {
24952            "message": "unknown tag: alt",
24953            "line": " src/math/calculation.js:700"
24954        },
24955        {
24956            "message": "unknown tag: alt",
24957            "line": " src/math/calculation.js:747"
24958        },
24959        {
24960            "message": "unknown tag: alt",
24961            "line": " src/math/math.js:12"
24962        },
24963        {
24964            "message": "unknown tag: alt",
24965            "line": " src/math/noise.js:40"
24966        },
24967        {
24968            "message": "unknown tag: alt",
24969            "line": " src/math/noise.js:187"
24970        },
24971        {
24972            "message": "unknown tag: alt",
24973            "line": " src/math/noise.js:253"
24974        },
24975        {
24976            "message": "unknown tag: alt",
24977            "line": " src/math/p5.Vector.js:12"
24978        },
24979        {
24980            "message": "unknown tag: alt",
24981            "line": " src/math/random.js:48"
24982        },
24983        {
24984            "message": "unknown tag: alt",
24985            "line": " src/math/random.js:79"
24986        },
24987        {
24988            "message": "unknown tag: alt",
24989            "line": " src/math/random.js:166"
24990        },
24991        {
24992            "message": "unknown tag: alt",
24993            "line": " src/math/trigonometry.js:124"
24994        },
24995        {
24996            "message": "unknown tag: alt",
24997            "line": " src/math/trigonometry.js:160"
24998        },
24999        {
25000            "message": "unknown tag: alt",
25001            "line": " src/math/trigonometry.js:188"
25002        },
25003        {
25004            "message": "unknown tag: alt",
25005            "line": " src/math/trigonometry.js:216"
25006        },
25007        {
25008            "message": "unknown tag: alt",
25009            "line": " src/math/trigonometry.js:296"
25010        },
25011        {
25012            "message": "replacing incorrect tag: returns with return",
25013            "line": " src/math/trigonometry.js:332"
25014        },
25015        {
25016            "message": "replacing incorrect tag: returns with return",
25017            "line": " src/math/trigonometry.js:347"
25018        },
25019        {
25020            "message": "replacing incorrect tag: returns with return",
25021            "line": " src/math/trigonometry.js:362"
25022        },
25023        {
25024            "message": "unknown tag: alt",
25025            "line": " src/typography/attributes.js:13"
25026        },
25027        {
25028            "message": "unknown tag: alt",
25029            "line": " src/typography/attributes.js:60"
25030        },
25031        {
25032            "message": "unknown tag: alt",
25033            "line": " src/typography/attributes.js:98"
25034        },
25035        {
25036            "message": "unknown tag: alt",
25037            "line": " src/typography/attributes.js:130"
25038        },
25039        {
25040            "message": "unknown tag: alt",
25041            "line": " src/typography/attributes.js:165"
25042        },
25043        {
25044            "message": "unknown tag: alt",
25045            "line": " src/typography/loading_displaying.js:16"
25046        },
25047        {
25048            "message": "unknown tag: alt",
25049            "line": " src/typography/loading_displaying.js:143"
25050        },
25051        {
25052            "message": "unknown tag: alt",
25053            "line": " src/typography/loading_displaying.js:202"
25054        },
25055        {
25056            "message": "unknown tag: alt",
25057            "line": " src/typography/p5.Font.js:43"
25058        },
25059        {
25060            "message": "unknown tag: alt",
25061            "line": " src/utilities/conversion.js:12"
25062        },
25063        {
25064            "message": "unknown tag: alt",
25065            "line": " src/utilities/string_functions.js:15"
25066        },
25067        {
25068            "message": "unknown tag: alt",
25069            "line": " src/utilities/string_functions.js:44"
25070        },
25071        {
25072            "message": "unknown tag: alt",
25073            "line": " src/utilities/string_functions.js:132"
25074        },
25075        {
25076            "message": "unknown tag: alt",
25077            "line": " src/utilities/string_functions.js:237"
25078        },
25079        {
25080            "message": "unknown tag: alt",
25081            "line": " src/utilities/string_functions.js:313"
25082        },
25083        {
25084            "message": "unknown tag: alt",
25085            "line": " src/utilities/string_functions.js:375"
25086        },
25087        {
25088            "message": "unknown tag: alt",
25089            "line": " src/utilities/string_functions.js:437"
25090        },
25091        {
25092            "message": "unknown tag: alt",
25093            "line": " src/utilities/string_functions.js:526"
25094        },
25095        {
25096            "message": "unknown tag: alt",
25097            "line": " src/utilities/time_date.js:12"
25098        },
25099        {
25100            "message": "unknown tag: alt",
25101            "line": " src/utilities/time_date.js:34"
25102        },
25103        {
25104            "message": "unknown tag: alt",
25105            "line": " src/utilities/time_date.js:56"
25106        },
25107        {
25108            "message": "unknown tag: alt",
25109            "line": " src/utilities/time_date.js:78"
25110        },
25111        {
25112            "message": "unknown tag: alt",
25113            "line": " src/utilities/time_date.js:101"
25114        },
25115        {
25116            "message": "unknown tag: alt",
25117            "line": " src/utilities/time_date.js:123"
25118        },
25119        {
25120            "message": "unknown tag: alt",
25121            "line": " src/utilities/time_date.js:145"
25122        },
25123        {
25124            "message": "unknown tag: alt",
25125            "line": " src/webgl/camera.js:12"
25126        },
25127        {
25128            "message": "unknown tag: alt",
25129            "line": " src/webgl/camera.js:161"
25130        },
25131        {
25132            "message": "unknown tag: alt",
25133            "line": " src/webgl/camera.js:243"
25134        },
25135        {
25136            "message": "unknown tag: alt",
25137            "line": " src/webgl/interaction.js:5"
25138        },
25139        {
25140            "message": "unknown tag: alt",
25141            "line": " src/webgl/light.js:12"
25142        },
25143        {
25144            "message": "unknown tag: alt",
25145            "line": " src/webgl/light.js:101"
25146        },
25147        {
25148            "message": "unknown tag: alt",
25149            "line": " src/webgl/light.js:207"
25150        },
25151        {
25152            "message": "unknown tag: alt",
25153            "line": " src/webgl/loading.js:14"
25154        },
25155        {
25156            "message": "unknown tag: alt",
25157            "line": " src/webgl/loading.js:215"
25158        },
25159        {
25160            "message": "replacing incorrect tag: returns with return",
25161            "line": " src/webgl/material.js:57"
25162        },
25163        {
25164            "message": "unknown tag: alt",
25165            "line": " src/webgl/material.js:57"
25166        },
25167        {
25168            "message": "unknown tag: alt",
25169            "line": " src/webgl/material.js:150"
25170        },
25171        {
25172            "message": "unknown tag: alt",
25173            "line": " src/webgl/material.js:185"
25174        },
25175        {
25176            "message": "unknown tag: alt",
25177            "line": " src/webgl/material.js:275"
25178        },
25179        {
25180            "message": "unknown tag: alt",
25181            "line": " src/webgl/material.js:324"
25182        },
25183        {
25184            "message": "unknown tag: alt",
25185            "line": " src/webgl/p5.RendererGL.js:197"
25186        },
25187        {
25188            "message": "unknown tag: alt",
25189            "line": " src/webgl/p5.RendererGL.js:439"
25190        },
25191        {
25192            "message": "unknown tag: alt",
25193            "line": " src/webgl/p5.RendererGL.js:486"
25194        },
25195        {
25196            "message": "unknown tag: alt",
25197            "line": " src/webgl/p5.RendererGL.js:526"
25198        },
25199        {
25200            "message": "unknown tag: alt",
25201            "line": " src/webgl/primitives.js:14"
25202        },
25203        {
25204            "message": "replacing incorrect tag: params with param",
25205            "line": " lib/addons/p5.sound.js:1567"
25206        },
25207        {
25208            "message": "replacing incorrect tag: returns with return",
25209            "line": " lib/addons/p5.sound.js:1567"
25210        },
25211        {
25212            "message": "replacing incorrect tag: returns with return",
25213            "line": " lib/addons/p5.sound.js:7272"
25214        },
25215        {
25216            "message": "replacing incorrect tag: returns with return",
25217            "line": " lib/addons/p5.sound.js:9222"
25218        },
25219        {
25220            "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); all other components\nare in the range [0,1]. 'Brightness' and 'value' are used interchangeably.",
25221            "line": " src/color/color_conversion.js:10"
25222        },
25223        {
25224            "message": "Missing item type\nConvert an HSBA array to HSLA.",
25225            "line": " src/color/color_conversion.js:20"
25226        },
25227        {
25228            "message": "Missing item type\nConvert an HSBA array to RGBA.",
25229            "line": " src/color/color_conversion.js:46"
25230        },
25231        {
25232            "message": "Missing item type\nConvert an HSLA array to HSBA.",
25233            "line": " src/color/color_conversion.js:101"
25234        },
25235        {
25236            "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.",
25237            "line": " src/color/color_conversion.js:124"
25238        },
25239        {
25240            "message": "Missing item type\nConvert an RGBA array to HSBA.",
25241            "line": " src/color/color_conversion.js:188"
25242        },
25243        {
25244            "message": "Missing item type\nConvert an RGBA array to HSLA.",
25245            "line": " src/color/color_conversion.js:227"
25246        },
25247        {
25248            "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.",
25249            "line": " src/color/p5.Color.js:406"
25250        },
25251        {
25252            "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.",
25253            "line": " src/color/p5.Color.js:437"
25254        },
25255        {
25256            "message": "Missing item type\nCSS named colors.",
25257            "line": " src/color/p5.Color.js:456"
25258        },
25259        {
25260            "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.",
25261            "line": " src/color/p5.Color.js:609"
25262        },
25263        {
25264            "message": "Missing item type\nFull color string patterns. The capture groups are necessary.",
25265            "line": " src/color/p5.Color.js:622"
25266        },
25267        {
25268            "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.",
25269            "line": " src/color/p5.Color.js:759"
25270        },
25271        {
25272            "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.",
25273            "line": " src/color/p5.Color.js:976"
25274        },
25275        {
25276            "message": "Missing item type",
25277            "line": " src/core/canvas.js:1"
25278        },
25279        {
25280            "message": "Missing item type\nReturns the current framerate.",
25281            "line": " src/core/environment.js:242"
25282        },
25283        {
25284            "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 setup() is\nrecommended. The default rate is 60 frames per second.\n\nCalling frameRate() with no arguments returns the current framerate.",
25285            "line": " src/core/environment.js:252"
25286        },
25287        {
25288            "message": "Missing item type",
25289            "line": " src/core/error_helpers.js:1"
25290        },
25291        {
25292            "message": "Missing item type\nPrints out a fancy, colorful message to the console log",
25293            "line": " src/core/error_helpers.js:65"
25294        },
25295        {
25296            "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.\"",
25297            "line": " src/core/error_helpers.js:405"
25298        },
25299        {
25300            "message": "Missing item type\nPrints out all the colors in the color pallete with white text.\nFor color blindness testing.",
25301            "line": " src/core/error_helpers.js:457"
25302        },
25303        {
25304            "message": "Missing item type\n_globalInit\n\nTODO: ???\nif sketch is on window\nassume \"global\" mode\nand instantiate p5 automatically\notherwise do nothing",
25305            "line": " src/core/init.js:5"
25306        },
25307        {
25308            "message": "Missing item type\nHelper fxn for sharing pixel methods",
25309            "line": " src/core/p5.Element.js:1057"
25310        },
25311        {
25312            "message": "Missing item type\nResize our canvas element.",
25313            "line": " src/core/p5.Renderer.js:113"
25314        },
25315        {
25316            "message": "Missing item type\nHelper fxn to check font type (system or otf)",
25317            "line": " src/core/p5.Renderer.js:182"
25318        },
25319        {
25320            "message": "Missing item type\nHelper fxn to measure ascent and desce
25320nt.\nAdapted from http://stackoverflow.com/a/25355178",
25321            "line": " src/core/p5.Renderer.js:235"
25322        },
25323        {
25324            "message": "Missing item type\np5.Renderer2D\nThe 2D graphics canvas renderer class.\nextends p5.Renderer",
25325            "line": " src/core/p5.Renderer2D.js:10"
25326        },
25327        {
25328            "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.",
25329            "line": " src/core/p5.Renderer2D.js:395"
25330        },
25331        {
25332            "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.",
25333            "line": " src/core/shim.js:70"
25334        },
25335        {
25336            "message": "Missing item type\nprivate helper function to handle the user passing objects in\nduring construction or calls to create()",
25337            "line": " src/data/p5.TypedDict.js:198"
25338        },
25339        {
25340            "message": "Missing item type\nprivate helper function to ensure that the user passed in valid\nvalues for the Dictionary type",
25341            "line": " src/data/p5.TypedDict.js:378"
25342        },
25343        {
25344            "message": "Missing item type\nprivate helper function to ensure that the user passed in valid\nvalues for the Dictionary type",
25345            "line": " src/data/p5.TypedDict.js:423"
25346        },
25347        {
25348            "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'",
25349            "line": " src/data/p5.TypedDict.js:540"
25350        },
25351        {
25352            "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'",
25353            "line": " src/data/p5.TypedDict.js:605"
25354        },
25355        {
25356            "message": "Missing item type\n_updatePAccelerations updates the pAcceleration values",
25357            "line": " src/events/acceleration.js:80"
25358        },
25359        {
25360            "message": "Missing item type\nHolds the key codes of currently pressed keys.",
25361            "line": " src/events/keyboard.js:12"
25362        },
25363        {
25364            "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.",
25365            "line": " src/events/keyboard.js:308"
25366        },
25367        {
25368            "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.",
25369            "line": " src/events/keyboard.js:370"
25370        },
25371        {
25372            "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.",
25373            "line": " src/image/filters.js:3"
25374        },
25375        {
25376            "message": "Missing item type\nReturns the pixel buffer for a canvas",
25377            "line": " src/image/filters.js:26"
25378        },
25379        {
25380            "message": "Missing item type\nReturns a 32 bit number containing ARGB data at ith pixel in the\n1D array containing pixels data.",
25381            "line": " src/image/filters.js:46"
25382        },
25383        {
25384            "message": "Missing item type\nModifies pixels RGBA values to values contained in the data object.",
25385            "line": " src/image/filters.js:67"
25386        },
25387        {
25388            "message": "Missing item type\nReturns the ImageData object for a canvas\nhttps://developer.mozilla.org/en-US/docs/Web/API/ImageData",
25389            "line": " src/image/filters.js:87"
25390        },
25391        {
25392            "message": "Missing item type\nReturns a blank ImageData object.",
25393            "line": " src/image/filters.js:107"
25394        },
25395        {
25396            "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 
25396support an advanced\nuse case of creating a filter chain that executes without actually updating\nthe canvas in between everystep.",
25397            "line": " src/image/filters.js:122"
25398        },
25399        {
25400            "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/",
25401            "line": " src/image/filters.js:159"
25402        },
25403        {
25404            "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/",
25405            "line": " src/image/filters.js:193"
25406        },
25407        {
25408            "message": "Missing item type\nSets the alpha channel to entirely opaque. No parameter is used.",
25409            "line": " src/image/filters.js:216"
25410        },
25411        {
25412            "message": "Missing item type\nSets each pixel to its inverse value. No parameter is used.",
25413            "line": " src/image/filters.js:232"
25414        },
25415        {
25416            "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",
25417            "line": " src/image/filters.js:247"
25418        },
25419        {
25420            "message": "Missing item type\nreduces the bright areas in an image",
25421            "line": " src/image/filters.js:279"
25422        },
25423        {
25424            "message": "Missing item type\nincreases the bright areas in an image",
25425            "line": " src/image/filters.js:367"
25426        },
25427        {
25428            "message": "Missing item type\nThis module defines the p5 methods for the p5.Image class\nfor drawing images to the main display canvas.",
25429            "line": " src/image/image.js:8"
25430        },
25431        {
25432            "message": "Missing item type\nValidates clipping params. Per drawImage spec sWidth and sHight cannot be\nnegative or greater than image intrinsic width and height",
25433            "line": " src/image/loading_displaying.js:108"
25434        },
25435        {
25436            "message": "Missing item type\nApply the current tint color to the input image, return the resulting\ncanvas.",
25437            "line": " src/image/loading_displaying.js:425"
25438        },
25439        {
25440            "message": "Missing item type\nThis module defines the p5.Image class and P5 methods for\ndrawing images to the main display canvas.",
25441            "line": " src/image/p5.Image.js:9"
25442        },
25443        {
25444            "message": "Missing item type\nHelper fxn for sharing pixel methods",
25445            "line": " src/image/p5.Image.js:221"
25446        },
25447        {
25448            "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 saveStrings, saveJSON, saveTable etc.",
25449            "line": " src/io/files.js:1697"
25450        },
25451        {
25452            "message": "Missing item type\nReturns a file extension, or another string\nif the provided parameter has no extension.",
25453            "line": " src/io/files.js:1766"
25454        },
25455        {
25456            "message": "Missing item type\nReturns true if the browser is Safari, false if not.\nSafari makes trouble for downloading files.",
25457            "line": " src/io/files.js:1799"
25458        },
25459        {
25460            "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.",
25461            "line": " src/io/files.js:1811"
25462        },
25463        {
25464            "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 loadTable method.</p>\n<p>To save tables to your computer, use the save method\n or the saveTable 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>",
25465            "line": " src/io/p5.Table.js:11"
25466        },
25467        {
25468            "message": "Missing item type\nThis method is called while the parsing of XML (when loadXML() is\ncalled). The difference between this method and the setContent()\nmethod defined later is that this one is used to set the content\nwhen the node in question has more nodes under it and so on and\nnot directly text content. While in the other one is used when\nthe node in question directly has text inside it.",
25469            "line": " src/io/p5.XML.js:801"
25470        },
25471        {
25472            "message": "Missing item type\nThis method is called while the parsing of XML (when loadXML() is\ncalled). The XML node is passed and its attributes are stored in the\np5.XML's attribute Object.",
25473            "line": " src/io/p5.XML.js:818"
25474        },
25475        {
25476            "message": "Missing item type\nMultiplies a vector by a scalar and returns a new vector.",
25477            "line": " src/math/p5.Vector.js:1611"
25478        },
25479        {
25480            "message": "Missing item type\nDivides a vector by a scalar and returns a new vector.",
25481            "line": " src/math/p5.Vector.js:1638"
25482        },
25483        {
25484            "message": "Missing item type\nCalculates the dot product of two vectors.",
25485            "line": " src/math/p5.Vector.js:1665"
25486        },
25487        {
25488            "message": "Missing item type\nCalculates the cross product of two vectors.",
25489            "line": " src/math/p5.Vector.js:1679"
25490        },
25491        {
25492            "message": "Missing item type\nCalculates the Euclidean distance between two points (considering a\npoint as a vector object).",
25493            "line": " src/math/p5.Vector.js:1693"
25494        },
25495        {
25496            "message": "Missing item type\nLinear interpolate a vector to another vector and return the result as a\nne
25496w vector.",
25497            "line": " src/math/p5.Vector.js:1708"
25498        },
25499        {
25500            "message": "Missing item type\nHelper function to measure ascent and descent.",
25501            "line": " src/typography/attributes.js:258"
25502        },
25503        {
25504            "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.",
25505            "line": " src/typography/p5.Font.js:257"
25506        },
25507        {
25508            "message": "Missing item type\nReturns an opentype path for the supplied string and position.",
25509            "line": " src/typography/p5.Font.js:272"
25510        },
25511        {
25512            "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",
25513            "line": " src/webgl/loading.js:106"
25514        },
25515        {
25516            "message": "Missing item type",
25517            "line": " src/webgl/material.js:373"
25518        },
25519        {
25520            "message": "Missing item type\nCreate a 2D array for establishing stroke connections",
25521            "line": " src/webgl/p5.Geometry.js:192"
25522        },
25523        {
25524            "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",
25525            "line": " src/webgl/p5.Geometry.js:213"
25526        },
25527        {
25528            "message": "Missing item type",
25529            "line": " src/webgl/p5.Matrix.js:1"
25530        },
25531        {
25532            "message": "Missing item type\nPRIVATE",
25533            "line": " src/webgl/p5.Matrix.js:673"
25534        },
25535        {
25536            "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 beginShape() & de-activated when you call endShape().\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.",
25537            "line": " src/webgl/p5.RendererGL.Immediate.js:1"
25538        },
25539        {
25540            "message": "Missing item type\nEnd shape drawing and render vertices to screen.",
25541            "line": " src/webgl/p5.RendererGL.Immediate.js:106"
25542        },
25543        {
25544            "message": "Missing item type\ninitializes buffer defaults. runs each time a new geometry is\nregistered",
25545            "line": " src/webgl/p5.RendererGL.Retained.js:8"
25546        },
25547        {
25548            "message": "Missing item type\ncreateBuffers description",
25549            "line": " src/webgl/p5.RendererGL.Retained.js:47"
25550        },
25551        {
25552            "message": "Missing item type\nDraws buffers given a geometry key ID",
25553            "line": " src/webgl/p5.RendererGL.Retained.js:191"
25554        },
25555        {
25556            "message": "Missing item type\nmodel view, projection, & normal\nmatrices",
25557            "line": " src/webgl/p5.RendererGL.js:77"
25558        },
25559        {
25560            "message": "Missing item type\n[background description]",
25561            "line": " src/webgl/p5.RendererGL.js:417"
25562        },
25563        {
25564            "message": "Missing item type\n[resize description]",
25565            "line": " src/webgl/p5.RendererGL.js:654"
25566        },
25567        {
25568            "message": "Missing item type\nclears color and depth buffers\nwith r,g,b,a",
25569            "line": " src/webgl/p5.RendererGL.js:684"
25570        },
25571        {
25572            "message": "Missing item type\n[translate description]",
25573            "line": " src/webgl/p5.RendererGL.js:702"
25574        },
25575        {
25576            "message": "Missing item type\nScales the Model View Matrix by a vector",
25577            "line": " src/webgl/p5.RendererGL.js:721"
25578        },
25579        {
25580            "message": "Missing item type\nturn a two dimensional array into one dimensional array",
25581            "line": " src/webgl/p5.RendererGL.js:1001"
25582        },
25583        {
25584            "message": "Missing item type\nturn a p5.Vector Array into a one dimensional number array",
25585            "line": " src/webgl/p5.RendererGL.js:1038"
25586        },
25587        {
25588            "message": "Missing item type\nensures that p5 is using a 3d renderer. throws an error if not.",
25589            "line": " src/webgl/p5.RendererGL.js:1054"
25590        },
25591        {
25592            "message": "Missing item type",
25593            "line": " src/webgl/primitives.js:257"
25594        },
25595        {
25596            "message": "Missing item type\nDraw a line given two points",
25597            "line": " src/webgl/primitives.js:1037"
25598        },
25599        {
25600            "message": "Missing item type\nHelper function for select and selectAll",
25601            "line": " lib/addons/p5.dom.js:168"
25602        },
25603        {
25604            "message": "Missing item type\nHelper function for getElement and getElements.",
25605            "line": " lib/addons/p5.dom.js:184"
25606        },
25607        {
25608            "message": "Missing item type\nHelpers for create methods.",
25609            "line": " lib/addons/p5.dom.js:245"
25610        },
25611        {
25612            "message": "Missing item type",
25613            "line": " lib/addons/p5.dom.js:376"
25614        },
25615        {
25616            "message": "Missing item type",
25617            "line": " lib/addons/p5.dom.js:897"
25618        },
25619        {
25620            "message": "Missing item type",
25621            "line": " lib/addons/p5.dom.js:973"
25622        },
25623        {
25624            "message": "Missing item type",
25625            "line": " lib/addons/p5.dom.js:1013"
25626        },
25627        {
25628            "message": "Missing item type",
25629            "line": " lib/addons/p5.dom.js:2581"
25630        },
25631        {
25632            "message": "Missing item type",
25633            "line": " lib/addons/p5.dom.js:2647"
25634        },
25635        {
25636            "message": "Missing item type",
25637            "line": " lib/addons/p5.dom.js:2709"
25638        },
25639        {
25640            "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/",
25641            "line": " lib/addons/p5.sound.js:46"
25642        },
25643        {
25644            "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",
25645            "line": " lib/addons/p5.sound.js:226"
25646        },
25647        {
25648            "message": "Missing item type\nMaster contains AudioContext and the master sound output.",
25649            "line": " lib/addons/p5.sound.js:296"
25650        },
25651        {
25652            "message": "Missing item type\na silent connection to the DesinationNode\nwhich will ensure that anything connected to it\nwill not be garbage collected",
25653            "line": " lib/addons/p5.sound.js:391"
25654        },
25655        {
25656            "message": "Missing item type",
25657            "line": " lib/addons/p5.sound.js:407"
25658        },
25659        {
25660            "message": "Missing item type\nUsed by Osc and Env to chain signal math",
25661            "line": " lib/addons/p5.sound.js:583"
25662        },
25663        {
25664            "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.",
25665            "line": " lib/addons/p5.sound.js:903"
25666        },
25667        {
25668            "message": "Missing item type\nStop playback on all of this soundfile's sources.",
25669            "line": " lib/addons/p5.sound.js:1304"
25670        },
25671        {
25672            "message": "Missing item type",
25673            "line": " lib/addons/p5.sound.js:1741"
25674        },
25675        {
25676            "message": "Missing item type",
25677            "line": " lib/addons/p5.sound.js:2022"
25678        },
25679        {
25680            "message": "Missing item type",
25681            "line": " lib/addons/p5.sound.js:3022"
25682        },
25683        {
25684            "message": "Missing item type",
25685            "line": " lib/addons/p5.sound.js:3399"
25686        },
25687        {
25688            "message": "Missing item type",
25689            "line": " lib/addons/p5.sound.js:3420"
25690        },
25691        {
25692            "message": "Missing item type",
25693            "line": " lib/addons/p5.sound.js:3479"
25694        },
25695        {
25696            "message": "Missing item type",
25697            "line": " lib/addons/p5.sound.js:3797"
25698        },
25699        {
25700            "message": "Missing item type",
25701            "line": " lib/addons/p5.sound.js:3969"
25702        },
25703        {
25704            "message": "Missing item type",
25705            "line": " lib/addons/p5.sound.js:4127"
25706        },
25707        {
25708            "message": "Missing item type",
25709            "line": " lib/addons/p5.sound.js:4168"
25710        },
25711        {
25712            "message": "Missing item type",
25713            "line": " lib/addons/p5.sound.js:4238"
25714        },
25715        {
25716            "message": "Missing item type",
25717            "line": " lib/addons/p5.sound.js:4426"
25718        },
25719        {
25720            "message": "Missing item type",
25721            "line": " lib/addons/p5.sound.js:4483"
25722        },
25723        {
25724            "message": "Missing item type",
25725            "line": " lib/addons/p5.sound.js:4651"
25726        },
25727        {
25728            "message": "Missing item type",
25729            "line": " lib/addons/p5.sound.js:4699"
25730        },
25731        {
25732            "message": "Missing item type",
25733            "line": " lib/addons/p5.sound.js:4730"
25734        },
25735        {
25736            "message": "Missing item type",
25737            "line": " lib/addons/p5.sound.js:4751"
25738        },
25739        {
25740            "message": "Missing item type",
25741            "line": " lib/addons/p5.sound.js:4771"
25742        },
25743        {
25744            "message": "Missing item type",
25745            "line": " lib/addons/p5.sound.js:5478"
25746        },
25747        {
25748            "message": "Missing item type",
25749            "line": " lib/addons/p5.sound.js:5681"
25750        },
25751        {
25752            "message": "Missing item type",
25753            "line": " lib/addons/p5.sound.js:7363"
25754        },
25755        {
25756            "message": "Missing item type",
25757            "line": " lib/addons/p5.sound.js:7379"
25758        },
25759        {
25760            "message": "Missing item type",
25761            "line": " lib/addons/p5.sound.js:7403"
25762        },
25763        {
25764            "message": "Missing item type",
25765            "line": " lib/addons/p5.sound.js:7429"
25766        },
25767        {
25768            "message": "Missing item type",
25769            "line": " lib/addons/p5.sound.js:7451"
25770        },
25771        {
25772            "message": "Missing item type",
25773            "line": " lib/addons/p5.sound.js:7473"
25774        },
25775        {
25776            "message": "Missing item type",
25777            "line": " lib/addons/p5.sound.js:7519"
25778        },
25779        {
25780            "message": "Missing item type",
25781            "line": " lib/addons/p5.sound.js:7550"
25782        },
25783        {
25784            "message": "Missing item type",
25785            "line": " lib/addons/p5.sound.js:7568"
25786        },
25787        {
25788            "message": "Missing item type",
25789            "line": " lib/addons/p5.sound.js:7905"
25790        },
25791        {
25792            "message": "Missing item type",
25793            "line": " lib/addons/p5.sound.js:7927"
25794        },
25795        {
25796            "message": "Missing item type\nThe p5.Effect class is built\n  using Tone.js CrossFade",
25797            "line": " lib/addons/p5.sound.js:7997"
25798        },
25799        {
25800            "message": "Missing item type\nIn classes that extend\np5.Effect, connect effect nodes\nto the wet parameter",
25801            "line": " lib/addons/p5.sound.js:8003"
25802        },
25803        {
25804            "message": "Missing item type\nEQFilter extends p5.Filter with constraints\nnecessary for the p5.EQ",
25805            "line": " lib/addons/p5.sound.js:8381"
25806        },
25807        {
25808            "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.",
25809            "line": " lib/addons/p5.sound.js:9471"
25810        },
25811        {
25812            "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.",
25813            "line": " lib/addons/p5.sound.js:9635"
25814        },
25815        {
25816            "message": "Missing item type",
25817            "line": " lib/addons/p5.sound.js:9821"
25818        },
25819        {
25820            "message": "Missing item type",
25821            "line": " lib/addons/p5.sound.js:9846"
25822        },
25823        {
25824            "message": "Missing item type\nmusicalTimeMode variables\nmodify these only when the interval is specified in musicalTime format as a string",
25825            "line": " lib/addons/p5.sound.js:10571"
25826        },
25827        {
25828            "message": "Missing item type\nDo not initiate the callback if timeFromNow is < 0\nThis ususually occurs for a few milliseconds when the page\
25828nis not fully loaded\n\nThe callback should only be called until maxIterations is reached",
25829            "line": " lib/addons/p5.sound.js:10587"
25830        },
25831        {
25832            "message": "Missing item type\ncallback invoked when the recording is over",
25833            "line": " lib/addons/p5.sound.js:11072"
25834        },
25835        {
25836            "message": "Missing item type\ninternal method called on audio process",
25837            "line": " lib/addons/p5.sound.js:11158"
25838        },
25839        {
25840            "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",
25841            "line": " lib/addons/p5.sound.js:12142"
25842        },
25843        {
25844            "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/",
25845            "line": " lib/addons/p5.sound.min.js:3"
25846        }
25847    ],
25848    "consts": {
25849        "RGB": [
25850            "p5.colorMode"
25851        ],
25852        "HSB": [
25853            "p5.colorMode"
25854        ],
25855        "HSL": [
25856            "p5.colorMode"
25857        ],
25858        "CHORD": [
25859            "p5.arc"
25860        ],
25861        "PIE": [
25862            "p5.arc"
25863        ],
25864        "OPEN": [
25865            "p5.arc"
25866        ],
25867        "CENTER": [
25868            "p5.ellipseMode",
25869            "p5.rectMode",
25870            "p5.imageMode",
25871            "p5.textAlign"
25872        ],
25873        "RADIUS": [
25874            "p5.ellipseMode",
25875            "p5.rectMode"
25876        ],
25877        "CORNER": [
25878            "p5.ellipseMode",
25879            "p5.rectMode",
25880            "p5.imageMode"
25881        ],
25882        "CORNERS": [
25883            "p5.ellipseMode",
25884            "p5.rectMode",
25885            "p5.imageMode"
25886        ],
25887        "SQUARE": [
25888            "p5.strokeCap"
25889        ],
25890        "PROJECT": [
25891            "p5.strokeCap"
25892        ],
25893        "ROUND": [
25894            "p5.strokeCap",
25895            "p5.strokeJoin"
25896        ],
25897        "MITER": [
25898            "p5.strokeJoin"
25899        ],
25900        "BEVEL": [
25901            "p5.strokeJoin"
25902        ],
25903        "ARROW": [
25904            "p5.cursor"
25905        ],
25906        "CROSS": [
25907            "p5.cursor"
25908        ],
25909        "HAND": [
25910            "p5.cursor"
25911        ],
25912        "MOVE": [
25913            "p5.cursor"
25914        ],
25915        "TEXT": [
25916            "p5.cursor"
25917        ],
25918        "WAIT": [
25919            "p5.cursor"
25920        ],
25921        "P2D": [
25922            "p5.createCanvas",
25923            "p5.createGraphics"
25924        ],
25925        "WEBGL": [
25926            "p5.createCanvas",
25927            "p5.createGraphics"
25928        ],
25929        "BLEND": [
25930            "p5.blendMode",
25931            "p5.Image.blend",
25932            "p5.blend"
25933        ],
25934        "DARKEST": [
25935            "p5.blendMode",
25936            "p5.Image.blend",
25937            "p5.blend"
25938        ],
25939        "LIGHTEST": [
25940            "p5.blendMode",
25941            "p5.Image.blend",
25942            "p5.blend"
25943        ],
25944        "DIFFERENCE": [
25945            "p5.blendMode",
25946            "p5.Image.blend",
25947            "p5.blend"
25948        ],
25949        "MULTIPLY": [
25950            "p5.blendMode",
25951            "p5.Image.blend",
25952            "p5.blend"
25953        ],
25954        "EXCLUSION": [
vendor: 6,626 bytes, lines 25955-26223
25955            "p5.blendMode",
25956            "p5.Image.blend",
25957            "p5.blend"
25958        ],
25959        "SCREEN": [
25960            "p5.blendMode",
25961            "p5.Image.blend",
25962            "p5.blend"
25963        ],
25964        "REPLACE": [
25965            "p5.blendMode",
25966            "p5.Image.blend",
25967            "p5.blend"
25968        ],
25969        "OVERLAY": [
25970            "p5.blendMode",
25971            "p5.Image.blend",
25972            "p5.blend"
25973        ],
25974        "HARD_LIGHT": [
25975            "p5.blendMode",
25976            "p5.Image.blend",
25977            "p5.blend"
25978        ],
25979        "SOFT_LIGHT": [
25980            "p5.blendMode",
25981            "p5.Image.blend",
25982            "p5.blend"
25983        ],
25984        "DODGE": [
25985            "p5.blendMode",
25986            "p5.Image.blend",
25987            "p5.blend"
25988        ],
25989        "BURN": [
25990            "p5.blendMode",
25991            "p5.Image.blend",
25992            "p5.blend"
25993        ],
25994        "ADD": [
25995            "p5.blendMode",
25996            "p5.Image.blend",
25997            "p5.blend"
25998        ],
25999        "NORMAL": [
26000            "p5.blendMode",
26001            "p5.Image.blend",
26002            "p5.blend",
26003            "p5.textStyle"
26004        ],
26005        "POINTS": [
26006            "p5.beginShape"
26007        ],
26008        "LINES": [
26009            "p5.beginShape"
26010        ],
26011        "TRIANGLES": [
26012            "p5.beginShape"
26013        ],
26014        "TRIANGLE_FAN": [
26015            "p5.beginShape"
26016        ],
26017        "TRIANGLE_STRIP": [
26018            "p5.beginShape"
26019        ],
26020        "QUADS": [
26021            "p5.beginShape"
26022        ],
26023        "QUAD_STRIP": [
26024            "p5.beginShape"
26025        ],
26026        "CLOSE": [
26027            "p5.endShape"
26028        ],
26029        "THRESHOLD": [
26030            "p5.Image.filter",
26031            "p5.filter"
26032        ],
26033        "GRAY": [
26034            "p5.Image.filter",
26035            "p5.filter"
26036        ],
26037        "OPAQUE": [
26038            "p5.Image.filter",
26039            "p5.filter"
26040        ],
26041        "INVERT": [
26042            "p5.Image.filter",
26043            "p5.filter"
26044        ],
26045        "POSTERIZE": [
26046            "p5.Image.filter",
26047            "p5.filter"
26048        ],
26049        "BLUR": [
26050            "p5.Image.filter",
26051            "p5.filter"
26052        ],
26053        "ERODE": [
26054            "p5.Image.filter",
26055            "p5.filter"
26056        ],
26057        "DILATE": [
26058            "p5.Image.filter",
26059            "p5.filter"
26060        ],
26061        "RADIANS": [
26062            "p5.angleMode"
26063        ],
26064        "DEGREES": [
26065            "p5.angleMode"
26066        ],
26067        "LEFT": [
26068            "p5.textAlign"
26069        ],
26070        "RIGHT": [
26071            "p5.textAlign"
26072        ],
26073        "TOP": [
26074            "p5.textAlign"
26075        ],
26076        "BOTTOM": [
26077            "p5.textAlign"
26078        ],
26079        "BASELINE": [
26080            "p5.textAlign"
26081        ],
26082        "ITALIC": [
26083            "p5.textStyle"
26084        ],
26085        "BOLD": [
26086            "p5.textStyle"
26087        ],
26088        "VIDEO": [
26089            "p5.dom.createCapture"
26090        ],
26091        "AUDIO": [
26092            "p5.dom.createCapture"
26093        ],
26094        "AUTO": [
26095            "p5.Element.size"
26096        ]
26097    }
26098}
26099},{}],2:[function(_dereq_,module,exports){
26100var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
26101
26102;(function (exports) {
26103	'use strict';
26104
26105  var Arr = (typeof Uint8Array !== 'undefined')
26106    ? Uint8Array
26107    : Array
26108
26109	var PLUS   = '+'.charCodeAt(0)
26110	var SLASH  = '/'.charCodeAt(0)
26111	var NUMBER = '0'.charCodeAt(0)
26112	var LOWER  = 'a'.charCodeAt(0)
26113	var UPPER  = 'A'.charCodeAt(0)
26114	var PLUS_URL_SAFE = '-'.charCodeAt(0)
26115	var SLASH_URL_SAFE = '_'.charCodeAt(0)
26116
26117	function decode (elt) {
26118		var code = elt.charCodeAt(0)
26119		if (code === PLUS ||
26120		    code === PLUS_URL_SAFE)
26121			return 62 // '+'
26122		if (code === SLASH ||
26123		    code === SLASH_URL_SAFE)
26124			return 63 // '/'
26125		if (code < NUMBER)
26126			return -1 //no match
26127		if (code < NUMBER + 10)
26128			return code - NUMBER + 26 + 26
26129		if (code < UPPER + 26)
26130			return code - UPPER
26131		if (code < LOWER + 26)
26132			return code - LOWER + 26
26133	}
26134
26135	function b64ToByteArray (b64) {
26136		var i, j, l, tmp, placeHolders, arr
26137
26138		if (b64.length % 4 > 0) {
26139			throw new Error('Invalid string. Length must be a multiple of 4')
26140		}
26141
26142		// the number of equal signs (place holders)
26143		// if there are two placeholders, than the two characters before it
26144		// represent one byte
26145		// if there is only one, then the three characters before it represent 2 bytes
26146		// this is just a cheap hack to not do indexOf twice
26147		var len = b64.length
26148		placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0
26149
26150		// base64 is 4/3 + up to two characters of the original data
26151		arr = new Arr(b64.length * 3 / 4 - placeHolders)
26152
26153		// if there are placeholders, only get up to the last complete 4 chars
26154		l = placeHolders > 0 ? b64.length - 4 : b64.length
26155
26156		var L = 0
26157
26158		function push (v) {
26159			arr[L++] = v
26160		}
26161
26162		for (i = 0, j = 0; i < l; i += 4, j += 3) {
26163			tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3))
26164			push((tmp & 0xFF0000) >> 16)
26165			push((tmp & 0xFF00) >> 8)
26166			push(tmp & 0xFF)
26167		}
26168
26169		if (placeHolders === 2) {
26170			tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4)
26171			push(tmp & 0xFF)
26172		} else if (placeHolders === 1) {
26173			tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2)
26174			push((tmp >> 8) & 0xFF)
26175			push(tmp & 0xFF)
26176		}
26177
26178		return arr
26179	}
26180
26181	function uint8ToBase64 (uint8) {
26182		var i,
26183			extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
26184			output = "",
26185			temp, length
26186
26187		function encode (num) {
26188			return lookup.charAt(num)
26189		}
26190
26191		function tripletToBase64 (num) {
26192			return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F)
26193		}
26194
26195		// go through the array every three bytes, we'll deal with trailing stuff later
26196		for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
26197			temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
26198			output += tripletToBase64(temp)
26199		}
26200
26201		// pad the end with zeros, but make sure to not forget the extra bytes
26202		switch (extraBytes) {
26203			case 1:
26204				temp = uint8[uint8.length - 1]
26205				output += encode(temp >> 2)
26206				output += encode((temp << 4) & 0x3F)
26207				output += '=='
26208				break
26209			case 2:
26210				temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])
26211				output += encode(temp >> 10)
26212				output += encode((temp >> 4) & 0x3F)
26213				output += encode((temp << 2) & 0x3F)
26214				output += '='
26215				break
26216		}
26217
26218		return output
26219	}
26220
26221	exports.toByteArray = b64ToByteArray
26222	exports.fromByteArray = uint8ToBase64
26223}(typeof exports === 'undefined' ? (this.base64js = {}
26223) : exports))
26224
26225},{}],3:[function(_dereq_,module,exports){
26226
26227},{}],4:[function(_dereq_,module,exports){
26228(function (global){
26229/*!
26230 * The buffer module from node.js, for the browser.
26231 *
26232 * @author   Feross Aboukhadijeh <[email protected]> <http://feross.org>
26233 * @license  MIT
26234 */
26235/* eslint-disable no-proto */
26236
26237'use strict'
26238
26239var base64 = _dereq_('base64-js')
26240var ieee754 = _dereq_('ieee754')
26241var isArray = _dereq_('isarray')
26242
26243exports.Buffer = Buffer
26244exports.SlowBuffer = SlowBuffer
26245exports.INSPECT_MAX_BYTES = 50
26246Buffer.poolSize = 8192 // not used by this implementation
26247
26248var rootParent = {}
26249
26250/**
26251 * If `Buffer.TYPED_ARRAY_SUPPORT`:
26252 *   === true    Use Uint8Array implementation (fastest)
26253 *   === false   Use Object implementation (most compatible, even IE6)
26254 *
26255 * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
26256 * Opera 11.6+, iOS 4.2+.
26257 *
26258 * Due to various browser bugs, sometimes the Object implementation will be used even
26259 * when the browser supports typed arrays.
26260 *
26261 * Note:
26262 *
26263 *   - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances,
26264 *     See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438.
26265 *
26266 *   - Safari 5-7 lacks support for changing the `Object.prototype.constructor` property
26267 *     on objects.
26268 *
26269 *   - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function.
26270 *
26271 *   - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of
26272 *     incorrect length in some situations.
26273
26274 * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they
26275 * get the Object implementation, which is slower but behaves correctly.
26276 */
26277Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined
26278  ? global.TYPED_ARRAY_SUPPORT
26279  : typedArraySupport()
26280
26281function typedArraySupport () {
26282  function Bar () {}
26283  try {
26284    var arr = new Uint8Array(1)
26285    arr.foo = function () { return 42 }
26286    arr.constructor = Bar
26287    return arr.foo() === 42 && // typed array instances can be augmented
26288        arr.constructor === Bar && // constructor can be set
26289        typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray`
26290        arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray`
26291  } catch (e) {
26292    return false
26293  }
26294}
26295
26296function kMaxLength () {
26297  return Buffer.TYPED_ARRAY_SUPPORT
26298    ? 0x7fffffff
26299    : 0x3fffffff
26300}
26301
26302/**
26303 * Class: Buffer
26304 * =============
26305 *
26306 * The Buffer constructor returns instances of `Uint8Array` that are augmented
26307 * with function properties for all the node `Buffer` API functions. We use
26308 * `Uint8Array` so that square bracket notation works as expected -- it returns
26309 * a single octet.
26310 *
26311 * By augmenting the instances, we can avoid modifying the `Uint8Array`
26312 * prototype.
26313 */
26314function Buffer (arg) {
26315  if (!(this instanceof Buffer)) {
26316    // Avoid going through an ArgumentsAdaptorTrampoline in the common case.
26317    if (arguments.length > 1) return new Buffer(arg, arguments[1])
26318    return new Buffer(arg)
26319  }
26320
26321  if (!Buffer.TYPED_ARRAY_SUPPORT) {
26322    this.length = 0
26323    this.parent = undefined
26324  }
26325
26326  // Common case.
26327  if (typeof arg === 'number') {
26328    return fromNumber(this, arg)
26329  }
26330
26331  // Slightly less common case.
26332  if (typeof arg === 'string') {
26333    return fromString(this, arg, arguments.length > 1 ? arguments[1] : 'utf8')
26334  }
26335
26336  // Unusual.
26337  return fromObject(this, arg)
26338}
26339
26340function fromNumber (that, length) {
26341  that = allocate(that, length < 0 ? 0 : checked(length) | 0)
26342  if (!Buffer.TYPED_ARRAY_SUPPORT) {
26343    for (var i = 0; i < length; i++) {
26344      that[i] = 0
26345    }
26346  }
26347  return that
26348}
26349
26350function fromString (that, string, encoding) {
26351  if (typeof encoding !== 'string' || encoding === '') encoding = 'utf8'
26352
26353  // Assumption: byteLength() return value is always < kMaxLength.
26354  var length = byteLength(string, encoding) | 0
26355  that = allocate(that, length)
26356
26357  that.write(string, encoding)
26358  return that
26359}
26360
26361function fromObject (that, object) {
26362  if (Buffer.isBuffer(object)) return fromBuffer(that, object)
26363
26364  if (isArray(object)) return fromArray(that, object)
26365
26366  if (object == null) {
26367    throw new TypeError('must start with number, buffer, array or string')
26368  }
26369
26370  if (typeof ArrayBuffer !== 'undefined') {
26371    if (object.buffer instanceof ArrayBuffer) {
26372      return fromTypedArray(that, object)
26373    }
26374    if (object instanceof ArrayBuffer) {
26375      return fromArrayBuffer(that, object)
26376    }
26377  }
26378
26379  if (object.length) return fromArrayLike(that, object)
26380
26381  return fromJsonObject(that, object)
26382}
26383
26384function fromBuffer (that, buffer) {
26385  var length = checked(buffer.length) | 0
26386  that = allocate(that, length)
26387  buffer.copy(that, 0, 0, length)
26388  return that
26389}
26390
26391function fromArray (that, array) {
26392  var length = checked(array.length) | 0
26393  that = allocate(that, length)
26394  for (var i = 0; i < length; i += 1) {
26395    that[i] = array[i] & 255
26396  }
26397  return that
26398}
26399
26400// Duplicate of fromArray() to keep fromArray() monomorphic.
26401function fromTypedArray (that, array) {
26402  var length = checked(array.length) | 0
26403  that = allocate(that, length)
26404  // Truncating the elements is probably not what people expect from typed
26405  // arrays with BYTES_PER_ELEMENT > 1 but it's compatible with the behavior
26406  // of the old Buffer constructor.
26407  for (var i = 0; i < length; i += 1) {
26408    that[i] = array[i] & 255
26409  }
26410  return that
26411}
26412
26413function fromArrayBuffer (that, array) {
26414  if (Buffer.TYPED_ARRAY_SUPPORT) {
26415    // Return an augmented `Uint8Array` instance, for best performance
26416    array.byteLength
26417    that = Buffer._augment(new Uint8Array(array))
26418  } else {
26419    // Fallback: Return an object instance of the Buffer class
26420    that = fromTypedArray(that, new Uint8Array(array))
26421  }
26422  return that
26423}
26424
26425function fromArrayLike (that, array) {
26426  var length = checked(array.length) | 0
26427  that = allocate(that, length)
26428  for (var i = 0; i < length; i += 1) {
26429    that[i] = array[i] & 255
26430  }
26431  return that
26432}
26433
26434// Deserialize { type: 'Buffer', data: [1,2,3,...] } into a Buffer object.
26435// Returns a zero-length buffer for inputs that don't conform to the spec.
26436function fromJsonObject (that, object) {
26437  var array
26438  var length = 0
26439
26440  if (object.type === 'Buffer' && isArray(object.data)) {
26441    array = object.data
26442    length = checked(array.length) | 0
26443  }
26444  that = allocate(that, length)
26445
26446  for (var i = 0; i < length; i += 1) {
26447    that[i] = array[i] & 255
26448  }
26449  return that
26450}
26451
26452if (Buffer.TYPED_ARRAY_SUPPORT) {
26453  Buffer.prototype.__proto__ = Uint8Array.prototype
26454  Buffer.__proto__ = Uint8Array
26455} else {
26456  // pre-set for values that may exist in the future
26457  Buffer.prototype.length = undefined
26458  Buffer.prototype.parent = undefined
26459}
26460
26461function allocate (that, length) {
26462  if (Buffer.TYPED_ARRAY_SUPPORT) {
26463    // Return an augmented `Uint8Array` instance, for best performance
26464    that = Buffer._augment(new Uint8Array(length))
26465    that.__proto__ = Buffer.prototype
26466  } else {
26467    // Fallback: Return an object instance of the Buffer class
26468    that.length = length
26469    that._isBuffer = true
26470  }
26471
26472  var fromPool = length !== 0 && length <= Buffer.poolSize >>> 1
26473  if (fromPool) that.parent = rootParent
26474
26475  return that
26476}
26477
26478function checked (length) {
26479  // Note: cannot use `length < kMaxLength` here because that fails when
26480  // length is NaN (which is otherwise coerced to zero.)
26481  if (length >= kMaxLength()) {
26482    throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
26483                         'size: 0x' + kMaxLength().toString(16) + ' bytes')
26484  }
26485  return length | 0
26486}
26487
26488function SlowBuffer (subject, encoding) {
26489  if (!(this instanceof SlowBuffer)) return new SlowBuffer(subject, encoding)
26490
26491  var buf = new Buffer(subject, encoding)
26492  delete buf.parent
26493  return buf
26494}
26495
26496Buffer.isBuffer = function isBuffer (b) {
26497  return !!(b != null && b._isBuffer)
26498}
26499
26500Buffer.compare = function compare (a, b) {
26501  if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {
26502    throw new TypeError('Arguments must be Buffers')
26503  }
26504
26505  if (a === b) return 0
26506
26507  var x = a.length
26508  var y = b.length
26509
26510  var i = 0
26511  var len = Math.min(x, y)
26512  while (i < len) {
26513    if (a[i] !== b[i]) break
26514
26515    ++i
26516  }
26517
26518  if (i !== len) {
26519    x = a[i]
26520    y = b[i]
26521  }
26522
26523  if (x < y) return -1
26524  if (y < x) return 1
26525  return 0
26526}
26527
26528Buffer.isEncoding = function isEncoding (encoding) {
26529  switch (String(encoding).toLowerCase()) {
26530    case 'hex':
26531    case 'utf8':
26532    case 'utf-8':
26533    case 'ascii':
26534    case 'binary':
26535    case 'base64':
26536    case 'raw':
26537    case 'ucs2':
26538    case 'ucs-2':
26539    case 'utf16le':
26540    case 'utf-16le':
26541      return true
26542    default:
26543      return false
26544  }
26545}
26546
26547Buffer.concat = function concat (list, length) {
26548  if (!isArray(list)) throw new TypeError('list argument must be an Array of Buffers.')
26549
26550  if (list.length === 0) {
26551    return new Buffer(0)
26552  }
26553
26554  var i
26555  if (length === undefined) {
26556    length = 0
26557    for (i = 0; i < list.length; i++) {
26558      length += list[i].length
26559    }
26560  }
26561
26562  var buf = new Buffer(length)
26563  var pos = 0
26564  for (i = 0; i < list.length; i++) {
26565    var item = list[i]
26566    item.copy(buf, pos)
26567    pos += item.length
26568  }
26569  return buf
26570}
26571
26572function byteLength (string, encoding) {
26573  if (typeof string !== 'string') string = '' + string
26574
26575  var len = string.length
26576  if (len === 0) return 0
26577
26578  // Use a for loop to avoid recursion
26579  var loweredCase = false
26580  for (;;) {
26581    switch (encoding) {
26582      case 'ascii':
26583      case 'binary':
26584      // Deprecated
26585      case 'raw':
26586      case 'raws':
26587        return len
26588      case 'utf8':
26589      case 'utf-8':
26590        return utf8ToBytes(string).length
26591      case 'ucs2':
26592      case 'ucs-2':
26593      case 'utf16le':
26594      case 'utf-16le':
26595        return len * 2
26596      case 'hex':
26597        return len >>> 1
26598      case 'base64':
26599        return base64ToBytes(string).length
26600      default:
26601        if (loweredCase) return utf8ToBytes(string).length // assume utf8
26602        encoding = ('' + encoding).toLowerCase()
26603        loweredCase = true
26604    }
26605  }
26606}
26607Buffer.byteLength = byteLength
26608
26609function slowToString (encoding, start, end) {
26610  var loweredCase = false
26611
26612  start = start | 0
26613  end = end === undefined || end === Infinity ? this.length : end | 0
26614
26615  if (!encoding) encoding = 'utf8'
26616  if (start < 0) start = 0
26617  if (end > this.length) end = this.length
26618  if (end <= start) return ''
26619
26620  while (true) {
26621    switch (encoding) {
26622      case 'hex':
26623        return hexSlice(this, start, end)
26624
26625      case 'utf8':
26626      case 'utf-8':
26627        return utf8Slice(this, start, end)
26628
26629      case 'ascii':
26630        return asciiSlice(this, start, end)
26631
26632      case 'binary':
26633        return binarySlice(this, start, end)
26634
26635      case 'base64':
26636        return base64Slice(this, start, end)
26637
26638      case 'ucs2':
26639      case 'ucs-2':
26640      case 'utf16le':
26641      case 'utf-16le':
26642        return utf16leSlice(this, start, end)
26643
26644      default:
26645        if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
26646        encoding = (encoding + '').toLowerCase()
26647        loweredCase = true
26648    }
26649  }
26650}
26651
26652Buffer.prototype.toString = function toString () {
26653  var length = this.length | 0
26654  if (length === 0) return ''
26655  if (arguments.length === 0) return utf8Slice(this, 0, length)
26656  return slowToString.apply(this, arguments)
26657}
26658
26659Buffer.prototype.equals = function equals (b) {
26660  if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
26661  if (this === b) return true
26662  return Buffer.compare(this, b) === 0
26663}
26664
26665Buffer.prototype.inspect = function inspect () {
26666  var str = ''
26667  var max = exports.INSPECT_MAX_BYTES
26668  if (this.length > 0) {
26669    str = this.toString('hex', 0, max).match(/.{2}/g).join(' ')
26670    if (this.length > max) str += ' ... '
26671  }
26672  return '<Buffer ' + str + '>'
26673}
26674
26675Buffer.prototype.compare = function compare (b) {
26676  if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
26677  if (this === b) return 0
26678  return Buffer.compare(this, b)
26679}
26680
26681Buffer.prototype.indexOf = function indexOf (val, byteOffset) {
26682  if (byteOffset > 0x7fffffff) byteOffset = 0x7fffffff
26683  else if (byteOffset < -0x80000000) byteOffset = -0x80000000
26684  byteOffset >>= 0
26685
26686  if (this.length === 0) return -1
26687  if (byteOffset >= this.length) return -1
26688
26689  // Negative offsets start from the end of the buffer
26690  if (byteOffset < 0) byteOffset = Math.max(this.length + byteOffset, 0)
26691
26692  if (typeof val === 'string') {
26693    if (val.length === 0) return -1 // special case: looking for empty string always fails
26694    return String.prototype.indexOf.call(this, val, byteOffset)
26695  }
26696  if (Buffer.isBuffer(val)) {
26697    return arrayIndexOf(this, val, byteOffset)
26698  }
26699  if (typeof val === 'number') {
26700    if (Buffer.TYPED_ARRAY_SUPPORT && Uint8Array.prototype.indexOf === 'function') {
26701      return Uint8Array.prototype.indexOf.call(this, val, byteOffset)
26702    }
26703    return arrayIndexOf(this, [ val ], byteOffset)
26704  }
26705
26706  function arrayIndexOf (arr, val, byteOffset) {
26707    var foundIndex = -1
26708    for (var i = 0; byteOffset + i < arr.length; i++) {
26709      if (arr[byteOffset + i] === val[foundIndex === -1 ? 0 : i - foundIndex]) {
26710        if (foundIndex === -1) foundIndex = i
26711        if (i - foundIndex + 1 === val.length) return byteOffset + foundIndex
26712      } else {
26713        foundIndex = -1
26714      }
26715    }
26716    return -1
26717  }
26718
26719  throw new TypeError('val must be string, number or Buffer')
26720}
26721
26722// `get` is deprecated
26723Buffer.prototype.get = function get (offset) {
26724  console.log('.get() is deprecated. Access using array indexes instead.')
26725  return this.readUInt8(offset)
26726}
26727
26728// `set` is deprecated
26729Buffer.prototype.set = function set (v, offset) {
26730  console.log('.set() is deprecated. Access using array indexes instead.')
26731  return this.writeUInt8(v, offset)
26732}
26733
26734function hexWrite (buf, string, offset, length) {
26735  offset = Number(offset) || 0
26736  var remaining = buf.length - offset
26737  if (!length) {
26738    length = remaining
26739  } else {
26740    length = Number(length)
26741    if (length > remaining) {
26742      length = remaining
26743    }
26744  }
26745
26746  // must be an even number of digits
26747  var strLen = string.length
26748  if (strLen % 2 !== 0) throw new Error('Invalid hex string')
26749
26750  if (length > strLen / 2) {
26751    length = strLen / 2
26752  }
26753  for (var i = 0; i < length; i++) {
26754    var parsed = parseInt(string.substr(i * 2, 2), 16)
26755    if (isNaN(parsed)) throw new Error('Invalid hex string')
26756    buf[offset + i] = parsed
26757  }
26758  return i
26759}
26760
26761function utf8Write (buf, string, offset, length) {
26762  return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)
26763}
26764
26765function asciiWrite (buf, string, offset, length) {
26766  return blitBuffer(asciiToBytes(string), buf, offset, length)
26767}
26768
26769function binaryWrite (buf, string, offset, length) {
26770  return asciiWrite(buf, string, offset, length)
26771}
26772
26773function base64Write (buf, string, offset, length) {
26774  return blitBuffer(base64ToBytes(string), buf, offset, length)
26775}
26776
26777function ucs2Write (buf, string, offset, length) {
26778  return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)
26779}
26780
26781Buffer.prototype.write = function write (string, offset, length, encoding) {
26782  // Buffer#write(string)
26783  if (offset === undefined) {
26784    encoding = 'utf8'
26785    length = this.length
26786    offset = 0
26787  // Buffer#write(string, encoding)
26788  } else if (length === undefined && typeof offset === 'string') {
26789    encoding = offset
26790    length = this.length
26791    offset = 0
26792  // Buffer#write(string, offset[, length][, encoding])
26793  } else if (isFinite(offset)) {
26794    offset = offset | 0
26795    if (isFinite(length)) {
26796      length = length | 0
26797      if (encoding === undefined) encoding = 'utf8'
26798    } else {
26799      encoding = length
26800      length = undefined
26801    }
26802  // legacy write(string, encoding, offset, length) - remove in v0.13
26803  } else {
26804    var swap = encoding
26805    encoding = offset
26806    offset = length | 0
26807    length = swap
26808  }
26809
26810  var remaining = this.length - offset
26811  if (length === undefined || length > remaining) length = remaining
26812
26813  if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {
26814    throw new RangeError('attempt to write outside buffer bounds')
26815  }
26816
26817  if (!encoding) encoding = 'utf8'
26818
26819  var loweredCase = false
26820  for (;;) {
26821    switch (encoding) {
26822      case 'hex':
26823        return hexWrite(this, string, offset, length)
26824
26825      case 'utf8':
26826      case 'utf-8':
26827        return utf8Write(this, string, offset, length)
26828
26829      case 'ascii':
26830        return asciiWrite(this, string, offset, length)
26831
26832      case 'binary':
26833        return binaryWrite(this, string, offset, length)
26834
26835      case 'base64':
26836        // Warning: maxLength not taken into account in base64Write
26837        return base64Write(this, string, offset, length)
26838
26839      case 'ucs2':
26840      case 'ucs-2':
26841      case 'utf16le':
26842      case 'utf-16le':
26843        return ucs2Write(this, string, offset, length)
26844
26845      default:
26846        if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
26847        encoding = ('' + encoding).toLowerCase()
26848        loweredCase = true
26849    }
26850  }
26851}
26852
26853Buffer.prototype.toJSON = function toJSON () {
26854  return {
26855    type: 'Buffer',
26856    data: Array.prototype.slice.call(this._arr || this, 0)
26857  }
26858}
26859
26860function base64Slice (buf, start, end) {
26861  if (start === 0 && end === buf.length) {
26862    return base64.fromByteArray(buf)
26863  } else {
26864    return base64.fromByteArray(buf.slice(start, end))
26865  }
26866}
26867
26868function utf8Slice (buf, start, end) {
26869  end = Math.min(buf.length, end)
26870  var res = []
26871
26872  var i = start
26873  while (i < end) {
26874    var firstByte = buf[i]
26875    var codePoint = null
26876    var bytesPerSequence = (firstByte > 0xEF) ? 4
26877      : (firstByte > 0xDF) ? 3
26878      : (firstByte > 0xBF) ? 2
26879      : 1
26880
26881    if (i + bytesPerSequence <= end) {
26882      var secondByte, thirdByte, fourthByte, tempCodePoint
26883
26884      switch (bytesPerSequence) {
26885        case 1:
26886          if (firstByte < 0x80) {
26887            codePoint = firstByte
26888          }
26889          break
26890        case 2:
26891          secondByte = buf[i + 1]
26892          if ((secondByte & 0xC0) === 0x80) {
26893            tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F)
26894            if (tempCodePoint > 0x7F) {
26895              codePoint = tempCodePoint
26896            }
26897          }
26898          break
26899        case 3:
26900          secondByte = buf[i + 1]
26901          thirdByte = buf[i + 2]
26902          if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {
26903            tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F)
26904            if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {
26905              codePoint = tempCodePoint
26906            }
26907          }
26908          break
26909        case 4:
26910          secondByte = buf[i + 1]
26911          thirdByte = buf[i + 2]
26912          fourthByte = buf[i + 3]
26913          if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {
26914            tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F)
26915            if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {
26916              codePoint = tempCodePoint
26917            }
26918          }
26919      }
26920    }
26921
26922    if (codePoint === null) {
26923      // we did not generate a valid codePoint so insert a
26924      // replacement char (U+FFFD) and advance only 1 byte
26925      codePoint = 0xFFFD
26926      bytesPerSequence = 1
26927    } else if (codePoint > 0xFFFF) {
26928      // encode to utf16 (surrogate pair dance)
26929      codePoint -= 0x10000
26930      res.push(codePoint >>>
vendor: 2,464 bytes, lines 26930-27045
26930 10 & 0x3FF | 0xD800)
26931      codePoint = 0xDC00 | codePoint & 0x3FF
26932    }
26933
26934    res.push(codePoint)
26935    i += bytesPerSequence
26936  }
26937
26938  return decodeCodePointsArray(res)
26939}
26940
26941// Based on http://stackoverflow.com/a/22747272/680742, the browser with
26942// the lowest limit is Chrome, with 0x10000 args.
26943// We go 1 magnitude less, for safety
26944var MAX_ARGUMENTS_LENGTH = 0x1000
26945
26946function decodeCodePointsArray (codePoints) {
26947  var len = codePoints.length
26948  if (len <= MAX_ARGUMENTS_LENGTH) {
26949    return String.fromCharCode.apply(String, codePoints) // avoid extra slice()
26950  }
26951
26952  // Decode in chunks to avoid "call stack size exceeded".
26953  var res = ''
26954  var i = 0
26955  while (i < len) {
26956    res += String.fromCharCode.apply(
26957      String,
26958      codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)
26959    )
26960  }
26961  return res
26962}
26963
26964function asciiSlice (buf, start, end) {
26965  var ret = ''
26966  end = Math.min(buf.length, end)
26967
26968  for (var i = start; i < end; i++) {
26969    ret += String.fromCharCode(buf[i] & 0x7F)
26970  }
26971  return ret
26972}
26973
26974function binarySlice (buf, start, end) {
26975  var ret = ''
26976  end = Math.min(buf.length, end)
26977
26978  for (var i = start; i < end; i++) {
26979    ret += String.fromCharCode(buf[i])
26980  }
26981  return ret
26982}
26983
26984function hexSlice (buf, start, end) {
26985  var len = buf.length
26986
26987  if (!start || start < 0) start = 0
26988  if (!end || end < 0 || end > len) end = len
26989
26990  var out = ''
26991  for (var i = start; i < end; i++) {
26992    out += toHex(buf[i])
26993  }
26994  return out
26995}
26996
26997function utf16leSlice (buf, start, end) {
26998  var bytes = buf.slice(start, end)
26999  var res = ''
27000  for (var i = 0; i < bytes.length; i += 2) {
27001    res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256)
27002  }
27003  return res
27004}
27005
27006Buffer.prototype.slice = function slice (start, end) {
27007  var len = this.length
27008  start = ~~start
27009  end = end === undefined ? len : ~~end
27010
27011  if (start < 0) {
27012    start += len
27013    if (start < 0) start = 0
27014  } else if (start > len) {
27015    start = len
27016  }
27017
27018  if (end < 0) {
27019    end += len
27020    if (end < 0) end = 0
27021  } else if (end > len) {
27022    end = len
27023  }
27024
27025  if (end < start) end = start
27026
27027  var newBuf
27028  if (Buffer.TYPED_ARRAY_SUPPORT) {
27029    newBuf = Buffer._augment(this.subarray(start, end))
27030  } else {
27031    var sliceLen = end - start
27032    newBuf = new Buffer(sliceLen, undefined)
27033    for (var i = 0; i < sliceLen; i++) {
27034      newBuf[i] = this[i + start]
27035    }
27036  }
27037
27038  if (newBuf.length) newBuf.parent = this.parent || this
27039
27040  return newBuf
27041}
27042
27043/*
27044 * Need to make sure that buffer isn't trying to write out of bounds.
27045 */
vendor: 9,737 bytes, lines 27046-27374
27046function checkOffset (offset, ext, length) {
27047  if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint')
27048  if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')
27049}
27050
27051Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {
27052  offset = offset | 0
27053  byteLength = byteLength | 0
27054  if (!noAssert) checkOffset(offset, byteLength, this.length)
27055
27056  var val = this[offset]
27057  var mul = 1
27058  var i = 0
27059  while (++i < byteLength && (mul *= 0x100)) {
27060    val += this[offset + i] * mul
27061  }
27062
27063  return val
27064}
27065
27066Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {
27067  offset = offset | 0
27068  byteLength = byteLength | 0
27069  if (!noAssert) {
27070    checkOffset(offset, byteLength, this.length)
27071  }
27072
27073  var val = this[offset + --byteLength]
27074  var mul = 1
27075  while (byteLength > 0 && (mul *= 0x100)) {
27076    val += this[offset + --byteLength] * mul
27077  }
27078
27079  return val
27080}
27081
27082Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {
27083  if (!noAssert) checkOffset(offset, 1, this.length)
27084  return this[offset]
27085}
27086
27087Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {
27088  if (!noAssert) checkOffset(offset, 2, this.length)
27089  return this[offset] | (this[offset + 1] << 8)
27090}
27091
27092Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {
27093  if (!noAssert) checkOffset(offset, 2, this.length)
27094  return (this[offset] << 8) | this[offset + 1]
27095}
27096
27097Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {
27098  if (!noAssert) checkOffset(offset, 4, this.length)
27099
27100  return ((this[offset]) |
27101      (this[offset + 1] << 8) |
27102      (this[offset + 2] << 16)) +
27103      (this[offset + 3] * 0x1000000)
27104}
27105
27106Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {
27107  if (!noAssert) checkOffset(offset, 4, this.length)
27108
27109  return (this[offset] * 0x1000000) +
27110    ((this[offset + 1] << 16) |
27111    (this[offset + 2] << 8) |
27112    this[offset + 3])
27113}
27114
27115Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) {
27116  offset = offset | 0
27117  byteLength = byteLength | 0
27118  if (!noAssert) checkOffset(offset, byteLength, this.length)
27119
27120  var val = this[offset]
27121  var mul = 1
27122  var i = 0
27123  while (++i < byteLength && (mul *= 0x100)) {
27124    val += this[offset + i] * mul
27125  }
27126  mul *= 0x80
27127
27128  if (val >= mul) val -= Math.pow(2, 8 * byteLength)
27129
27130  return val
27131}
27132
27133Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) {
27134  offset = offset | 0
27135  byteLength = byteLength | 0
27136  if (!noAssert) checkOffset(offset, byteLength, this.length)
27137
27138  var i = byteLength
27139  var mul = 1
27140  var val = this[offset + --i]
27141  while (i > 0 && (mul *= 0x100)) {
27142    val += this[offset + --i] * mul
27143  }
27144  mul *= 0x80
27145
27146  if (val >= mul) val -= Math.pow(2, 8 * byteLength)
27147
27148  return val
27149}
27150
27151Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) {
27152  if (!noAssert) checkOffset(offset, 1, this.length)
27153  if (!(this[offset] & 0x80)) return (this[offset])
27154  return ((0xff - this[offset] + 1) * -1)
27155}
27156
27157Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) {
27158  if (!noAssert) checkOffset(offset, 2, this.length)
27159  var val = this[offset] | (this[offset + 1] << 8)
27160  return (val & 0x8000) ? val | 0xFFFF0000 : val
27161}
27162
27163Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) {
27164  if (!noAssert) checkOffset(offset, 2, this.length)
27165  var val = this[offset + 1] | (this[offset] << 8)
27166  return (val & 0x8000) ? val | 0xFFFF0000 : val
27167}
27168
27169Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) {
27170  if (!noAssert) checkOffset(offset, 4, this.length)
27171
27172  return (this[offset]) |
27173    (this[offset + 1] << 8) |
27174    (this[offset + 2] << 16) |
27175    (this[offset + 3] << 24)
27176}
27177
27178Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) {
27179  if (!noAssert) checkOffset(offset, 4, this.length)
27180
27181  return (this[offset] << 24) |
27182    (this[offset + 1] << 16) |
27183    (this[offset + 2] << 8) |
27184    (this[offset + 3])
27185}
27186
27187Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) {
27188  if (!noAssert) checkOffset(offset, 4, this.length)
27189  return ieee754.read(this, offset, true, 23, 4)
27190}
27191
27192Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {
27193  if (!noAssert) checkOffset(offset, 4, this.length)
27194  return ieee754.read(this, offset, false, 23, 4)
27195}
27196
27197Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {
27198  if (!noAssert) checkOffset(offset, 8, this.length)
27199  return ieee754.read(this, offset, true, 52, 8)
27200}
27201
27202Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {
27203  if (!noAssert) checkOffset(offset, 8, this.length)
27204  return ieee754.read(this, offset, false, 52, 8)
27205}
27206
27207function checkInt (buf, value, offset, ext, max, min) {
27208  if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance')
27209  if (value > max || value < min) throw new RangeError('value is out of bounds')
27210  if (offset + ext > buf.length) throw new RangeError('index out of range')
27211}
27212
27213Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) {
27214  value = +value
27215  offset = offset | 0
27216  byteLength = byteLength | 0
27217  if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)
27218
27219  var mul = 1
27220  var i = 0
27221  this[offset] = value & 0xFF
27222  while (++i < byteLength && (mul *= 0x100)) {
27223    this[offset + i] = (value / mul) & 0xFF
27224  }
27225
27226  return offset + byteLength
27227}
27228
27229Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) {
27230  value = +value
27231  offset = offset | 0
27232  byteLength = byteLength | 0
27233  if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)
27234
27235  var i = byteLength - 1
27236  var mul = 1
27237  this[offset + i] = value & 0xFF
27238  while (--i >= 0 && (mul *= 0x100)) {
27239    this[offset + i] = (value / mul) & 0xFF
27240  }
27241
27242  return offset + byteLength
27243}
27244
27245Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {
27246  value = +value
27247  offset = offset | 0
27248  if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)
27249  if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
27250  this[offset] = (value & 0xff)
27251  return offset + 1
27252}
27253
27254function objectWriteUInt16 (buf, value, offset, littleEndian) {
27255  if (value < 0) value = 0xffff + value + 1
27256  for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) {
27257    buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>
27258      (littleEndian ? i : 1 - i) * 8
27259  }
27260}
27261
27262Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {
27263  value = +value
27264  offset = offset | 0
27265  if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
27266  if (Buffer.TYPED_ARRAY_SUPPORT) {
27267    this[offset] = (value & 0xff)
27268    this[offset + 1] = (value >>> 8)
27269  } else {
27270    objectWriteUInt16(this, value, offset, true)
27271  }
27272  return offset + 2
27273}
27274
27275Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) {
27276  value = +value
27277  offset = offset | 0
27278  if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
27279  if (Buffer.TYPED_ARRAY_SUPPORT) {
27280    this[offset] = (value >>> 8)
27281    this[offset + 1] = (value & 0xff)
27282  } else {
27283    objectWriteUInt16(this, value, offset, false)
27284  }
27285  return offset + 2
27286}
27287
27288function objectWriteUInt32 (buf, value, offset, littleEndian) {
27289  if (value < 0) value = 0xffffffff + value + 1
27290  for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) {
27291    buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff
27292  }
27293}
27294
27295Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {
27296  value = +value
27297  offset = offset | 0
27298  if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
27299  if (Buffer.TYPED_ARRAY_SUPPORT) {
27300    this[offset + 3] = (value >>> 24)
27301    this[offset + 2] = (value >>> 16)
27302    this[offset + 1] = (value >>> 8)
27303    this[offset] = (value & 0xff)
27304  } else {
27305    objectWriteUInt32(this, value, offset, true)
27306  }
27307  return offset + 4
27308}
27309
27310Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) {
27311  value = +value
27312  offset = offset | 0
27313  if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
27314  if (Buffer.TYPED_ARRAY_SUPPORT) {
27315    this[offset] = (value >>> 24)
27316    this[offset + 1] = (value >>> 16)
27317    this[offset + 2] = (value >>> 8)
27318    this[offset + 3] = (value & 0xff)
27319  } else {
27320    objectWriteUInt32(this, value, offset, false)
27321  }
27322  return offset + 4
27323}
27324
27325Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) {
27326  value = +value
27327  offset = offset | 0
27328  if (!noAssert) {
27329    var limit = Math.pow(2, 8 * byteLength - 1)
27330
27331    checkInt(this, value, offset, byteLength, limit - 1, -limit)
27332  }
27333
27334  var i = 0
27335  var mul = 1
27336  var sub = value < 0 ? 1 : 0
27337  this[offset] = value & 0xFF
27338  while (++i < byteLength && (mul *= 0x100)) {
27339    this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
27340  }
27341
27342  return offset + byteLength
27343}
27344
27345Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) {
27346  value = +value
27347  offset = offset | 0
27348  if (!noAssert) {
27349    var limit = Math.pow(2, 8 * byteLength - 1)
27350
27351    checkInt(this, value, offset, byteLength, limit - 1, -limit)
27352  }
27353
27354  var i = byteLength - 1
27355  var mul = 1
27356  var sub = value < 0 ? 1 : 0
27357  this[offset + i] = value & 0xFF
27358  while (--i >= 0 && (mul *= 0x100)) {
27359    this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
27360  }
27361
27362  return offset + byteLength
27363}
27364
27365Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) {
27366  value = +value
27367  offset = offset | 0
27368  if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)
27369  if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
27370  if (value < 0) value = 0xff + value + 1
27371  this[offset] = (value & 0xff)
27372  return offset + 1
27373}
27374
vendor: 4,133 bytes, lines 27375-27498
27375Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) {
27376  value = +value
27377  offset = offset | 0
27378  if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
27379  if (Buffer.TYPED_ARRAY_SUPPORT) {
27380    this[offset] = (value & 0xff)
27381    this[offset + 1] = (value >>> 8)
27382  } else {
27383    objectWriteUInt16(this, value, offset, true)
27384  }
27385  return offset + 2
27386}
27387
27388Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) {
27389  value = +value
27390  offset = offset | 0
27391  if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
27392  if (Buffer.TYPED_ARRAY_SUPPORT) {
27393    this[offset] = (value >>> 8)
27394    this[offset + 1] = (value & 0xff)
27395  } else {
27396    objectWriteUInt16(this, value, offset, false)
27397  }
27398  return offset + 2
27399}
27400
27401Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) {
27402  value = +value
27403  offset = offset | 0
27404  if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
27405  if (Buffer.TYPED_ARRAY_SUPPORT) {
27406    this[offset] = (value & 0xff)
27407    this[offset + 1] = (value >>> 8)
27408    this[offset + 2] = (value >>> 16)
27409    this[offset + 3] = (value >>> 24)
27410  } else {
27411    objectWriteUInt32(this, value, offset, true)
27412  }
27413  return offset + 4
27414}
27415
27416Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) {
27417  value = +value
27418  offset = offset | 0
27419  if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
27420  if (value < 0) value = 0xffffffff + value + 1
27421  if (Buffer.TYPED_ARRAY_SUPPORT) {
27422    this[offset] = (value >>> 24)
27423    this[offset + 1] = (value >>> 16)
27424    this[offset + 2] = (value >>> 8)
27425    this[offset + 3] = (value & 0xff)
27426  } else {
27427    objectWriteUInt32(this, value, offset, false)
27428  }
27429  return offset + 4
27430}
27431
27432function checkIEEE754 (buf, value, offset, ext, max, min) {
27433  if (value > max || value < min) throw new RangeError('value is out of bounds')
27434  if (offset + ext > buf.length) throw new RangeError('index out of range')
27435  if (offset < 0) throw new RangeError('index out of range')
27436}
27437
27438function writeFloat (buf, value, offset, littleEndian, noAssert) {
27439  if (!noAssert) {
27440    checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)
27441  }
27442  ieee754.write(buf, value, offset, littleEndian, 23, 4)
27443  return offset + 4
27444}
27445
27446Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) {
27447  return writeFloat(this, value, offset, true, noAssert)
27448}
27449
27450Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) {
27451  return writeFloat(this, value, offset, false, noAssert)
27452}
27453
27454function writeDouble (buf, value, offset, littleEndian, noAssert) {
27455  if (!noAssert) {
27456    checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)
27457  }
27458  ieee754.write(buf, value, offset, littleEndian, 52, 8)
27459  return offset + 8
27460}
27461
27462Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) {
27463  return writeDouble(this, value, offset, true, noAssert)
27464}
27465
27466Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) {
27467  return writeDouble(this, value, offset, false, noAssert)
27468}
27469
27470// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
27471Buffer.prototype.copy = function copy (target, targetStart, start, end) {
27472  if (!start) start = 0
27473  if (!end && end !== 0) end = this.length
27474  if (targetStart >= target.length) targetStart = target.length
27475  if (!targetStart) targetStart = 0
27476  if (end > 0 && end < start) end = start
27477
27478  // Copy 0 bytes; we're done
27479  if (end === start) return 0
27480  if (target.length === 0 || this.length === 0) return 0
27481
27482  // Fatal error conditions
27483  if (targetStart < 0) {
27484    throw new RangeError('targetStart out of bounds')
27485  }
27486  if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds')
27487  if (end < 0) throw new RangeError('sourceEnd out of bounds')
27488
27489  // Are we oob?
27490  if (end > this.length) end = this.length
27491  if (target.length - targetStart < end - start) {
27492    end = target.length - targetStart + start
27493  }
27494
27495  var len = end - start
27496  var i
27497
27498  if (this === target && start < targetStart && targetStart < end) {
27499    // descending copy from end
27500    for (i = len - 1; i >= 0; i--) {
27501      target[i + targetStart] = this[i + start]
27502    }
27503  } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) {
27504    // ascending copy from start
27505    for (i = 0; i < len; i++) {
27506      target[i + targetStart] = this[i + start]
27507    }
27508  } else {
27509    target._set(this.subarray(start, start + len), targetStart)
27510  }
27511
27512  return len
27513}
27514
27515// fill(value, start=0, end=buffer.length)
27516Buffer.prototype.fill = function fill (value, start, end) {
27517  if (!value) value = 0
27518  if (!start) start = 0
27519  if (!end) end = this.length
27520
27521  if (end < start) throw new RangeError('end < start')
27522
27523  // Fill 0 bytes; we're done
27524  if (end === start) return
27525  if (this.length === 0) return
27526
27527  if (start < 0 || start >= this.length) throw new RangeError('start out of bounds')
27528  if (end < 0 || end > this.length) throw new RangeError('end out of bounds')
27529
27530  var i
27531  if (typeof value === 'number') {
27532    for (i = start; i < end; i++) {
27533      this[i] = value
27534    }
27535  } else {
27536    var bytes = utf8ToBytes(value.toString())
27537    var len = bytes.length
27538    for (i = start; i < end; i++) {
27539      this[i] = bytes[i % len]
27540    }
27541  }
27542
27543  return this
27544}
27545
27546/**
27547 * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance.
27548 * Added in Node 0.12. Only available in browsers that support ArrayBuffer.
27549 */
27550Buffer.prototype.toArrayBuffer = function toArrayBuffer () {
27551  if (typeof Uint8Array !== 'undefined') {
27552    if (Buffer.TYPED_ARRAY_SUPPORT) {
27553      return (new Buffer(this)).buffer
27554    } else {
27555      var buf = new Uint8Array(this.length)
27556      for (var i = 0, len = buf.length; i < len; i += 1) {
27557        buf[i] = this[i]
27558      }
27559      return buf.buffer
27560    }
27561  } else {
27562    throw new TypeError('Buffer.toArrayBuffer not supported in this browser')
27563  }
27564}
27565
27566// HELPER FUNCTIONS
27567// ================
27568
27569var BP = Buffer.prototype
27570
27571/**
27572 * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods
27573 */
27574Buffer._augment = function _augment (arr) {
27575  arr.constructor = Buffer
27576  arr._isBuffer = true
27577
27578  // save reference to original Uint8Array set method before overwriting
27579  arr._set = arr.set
27580
27581  // deprecated
27582  arr.get = BP.get
27583  arr.set = BP.set
27584
27585  arr.write = BP.write
27586  arr.toString = BP.toString
27587  arr.toLocaleString = BP.toString
27588  arr.toJSON = BP.toJSON
27589  arr.equals = BP.equals
27590  arr.compare = BP.compare
27591  arr.indexOf = BP.indexOf
27592  arr.copy = BP.copy
27593  arr.slice = BP.slice
27594  arr.readUIntLE = BP.readUIntLE
27595  arr.readUIntBE = BP.readUIntBE
27596  arr.readUInt8 = BP.readUInt8
27597  arr.readUInt16LE = BP.readUInt16LE
27598  arr.readUInt16BE = BP.readUInt16BE
27599  arr.readUInt32LE = BP.readUInt32LE
27600  arr.readUInt32BE = BP.readUInt32BE
27601  arr.readIntLE = BP.readIntLE
27602  arr.readIntBE = BP.readIntBE
27603  arr.readInt8 = BP.readInt8
27604  arr.readInt16LE = BP.readInt16LE
27605  arr.readInt16BE = BP.readInt16BE
27606  arr.readInt32LE = BP.readInt32LE
27607  arr.readInt32BE = BP.readInt32BE
27608  arr.readFloatLE = BP.readFloatLE
27609  arr.readFloatBE = BP.readFloatBE
27610  arr.readDoubleLE = BP.readDoubleLE
27611  arr.readDoubleBE = BP.readDoubleBE
27612  arr.writeUInt8 = BP.writeUInt8
27613  arr.writeUIntLE = BP.writeUIntLE
27614  arr.writeUIntBE = BP.writeUIntBE
27615  arr.writeUInt16LE = BP.writeUInt16LE
27616  arr.writeUInt16BE = BP.writeUInt16BE
27617  arr.writeUInt32LE = BP.writeUInt32LE
27618  arr.writeUInt32BE = BP.writeUInt32BE
27619  arr.writeIntLE = BP.writeIntLE
27620  arr.writeIntBE = BP.writeIntBE
27621  arr.writeInt8 = BP.writeInt8
27622  arr.writeInt16LE = BP.writeInt16LE
27623  arr.writeInt16BE = BP.writeInt16BE
27624  arr.writeInt32LE = BP.writeInt32LE
27625  arr.writeInt32BE = BP.writeInt32BE
27626  arr.writeFloatLE = BP.writeFloatLE
27627  arr.writeFloatBE = BP.writeFloatBE
27628  arr.writeDoubleLE = BP.writeDoubleLE
27629  arr.writeDoubleBE = BP.writeDoubleBE
27630  arr.fill = BP.fill
27631  arr.inspect = BP.inspect
27632  arr.toArrayBuffer = BP.toArrayBuffer
27633
27634  return arr
27635}
27636
27637var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g
27638
27639function base64clean (str) {
27640  // Node strips out invalid characters like \n and \t from the string, base64-js does not
27641  str = stringtrim(str).replace(INVALID_BASE64_RE, '')
27642  // Node converts strings with length < 2 to ''
27643  if (str.length < 2) return ''
27644  // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
27645  while (str.length % 4 !== 0) {
27646    str = str + '='
27647  }
27648  return str
27649}
27650
27651function stringtrim (str) {
27652  if (str.trim) return str.trim()
27653  return str.replace(/^\s+|\s+$/g, '')
27654}
27655
27656function toHex (n) {
27657  if (n < 16) return '0' + n.toString(16)
27658  return n.toString(16)
27659}
27660
27661function utf8ToBytes (string, units) {
27662  units = units || Infinity
27663  var codePoint
27664  var length = string.length
27665  var leadSurrogate = null
27666  var bytes = []
27667
27668  for (var i = 0; i < length; i++) {
27669    codePoint = string.charCodeAt(i)
27670
27671    // is surrogate component
27672    if (codePoint > 0xD7FF && codePoint < 0xE000) {
27673      // last char was a lead
27674      if (!leadSurrogate) {
27675        // no lead yet
27676        if (codePoint > 0xDBFF) {
27677          // unexpected trail
27678          if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
27679          continue
27680        } else if (i + 1 === length) {
27681          // unpaired lead
27682          if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
27683          continue
27684        }
27685
27686        // valid lead
27687        leadSurrogate = codePoint
27688
27689        continue
27690      }
27691
27692      // 2 leads in a row
27693      if (codePoint < 0xDC00) {
27694        if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
27695        leadSurrogate = codePoint
27696        continue
27697      }
27698
27699      // valid surrogate pair
27700      codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000
27701    } else if (leadSurrogate) {
27702      // valid bmp char, but last char was a lead
27703      if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
27704    }
27705
27706    leadSurrogate = null
27707
27708    // encode utf8
27709    if (codePoint < 0x80) {
27710      if ((units -= 1) < 0) break
27711      bytes.push(codePoint)
27712    } else if (codePoint < 0x800) {
27713      if ((units -= 2) < 0) break
27714      bytes.push(
27715        codePoint >> 0x6 | 0xC0,
27716        codePoint & 0x3F | 0x80
27717      )
27718    } else if (codePoint < 0x10000) {
27719      if ((units -= 3) < 0) break
27720      bytes.push(
27721        codePoint >> 0xC | 0xE0,
27722        codePoint >> 0x6 & 0x3F | 0x80,
27723        codePoint & 0x3F | 0x80
27724      )
27725    } else if (codePoint < 0x110000) {
27726      if ((units -= 4) < 0) break
27727      bytes.push(
27728        codePoint >> 0x12 | 0xF0,
27729        codePoint >> 0xC & 0x3F | 0x80,
27730        codePoint >> 0x6 & 0x3F | 0x80,
27731        codePoint & 0x3F | 0x80
27732      )
27733    } else {
27734      throw new Error('Invalid code point')
27735    }
27736  }
27737
27738  return bytes
27739}
27740
27741function asciiToBytes (str) {
27742  var byteArray = []
27743  for (var i = 0; i < str.length; i++) {
27744    // Node's code seems to be doing this and not & 0x7F..
27745    byteArray.push(str.charCodeAt(i) & 0xFF)
27746  }
27747  return byteArray
27748}
27749
27750function utf16leToBytes (str, units) {
27751  var c, hi, lo
27752  var byteArray = []
27753  for (var i = 0; i < str.length; i++) {
27754    if ((units -= 2) < 0) break
27755
27756    c = str.charCodeAt(i)
27757    hi = c >> 8
27758    lo = c % 256
27759    byteArray.push(lo)
27760    byteArray.push(hi)
27761  }
27762
27763  return byteArray
27764}
27765
27766function base64ToBytes (str) {
27767  return base64.toByteArray(base64clean(str))
27768}
27769
27770function blitBuffer (src, dst, offset, length) {
27771  for (var i = 0; i < length; i++) {
27772    if ((i + offset >= dst.length) || (i >= src.length)) break
27773    dst[i + offset] = src[i]
27774  }
27775  return i
27776}
27777
27778}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
27779},{"base64-js":2,"ieee754":8,"isarray":9}],5:[function(_dereq_,module,exports){
27780(function (process,global){
27781/*!
27782 * @overview es6-promise - a tiny implementation of Promises/A+.
27783 * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald)
27784 * @license   Licensed under MIT license
27785 *            See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE
27786 * @version   4.1.1
27787 */
27788
27789(function (global, factory) {
27790	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
27791	typeof define === 'function' && define.amd ? define(factory) :
27792	(global.ES6Promise = factory());
27793}(this, (function () { 'use strict';
27794
27795function objectOrFunction(x) {
27796  var type = typeof x;
27797  return x !== null && (type === 'object' || type === 'function');
27798}
27799
27800function isFunction(x) {
27801  return typeof x === 'function';
27802}
27803
27804var _isArray = undefined;
27805if (Array.isArray) {
27806  _isArray = Array.isArray;
27807} else {
27808  _isArray = function (x) {
27809    return Object.prototype.toString.call(x) === '[object Array]';
27810  };
27811}
27812
27813var isArray = _isArray;
27814
27815var len = 0;
27816var vertxNext = undefined;
27817var customSchedulerFn = undefined;
27818
27819var asap = function asap(callback, arg) {
27820  queue[len] = callback;
27821  queue[len + 1] = arg;
27822  len += 2;
27823  if (len === 2) {
27824    // If len is 2, that means that we need to schedule an async flush.
27825    // If additional callbacks are queued before the queue is flushed, they
27826    // will be processed by this flush that we are scheduling.
27827    if (customSchedulerFn) {
27828      customSchedulerFn(flush);
27829    } else {
27830      scheduleFlush();
27831    }
27832  }
27833};
27834
27835function setScheduler(scheduleFn) {
27836  customSchedulerFn = scheduleFn;
27837}
27838
27839function setAsap(asapFn) {
27840  asap = asapFn;
27841}
27842
27843var browserWindow = typeof window !== 'undefined' ? window : undefined;
27844var browserGlobal = browserWindow || {};
27845var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
27846var isNode = typeof self === 'undefined' && typeof process !== 'undefined' && ({}).toString.call(process) === '[object process]';
27847
27848// test for web worker but not in IE10
27849var isWorker = typeof Uint8ClampedArray !== 'undefined' && typeof importScripts !== 'undefined' && typeof MessageChannel !== 'undefined';
27850
27851// node
27852function useNextTick() {
27853  // node version 0.10.x displays a deprecation warning when nextTick is used recursively
27854  // see https://github.com/cujojs/when/issues/410 for details
27855  return function () {
27856    return process.nextTick(flush);
27857  };
27858}
27859
27860// vertx
27861function useVertxTimer() {
27862  if (typeof vertxNext !== 'undefined') {
27863    return function () {
27864      vertxNext(flush);
27865    };
27866  }
27867
27868  return useSetTimeout();
27869}
27870
27871function useMutationObserver() {
27872  var iterations = 0;
27873  var observer = new BrowserMutationObserver(flush);
27874  var node = document.createTextNode('');
27875  observer.observe(node, { characterData: true });
27876
27877  return function () {
27878    node.data = iterations = ++iterations % 2;
27879  };
27880}
27881
27882// web worker
27883function useMessageChannel() {
27884  var channel = new MessageChannel();
27885  channel.port1.onmessage = flush;
27886  return function () {
27887    return channel.port2.postMessage(0);
27888  };
27889}
27890
27891function useSetTimeout() {
27892  // Store setTimeout reference so es6-promise will be unaffected by
27893  // other code modifying setTimeout (like sinon.useFakeTimers())
27894  var globalSetTimeout = setTimeout;
27895  return function () {
27896    return globalSetTimeout(flush, 1);
27897  };
27898}
27899
27900var queue = new Array(1000);
27901function flush() {
27902  for (var i = 0; i < len; i += 2) {
27903    var callback = queue[i];
27904    var arg = queue[i + 1];
27905
27906    callback(arg);
27907
27908    queue[i] = undefined;
27909    queue[i + 1] = undefined;
27910  }
27911
27912  len = 0;
27913}
27914
27915function attemptVertx() {
27916  try {
27917    var r = _dereq_;
27918    var vertx = r('vertx');
27919    vertxNext = vertx.runOnLoop || vertx.runOnContext;
27920    return useVertxTimer();
27921  } catch (e) {
27922    return useSetTimeout();
27923  }
27924}
27925
27926var scheduleFlush = undefined;
27927// Decide what async method to use to triggering processing of queued callbacks:
27928if (isNode) {
27929  scheduleFlush = useNextTick();
27930} else if (BrowserMutationObserver) {
27931  scheduleFlush = useMutationObserver();
27932} else if (isWorker) {
27933  scheduleFlush = useMessageChannel();
27934} else if (browserWindow === undefined && typeof _dereq_
vendor: 24,376 bytes, lines 27934-28936
27934 === 'function') {
27935  scheduleFlush = attemptVertx();
27936} else {
27937  scheduleFlush = useSetTimeout();
27938}
27939
27940function then(onFulfillment, onRejection) {
27941  var _arguments = arguments;
27942
27943  var parent = this;
27944
27945  var child = new this.constructor(noop);
27946
27947  if (child[PROMISE_ID] === undefined) {
27948    makePromise(child);
27949  }
27950
27951  var _state = parent._state;
27952
27953  if (_state) {
27954    (function () {
27955      var callback = _arguments[_state - 1];
27956      asap(function () {
27957        return invokeCallback(_state, child, callback, parent._result);
27958      });
27959    })();
27960  } else {
27961    subscribe(parent, child, onFulfillment, onRejection);
27962  }
27963
27964  return child;
27965}
27966
27967/**
27968  `Promise.resolve` returns a promise that will become resolved with the
27969  passed `value`. It is shorthand for the following:
27970
27971  ```javascript
27972  let promise = new Promise(function(resolve, reject){
27973    resolve(1);
27974  });
27975
27976  promise.then(function(value){
27977    // value === 1
27978  });
27979  ```
27980
27981  Instead of writing the above, your code now simply becomes the following:
27982
27983  ```javascript
27984  let promise = Promise.resolve(1);
27985
27986  promise.then(function(value){
27987    // value === 1
27988  });
27989  ```
27990
27991  @method resolve
27992  @static
27993  @param {Any} value value that the returned promise will be resolved with
27994  Useful for tooling.
27995  @return {Promise} a promise that will become fulfilled with the given
27996  `value`
27997*/
27998function resolve$1(object) {
27999  /*jshint validthis:true */
28000  var Constructor = this;
28001
28002  if (object && typeof object === 'object' && object.constructor === Constructor) {
28003    return object;
28004  }
28005
28006  var promise = new Constructor(noop);
28007  resolve(promise, object);
28008  return promise;
28009}
28010
28011var PROMISE_ID = Math.random().toString(36).substring(16);
28012
28013function noop() {}
28014
28015var PENDING = void 0;
28016var FULFILLED = 1;
28017var REJECTED = 2;
28018
28019var GET_THEN_ERROR = new ErrorObject();
28020
28021function selfFulfillment() {
28022  return new TypeError("You cannot resolve a promise with itself");
28023}
28024
28025function cannotReturnOwn() {
28026  return new TypeError('A promises callback cannot return that same promise.');
28027}
28028
28029function getThen(promise) {
28030  try {
28031    return promise.then;
28032  } catch (error) {
28033    GET_THEN_ERROR.error = error;
28034    return GET_THEN_ERROR;
28035  }
28036}
28037
28038function tryThen(then$$1, value, fulfillmentHandler, rejectionHandler) {
28039  try {
28040    then$$1.call(value, fulfillmentHandler, rejectionHandler);
28041  } catch (e) {
28042    return e;
28043  }
28044}
28045
28046function handleForeignThenable(promise, thenable, then$$1) {
28047  asap(function (promise) {
28048    var sealed = false;
28049    var error = tryThen(then$$1, thenable, function (value) {
28050      if (sealed) {
28051        return;
28052      }
28053      sealed = true;
28054      if (thenable !== value) {
28055        resolve(promise, value);
28056      } else {
28057        fulfill(promise, value);
28058      }
28059    }, function (reason) {
28060      if (sealed) {
28061        return;
28062      }
28063      sealed = true;
28064
28065      reject(promise, reason);
28066    }, 'Settle: ' + (promise._label || ' unknown promise'));
28067
28068    if (!sealed && error) {
28069      sealed = true;
28070      reject(promise, error);
28071    }
28072  }, promise);
28073}
28074
28075function handleOwnThenable(promise, thenable) {
28076  if (thenable._state === FULFILLED) {
28077    fulfill(promise, thenable._result);
28078  } else if (thenable._state === REJECTED) {
28079    reject(promise, thenable._result);
28080  } else {
28081    subscribe(thenable, undefined, function (value) {
28082      return resolve(promise, value);
28083    }, function (reason) {
28084      return reject(promise, reason);
28085    });
28086  }
28087}
28088
28089function handleMaybeThenable(promise, maybeThenable, then$$1) {
28090  if (maybeThenable.constructor === promise.constructor && then$$1 === then && maybeThenable.constructor.resolve === resolve$1) {
28091    handleOwnThenable(promise, maybeThenable);
28092  } else {
28093    if (then$$1 === GET_THEN_ERROR) {
28094      reject(promise, GET_THEN_ERROR.error);
28095      GET_THEN_ERROR.error = null;
28096    } else if (then$$1 === undefined) {
28097      fulfill(promise, maybeThenable);
28098    } else if (isFunction(then$$1)) {
28099      handleForeignThenable(promise, maybeThenable, then$$1);
28100    } else {
28101      fulfill(promise, maybeThenable);
28102    }
28103  }
28104}
28105
28106function resolve(promise, value) {
28107  if (promise === value) {
28108    reject(promise, selfFulfillment());
28109  } else if (objectOrFunction(value)) {
28110    handleMaybeThenable(promise, value, getThen(value));
28111  } else {
28112    fulfill(promise, value);
28113  }
28114}
28115
28116function publishRejection(promise) {
28117  if (promise._onerror) {
28118    promise._onerror(promise._result);
28119  }
28120
28121  publish(promise);
28122}
28123
28124function fulfill(promise, value) {
28125  if (promise._state !== PENDING) {
28126    return;
28127  }
28128
28129  promise._result = value;
28130  promise._state = FULFILLED;
28131
28132  if (promise._subscribers.length !== 0) {
28133    asap(publish, promise);
28134  }
28135}
28136
28137function reject(promise, reason) {
28138  if (promise._state !== PENDING) {
28139    return;
28140  }
28141  promise._state = REJECTED;
28142  promise._result = reason;
28143
28144  asap(publishRejection, promise);
28145}
28146
28147function subscribe(parent, child, onFulfillment, onRejection) {
28148  var _subscribers = parent._subscribers;
28149  var length = _subscribers.length;
28150
28151  parent._onerror = null;
28152
28153  _subscribers[length] = child;
28154  _subscribers[length + FULFILLED] = onFulfillment;
28155  _subscribers[length + REJECTED] = onRejection;
28156
28157  if (length === 0 && parent._state) {
28158    asap(publish, parent);
28159  }
28160}
28161
28162function publish(promise) {
28163  var subscribers = promise._subscribers;
28164  var settled = promise._state;
28165
28166  if (subscribers.length === 0) {
28167    return;
28168  }
28169
28170  var child = undefined,
28171      callback = undefined,
28172      detail = promise._result;
28173
28174  for (var i = 0; i < subscribers.length; i += 3) {
28175    child = subscribers[i];
28176    callback = subscribers[i + settled];
28177
28178    if (child) {
28179      invokeCallback(settled, child, callback, detail);
28180    } else {
28181      callback(detail);
28182    }
28183  }
28184
28185  promise._subscribers.length = 0;
28186}
28187
28188function ErrorObject() {
28189  this.error = null;
28190}
28191
28192var TRY_CATCH_ERROR = new ErrorObject();
28193
28194function tryCatch(callback, detail) {
28195  try {
28196    return callback(detail);
28197  } catch (e) {
28198    TRY_CATCH_ERROR.error = e;
28199    return TRY_CATCH_ERROR;
28200  }
28201}
28202
28203function invokeCallback(settled, promise, callback, detail) {
28204  var hasCallback = isFunction(callback),
28205      value = undefined,
28206      error = undefined,
28207      succeeded = undefined,
28208      failed = undefined;
28209
28210  if (hasCallback) {
28211    value = tryCatch(callback, detail);
28212
28213    if (value === TRY_CATCH_ERROR) {
28214      failed = true;
28215      error = value.error;
28216      value.error = null;
28217    } else {
28218      succeeded = true;
28219    }
28220
28221    if (promise === value) {
28222      reject(promise, cannotReturnOwn());
28223      return;
28224    }
28225  } else {
28226    value = detail;
28227    succeeded = true;
28228  }
28229
28230  if (promise._state !== PENDING) {
28231    // noop
28232  } else if (hasCallback && succeeded) {
28233      resolve(promise, value);
28234    } else if (failed) {
28235      reject(promise, error);
28236    } else if (settled === FULFILLED) {
28237      fulfill(promise, value);
28238    } else if (settled === REJECTED) {
28239      reject(promise, value);
28240    }
28241}
28242
28243function initializePromise(promise, resolver) {
28244  try {
28245    resolver(function resolvePromise(value) {
28246      resolve(promise, value);
28247    }, function rejectPromise(reason) {
28248      reject(promise, reason);
28249    });
28250  } catch (e) {
28251    reject(promise, e);
28252  }
28253}
28254
28255var id = 0;
28256function nextId() {
28257  return id++;
28258}
28259
28260function makePromise(promise) {
28261  promise[PROMISE_ID] = id++;
28262  promise._state = undefined;
28263  promise._result = undefined;
28264  promise._subscribers = [];
28265}
28266
28267function Enumerator$1(Constructor, input) {
28268  this._instanceConstructor = Constructor;
28269  this.promise = new Constructor(noop);
28270
28271  if (!this.promise[PROMISE_ID]) {
28272    makePromise(this.promise);
28273  }
28274
28275  if (isArray(input)) {
28276    this.length = input.length;
28277    this._remaining = input.length;
28278
28279    this._result = new Array(this.length);
28280
28281    if (this.length === 0) {
28282      fulfill(this.promise, this._result);
28283    } else {
28284      this.length = this.length || 0;
28285      this._enumerate(input);
28286      if (this._remaining === 0) {
28287        fulfill(this.promise, this._result);
28288      }
28289    }
28290  } else {
28291    reject(this.promise, validationError());
28292  }
28293}
28294
28295function validationError() {
28296  return new Error('Array Methods must be provided an Array');
28297}
28298
28299Enumerator$1.prototype._enumerate = function (input) {
28300  for (var i = 0; this._state === PENDING && i < input.length; i++) {
28301    this._eachEntry(input[i], i);
28302  }
28303};
28304
28305Enumerator$1.prototype._eachEntry = function (entry, i) {
28306  var c = this._instanceConstructor;
28307  var resolve$$1 = c.resolve;
28308
28309  if (resolve$$1 === resolve$1) {
28310    var _then = getThen(entry);
28311
28312    if (_then === then && entry._state !== PENDING) {
28313      this._settledAt(entry._state, i, entry._result);
28314    } else if (typeof _then !== 'function') {
28315      this._remaining--;
28316      this._result[i] = entry;
28317    } else if (c === Promise$2) {
28318      var promise = new c(noop);
28319      handleMaybeThenable(promise, entry, _then);
28320      this._willSettleAt(promise, i);
28321    } else {
28322      this._willSettleAt(new c(function (resolve$$1) {
28323        return resolve$$1(entry);
28324      }), i);
28325    }
28326  } else {
28327    this._willSettleAt(resolve$$1(entry), i);
28328  }
28329};
28330
28331Enumerator$1.prototype._settledAt = function (state, i, value) {
28332  var promise = this.promise;
28333
28334  if (promise._state === PENDING) {
28335    this._remaining--;
28336
28337    if (state === REJECTED) {
28338      reject(promise, value);
28339    } else {
28340      this._result[i] = value;
28341    }
28342  }
28343
28344  if (this._remaining === 0) {
28345    fulfill(promise, this._result);
28346  }
28347};
28348
28349Enumerator$1.prototype._willSettleAt = function (promise, i) {
28350  var enumerator = this;
28351
28352  subscribe(promise, undefined, function (value) {
28353    return enumerator._settledAt(FULFILLED, i, value);
28354  }, function (reason) {
28355    return enumerator._settledAt(REJECTED, i, reason);
28356  });
28357};
28358
28359/**
28360  `Promise.all` accepts an array of promises, and returns a new promise which
28361  is fulfilled with an array of fulfillment values for the passed promises, or
28362  rejected with the reason of the first passed promise to be rejected. It casts all
28363  elements of the passed iterable to promises as it runs this algorithm.
28364
28365  Example:
28366
28367  ```javascript
28368  let promise1 = resolve(1);
28369  let promise2 = resolve(2);
28370  let promise3 = resolve(3);
28371  let promises = [ promise1, promise2, promise3 ];
28372
28373  Promise.all(promises).then(function(array){
28374    // The array here would be [ 1, 2, 3 ];
28375  });
28376  ```
28377
28378  If any of the `promises` given to `all` are rejected, the first promise
28379  that is rejected will be given as an argument to the returned promises's
28380  rejection handler. For example:
28381
28382  Example:
28383
28384  ```javascript
28385  let promise1 = resolve(1);
28386  let promise2 = reject(new Error("2"));
28387  let promise3 = reject(new Error("3"));
28388  let promises = [ promise1, promise2, promise3 ];
28389
28390  Promise.all(promises).then(function(array){
28391    // Code here never runs because there are rejected promises!
28392  }, function(error) {
28393    // error.message === "2"
28394  });
28395  ```
28396
28397  @method all
28398  @static
28399  @param {Array} entries array of promises
28400  @param {String} label optional string for labeling the promise.
28401  Useful for tooling.
28402  @return {Promise} promise that is fulfilled when all `promises` have been
28403  fulfilled, or rejected if any of them become rejected.
28404  @static
28405*/
28406function all$1(entries) {
28407  return new Enumerator$1(this, entries).promise;
28408}
28409
28410/**
28411  `Promise.race` returns a new promise which is settled in the same way as the
28412  first passed promise to settle.
28413
28414  Example:
28415
28416  ```javascript
28417  let promise1 = new Promise(function(resolve, reject){
28418    setTimeout(function(){
28419      resolve('promise 1');
28420    }, 200);
28421  });
28422
28423  let promise2 = new Promise(function(resolve, reject){
28424    setTimeout(function(){
28425      resolve('promise 2');
28426    }, 100);
28427  });
28428
28429  Promise.race([promise1, promise2]).then(function(result){
28430    // result === 'promise 2' because it was resolved before promise1
28431    // was resolved.
28432  });
28433  ```
28434
28435  `Promise.race` is deterministic in that only the state of the first
28436  settled promise matters. For example, even if other promises given to the
28437  `promises` array argument are resolved, but the first settled promise has
28438  become rejected before the other promises became fulfilled, the returned
28439  promise will become rejected:
28440
28441  ```javascript
28442  let promise1 = new Promise(function(resolve, reject){
28443    setTimeout(function(){
28444      resolve('promise 1');
28445    }, 200);
28446  });
28447
28448  let promise2 = new Promise(function(resolve, reject){
28449    setTimeout(function(){
28450      reject(new Error('promise 2'));
28451    }, 100);
28452  });
28453
28454  Promise.race([promise1, promise2]).then(function(result){
28455    // Code here never runs
28456  }, function(reason){
28457    // reason.message === 'promise 2' because promise 2 became rejected before
28458    // promise 1 became fulfilled
28459  });
28460  ```
28461
28462  An example real-world use case is implementing timeouts:
28463
28464  ```javascript
28465  Promise.race([ajax('foo.json'), timeout(5000)])
28466  ```
28467
28468  @method race
28469  @static
28470  @param {Array} promises array of promises to observe
28471  Useful for tooling.
28472  @return {Promise} a promise which settles in the same way as the first passed
28473  promise to settle.
28474*/
28475function race$1(entries) {
28476  /*jshint validthis:true */
28477  var Constructor = this;
28478
28479  if (!isArray(entries)) {
28480    return new Constructor(function (_, reject) {
28481      return reject(new TypeError('You must pass an array to race.'));
28482    });
28483  } else {
28484    return new Constructor(function (resolve, reject) {
28485      var length = entries.length;
28486      for (var i = 0; i < length; i++) {
28487        Constructor.resolve(entries[i]).then(resolve, reject);
28488      }
28489    });
28490  }
28491}
28492
28493/**
28494  `Promise.reject` returns a promise rejected with the passed `reason`.
28495  It is shorthand for the following:
28496
28497  ```javascript
28498  let promise = new Promise(function(resolve, reject){
28499    reject(new Error('WHOOPS'));
28500  });
28501
28502  promise.then(function(value){
28503    // Code here doesn't run because the promise is rejected!
28504  }, function(reason){
28505    // reason.message === 'WHOOPS'
28506  });
28507  ```
28508
28509  Instead of writing the above, your code now simply becomes the following:
28510
28511  ```javascript
28512  let promise = Promise.reject(new Error('WHOOPS'));
28513
28514  promise.then(function(value){
28515    // Code here doesn't run because the promise is rejected!
28516  }, function(reason){
28517    // reason.message === 'WHOOPS'
28518  });
28519  ```
28520
28521  @method reject
28522  @static
28523  @param {Any} reason value that the returned promise will be rejected with.
28524  Useful for tooling.
28525  @return {Promise} a promise rejected with the given `reason`.
28526*/
28527function reject$1(reason) {
28528  /*jshint validthis:true */
28529  var Constructor = this;
28530  var promise = new Constructor(noop);
28531  reject(promise, reason);
28532  return promise;
28533}
28534
28535function needsResolver() {
28536  throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');
28537}
28538
28539function needsNew() {
28540  throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");
28541}
28542
28543/**
28544  Promise objects represent the eventual result of an asynchronous operation. The
28545  primary way of interacting with a promise is through its `then` method, which
28546  registers callbacks to receive either a promise's eventual value or the reason
28547  why the promise cannot be fulfilled.
28548
28549  Terminology
28550  -----------
28551
28552  - `promise` is an object or function with a `then` method whose behavior conforms to this specification.
28553  - `thenable` is an object or function that defines a `then` method.
28554  - `value` is any legal JavaScript value (including undefined, a thenable, or a promise).
28555  - `exception` is a value that is thrown using the throw statement.
28556  - `reason` is a value that indicates why a promise was rejected.
28557  - `settled` the final resting state of a promise, fulfilled or rejected.
28558
28559  A promise can be in one of three states: pending, fulfilled, or rejected.
28560
28561  Promises that are fulfilled have a fulfillment value and are in the fulfilled
28562  state.  Promises that are rejected have a rejection reason and are in the
28563  rejected state.  A fulfillment value is never a thenable.
28564
28565  Promises can also be said to *resolve* a value.  If this value is also a
28566  promise, then the original promise's settled state will match the value's
28567  settled state.  So a promise that *resolves* a promise that rejects will
28568  itself reject, and a promise that *resolves* a promise that fulfills will
28569  itself fulfill.
28570
28571
28572  Basic Usage:
28573  ------------
28574
28575  ```js
28576  let promise = new Promise(function(resolve, reject) {
28577    // on success
28578    resolve(value);
28579
28580    // on failure
28581    reject(reason);
28582  });
28583
28584  promise.then(function(value) {
28585    // on fulfillment
28586  }, function(reason) {
28587    // on rejection
28588  });
28589  ```
28590
28591  Advanced Usage:
28592  ---------------
28593
28594  Promises shine when abstracting away asynchronous interactions such as
28595  `XMLHttpRequest`s.
28596
28597  ```js
28598  function getJSON(url) {
28599    return new Promise(function(resolve, reject){
28600      let xhr = new XMLHttpRequest();
28601
28602      xhr.open('GET', url);
28603      xhr.onreadystatechange = handler;
28604      xhr.responseType = 'json';
28605      xhr.setRequestHeader('Accept', 'application/json');
28606      xhr.send();
28607
28608      function handler() {
28609        if (this.readyState === this.DONE) {
28610          if (this.status === 200) {
28611            resolve(this.response);
28612          } else {
28613            reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']'));
28614          }
28615        }
28616      };
28617    });
28618  }
28619
28620  getJSON('/posts.json').then(function(json) {
28621    // on fulfillment
28622  }, function(reason) {
28623    // on rejection
28624  });
28625  ```
28626
28627  Unlike callbacks, promises are great composable primitives.
28628
28629  ```js
28630  Promise.all([
28631    getJSON('/posts'),
28632    getJSON('/comments')
28633  ]).then(function(values){
28634    values[0] // => postsJSON
28635    values[1] // => commentsJSON
28636
28637    return values;
28638  });
28639  ```
28640
28641  @class Promise
28642  @param {function} resolver
28643  Useful for tooling.
28644  @constructor
28645*/
28646function Promise$2(resolver) {
28647  this[PROMISE_ID] = nextId();
28648  this._result = this._state = undefined;
28649  this._subscribers = [];
28650
28651  if (noop !== resolver) {
28652    typeof resolver !== 'function' && needsResolver();
28653    this instanceof Promise$2 ? initializePromise(this, resolver) : needsNew();
28654  }
28655}
28656
28657Promise$2.all = all$1;
28658Promise$2.race = race$1;
28659Promise$2.resolve = resolve$1;
28660Promise$2.reject = reject$1;
28661Promise$2._setScheduler = setScheduler;
28662Promise$2._setAsap = setAsap;
28663Promise$2._asap = asap;
28664
28665Promise$2.prototype = {
28666  constructor: Promise$2,
28667
28668  /**
28669    The primary way of interacting with a promise is through its `then` method,
28670    which registers callbacks to receive either a promise's eventual value or the
28671    reason why the promise cannot be fulfilled.
28672  
28673    ```js
28674    findUser().then(function(user){
28675      // user is available
28676    }, function(reason){
28677      // user is unavailable, and you are given the reason why
28678    });
28679    ```
28680  
28681    Chaining
28682    --------
28683  
28684    The return value of `then` is itself a promise.  This second, 'downstream'
28685    promise is resolved with the return value of the first promise's fulfillment
28686    or rejection handler, or rejected if the handler throws an exception.
28687  
28688    ```js
28689    findUser().then(function (user) {
28690      return user.name;
28691    }, function (reason) {
28692      return 'default name';
28693    }).then(function (userName) {
28694      // If `findUser` fulfilled, `userName` will be the user's name, otherwise it
28695      // will be `'default name'`
28696    });
28697  
28698    findUser().then(function (user) {
28699      throw new Error('Found user, but still unhappy');
28700    }, function (reason) {
28701      throw new Error('`findUser` rejected and we're unhappy');
28702    }).then(function (value) {
28703      // never reached
28704    }, function (reason) {
28705      // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'.
28706      // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'.
28707    });
28708    ```
28709    If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream.
28710  
28711    ```js
28712    findUser().then(function (user) {
28713      throw new PedagogicalException('Upstream error');
28714    }).then(function (value) {
28715      // never reached
28716    }).then(function (value) {
28717      // never reached
28718    }, function (reason) {
28719      // The `PedgagocialException` is propagated all the way down to here
28720    });
28721    ```
28722  
28723    Assimilation
28724    ------------
28725  
28726    Sometimes the value you want to propagate to a downstream promise can only be
28727    retrieved asynchronously. This can be achieved by returning a promise in the
28728    fulfillment or rejection handler. The downstream promise will then be pending
28729    until the returned promise is settled. This is called *assimilation*.
28730  
28731    ```js
28732    findUser().then(function (user) {
28733      return findCommentsByAuthor(user);
28734    }).then(function (comments) {
28735      // The user's comments are now available
28736    });
28737    ```
28738  
28739    If the assimliated promise rejects, then the downstream promise will also reject.
28740  
28741    ```js
28742    findUser().then(function (user) {
28743      return findCommentsByAuthor(user);
28744    }).then(function (comments) {
28745      // If `findCommentsByAuthor` fulfills, we'll have the value here
28746    }, function (reason) {
28747      // If `findCommentsByAuthor` rejects, we'll have the reason here
28748    });
28749    ```
28750  
28751    Simple Example
28752    --------------
28753  
28754    Synchronous Example
28755  
28756    ```javascript
28757    let result;
28758  
28759    try {
28760      result = findResult();
28761      // success
28762    } catch(reason) {
28763      // failure
28764    }
28765    ```
28766  
28767    Errback Example
28768  
28769    ```js
28770    findResult(function(result, err){
28771      if (err) {
28772        // failure
28773      } else {
28774        // success
28775      }
28776    });
28777    ```
28778  
28779    Promise Example;
28780  
28781    ```javascript
28782    findResult().then(function(result){
28783      // success
28784    }, function(reason){
28785      // failure
28786    });
28787    ```
28788  
28789    Advanced Example
28790    --------------
28791  
28792    Synchronous Example
28793  
28794    ```javascript
28795    let author, books;
28796  
28797    try {
28798      author = findAuthor();
28799      books  = findBooksByAuthor(author);
28800      // success
28801    } catch(reason) {
28802      // failure
28803    }
28804    ```
28805  
28806    Errback Example
28807  
28808    ```js
28809  
28810    function foundBooks(books) {
28811  
28812    }
28813  
28814    function failure(reason) {
28815  
28816    }
28817  
28818    findAuthor(function(author, err){
28819      if (err) {
28820        failure(err);
28821        // failure
28822      } else {
28823        try {
28824          findBoooksByAuthor(author, function(books, err) {
28825            if (err) {
28826              failure(err);
28827            } else {
28828              try {
28829                foundBooks(books);
28830              } catch(reason) {
28831                failure(reason);
28832              }
28833            }
28834          });
28835        } catch(error) {
28836          failure(err);
28837        }
28838        // success
28839      }
28840    });
28841    ```
28842  
28843    Promise Example;
28844  
28845    ```javascript
28846    findAuthor().
28847      then(findBooksByAuthor).
28848      then(function(books){
28849        // found books
28850    }).catch(function(reason){
28851      // something went wrong
28852    });
28853    ```
28854  
28855    @method then
28856    @param {Function} onFulfilled
28857    @param {Function} onRejected
28858    Useful for tooling.
28859    @return {Promise}
28860  */
28861  then: then,
28862
28863  /**
28864    `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same
28865    as the catch block of a try/catch statement.
28866  
28867    ```js
28868    function findAuthor(){
28869      throw new Error('couldn't find that author');
28870    }
28871  
28872    // synchronous
28873    try {
28874      findAuthor();
28875    } catch(reason) {
28876      // something went wrong
28877    }
28878  
28879    // async with promises
28880    findAuthor().catch(function(reason){
28881      // something went wrong
28882    });
28883    ```
28884  
28885    @method catch
28886    @param {Function} onRejection
28887    Useful for tooling.
28888    @return {Promise}
28889  */
28890  'catch': function _catch(onRejection) {
28891    return this.then(null, onRejection);
28892  }
28893};
28894
28895/*global self*/
28896function polyfill$1() {
28897    var local = undefined;
28898
28899    if (typeof global !== 'undefined') {
28900        local = global;
28901    } else if (typeof self !== 'undefined') {
28902        local = self;
28903    } else {
28904        try {
28905            local = Function('return this')();
28906        } catch (e) {
28907            throw new Error('polyfill failed because global object is unavailable in this environment');
28908        }
28909    }
28910
28911    var P = local.Promise;
28912
28913    if (P) {
28914        var promiseToString = null;
28915        try {
28916            promiseToString = Object.prototype.toString.call(P.resolve());
28917        } catch (e) {
28918            // silently ignored
28919        }
28920
28921        if (promiseToString === '[object Promise]' && !P.cast) {
28922            return;
28923        }
28924    }
28925
28926    local.Promise = Promise$2;
28927}
28928
28929// Strange compat..
28930Promise$2.polyfill = polyfill$1;
28931Promise$2.Promise = Promise$2;
28932
28933return Promise$2;
28934
28935})));
28936
vendor: 2,252 bytes, lines 28937-29012
28937
28938
28939}).call(this,_dereq_('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
28940},{"_process":11}],6:[function(_dereq_,module,exports){
28941(function (global, factory) {
28942  if (typeof define === 'function' && define.amd) {
28943    define(['exports', 'module'], factory);
28944  } else if (typeof exports !== 'undefined' && typeof module !== 'undefined') {
28945    factory(exports, module);
28946  } else {
28947    var mod = {
28948      exports: {}
28949    };
28950    factory(mod.exports, mod);
28951    global.fetchJsonp = mod.exports;
28952  }
28953})(this, function (exports, module) {
28954  'use strict';
28955
28956  var defaultOptions = {
28957    timeout: 5000,
28958    jsonpCallback: 'callback',
28959    jsonpCallbackFunction: null
28960  };
28961
28962  function generateCallbackFunction() {
28963    return 'jsonp_' + Date.now() + '_' + Math.ceil(Math.random() * 100000);
28964  }
28965
28966  function clearFunction(functionName) {
28967    // IE8 throws an exception when you try to delete a property on window
28968    // http://stackoverflow.com/a/1824228/751089
28969    try {
28970      delete window[functionName];
28971    } catch (e) {
28972      window[functionName] = undefined;
28973    }
28974  }
28975
28976  function removeScript(scriptId) {
28977    var script = document.getElementById(scriptId);
28978    if (script) {
28979      document.getElementsByTagName('head')[0].removeChild(script);
28980    }
28981  }
28982
28983  function fetchJsonp(_url) {
28984    var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
28985
28986    // to avoid param reassign
28987    var url = _url;
28988    var timeout = options.timeout || defaultOptions.timeout;
28989    var jsonpCallback = options.jsonpCallback || defaultOptions.jsonpCallback;
28990
28991    var timeoutId = undefined;
28992
28993    return new Promise(function (resolve, reject) {
28994      var callbackFunction = options.jsonpCallbackFunction || generateCallbackFunction();
28995      var scriptId = jsonpCallback + '_' + callbackFunction;
28996
28997      window[callbackFunction] = function (response) {
28998        resolve({
28999          ok: true,
29000          // keep consistent with fetch API
29001          json: function json() {
29002            return Promise.resolve(response);
29003          }
29004        });
29005
29006        if (timeoutId) clearTimeout(timeoutId);
29007
29008        removeScript(scriptId);
29009
29010        clearFunction(callbackFunction);
29011      };
29012
29013      // Check if the user set their own params, and if not add a ? to start a list of params
29014      url += url.indexOf('?') === -1 ? '?' : '&';
29015
29016      var jsonpScript = document.createElement('script');
29017      jsonpScript.setAttribute('src', '' + url + jsonpCallback + '=' + callbackFunction);
29018      if (options.charset) {
29019        jsonpScript.setAttribute('charset', options.charset);
29020      }
29021      jsonpScript.id = scriptId;
29022      document.getElementsByTagName('head')[0].appendChild(jsonpScript);
29023
29024      timeoutId = setTimeout(function () {
29025        reject(new Error('JSONP request to ' + _url + ' timed out'));
29026
29027        clearFunction(callbackFunction);
29028        removeScript(scriptId);
29029        window[callbackFunction] = function () {
29030          clearFunction(callbackFunction);
29031        };
29032      }, timeout);
29033
29034      // Caught if got 404/500
29035      jsonpScript.onerror = function () {
29036        reject(new Error('JSONP request to ' + _url + ' failed'));
29037
29038        clearFunction(callbackFunction);
29039        removeScript(scriptId);
29040        if (timeoutId) clearTimeout(timeoutId);
29041      };
29042    });
29043  }
29044
29045  // export as global function
29046  /*
29047  let local;
29048  if (typeof global !== 'undefined') {
29049    local = global;
29050  } else if (typeof self !== 'undefined') {
29051    local = self;
29052  } else {
29053    try {
29054      local = Function('return this')();
29055    } catch (e) {
29056      throw new Error('polyfill failed because global object is unavailable in this environment');
29057    }
29058  }
29059  local.fetchJsonp = fetchJsonp;
29060  */
29061
29062  module.exports = fetchJsonp;
29063});
29064},{}],7:[function(_dereq_,module,exports){
29065/* FileSaver.js
29066 * A saveAs() FileSaver implementation.
29067 * 1.3.2
29068 * 2016-06-16 18:25:19
29069 *
29070 * By Eli Grey, http://eligrey.com
29071 * License: MIT
29072 *   See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md
29073 */
29074
29075/*global self */
29076/*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */
29077
29078/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */
29079
29080var saveAs = saveAs || (function(view) {
29081	"use strict";
29082	// IE <10 is explicitly unsupported
29083	if (typeof view === "undefined" || typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) {
29084		return;
29085	}
29086	var
29087		  doc = view.document
29088		  // only get URL when necessary in case Blob.js hasn't overridden it yet
29089		, get_URL = function() {
29090			return view.URL || view.webkitURL || view;
29091		}
29092		, save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
29093		, can_use_save_link = "download" in save_link
29094		, click = function(node) {
29095			var event = new MouseEvent("click");
29096			node.dispatchEvent(event);
29097		}
29098		, is_safari = /constructor/i.test(view.HTMLElement) || view.safari
29099		, is_chrome_ios =/CriOS\/[\d]+/.test(navigator.userAgent)
29100		, throw_outside = function(ex) {
29101			(view.setImmediate || view.setTimeout)(function() {
29102				throw ex;
29103			}, 0);
29104		}
29105		, force_saveable_type = "application/octet-stream"
29106		// the Blob API is fundamentally broken as there is no "downloadfinished" event to subscribe to
29107		, arbitrary_revoke_timeout = 1000 * 40 // in ms
29108		, revoke = function(file) {
29109			var revoker = function() {
29110				if (typeof file === "string") { // file is an object URL
29111					get_URL().revokeObjectURL(file);
29112				} else { // file is a File
29113					file.remove();
29114				}
29115			};
29116			setTimeout(revoker, arbitrary_revoke_timeout);
29117		}
29118		, dispatch = function(filesaver, event_types, event) {
29119			event_types = [].concat(event_types);
29120			var i = event_types.length;
29121			while (i--) {
29122				var listener = filesaver["on" + event_types[i]];
29123				if (typeof listener === "function") {
29124					try {
29125						listener.call(filesaver, event || filesaver);
29126					} catch (ex) {
29127						throw_outside(ex);
29128					}
29129				}
29130			}
29131		}
29132		, auto_bom = function(blob) {
29133			// prepend BOM for UTF-8 XML and text/* types (including HTML)
29134			// note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF
29135			if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {
29136				return new Blob([String.fromCharCode(0xFEFF), blob], {type: blob.type});
29137			}
29138			return blob;
29139		}
29140		, FileSaver = function(blob, name, no_auto_bom) {
29141			if (!no_auto_bom) {
29142				blob = auto_bom(blob);
29143			}
29144			// First try a.download, then web filesystem, then object URLs
29145			var
29146				  filesaver = this
29147				, type = blob.type
29148				, force = type === force_saveable_type
29149				, object_url
29150				, dispatch_all = function() {
29151					dispatch(filesaver, "writestart progress write writeend".split(" "));
29152				}
29153				// on any filesys errors revert to saving with object URLs
29154				, fs_error = function() {
29155					if ((is_chrome_ios || (force && is_safari)) && view.FileReader) {
29156						// Safari doesn't allow downloading of blob urls
29157						var reader = new FileReader();
29158						reader.onloadend = function() {
29159							var url = is_chrome_ios ? reader.result : reader.result.replace(/^data:[^;]*;/, 'data:attachment/file;');
29160							var popup = view.open(url, '_blank');
29161							if(!popup) view.location.href = url;
29162							url=undefined; // release reference before dispatching
29163							filesaver.readyState = filesaver.DONE;
29164							dispatch_all();
29165						};
29166						reader.readAsDataURL(blob);
29167						filesaver.readyState = filesaver.INIT;
29168						return;
29169					}
29170					// don't create more object URLs than needed
29171					if (!object_url) {
29172						object_url = get_URL().createObjectURL(blob);
29173					}
29174					if (force) {
29175						view.location.href = object_url;
29176					} else {
29177						var opened = view.open(object_url, "_blank");
29178						if (!opened) {
29179							// Apple does not allow window.open, see https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/WorkingwithWindowsandTabs/WorkingwithWindowsandTabs.html
29180							view.location.href = object_url;
29181						}
29182					}
29183					filesaver.readyState = filesaver.DONE;
29184					dispatch_all();
29185					revoke(object_url);
29186				}
29187			;
29188			filesaver.readyState = filesaver.INIT;
29189
29190			if (can_use_save_link) {
29191				object_url = get_URL().createObjectURL(blob);
29192				setTimeout(function() {
29193					save_link.href = object_url;
29194					save_link.download = name;
29195					click(save_link);
29196					dispatch_all();
29197					revoke(object_url);
29198					filesaver.readyState = filesaver.DONE;
29199				});
29200				return;
29201			}
29202
29203			fs_error();
29204		}
29205		, FS_proto = FileSaver.prototype
29206		, saveAs = function(blob, name, no_auto_bom) {
29207			return new FileSaver(blob, name || blob.name || "download", no_auto_bom);
29208		}
29209	;
29210	// IE 10+ (native saveAs)
29211	if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) {
29212		return function(blob, name, no_auto_bom) {
29213			name = name || blob.name || "download";
29214
29215			if (!no_auto_bom) {
29216				blob = auto_bom(blob);
29217			}
29218			return navigator.msSaveOrOpenBlob(blob, name);
29219		};
29220	}
29221
29222	FS_proto.abort = function(){};
29223	FS_proto.readyState = FS_proto.INIT = 0;
29224	FS_proto.WRITING = 1;
29225	FS_proto.DONE = 2;
29226
29227	FS_proto.error =
29228	FS_proto.onwritestart =
29229	FS_proto.onprogress =
29230	FS_proto.onwrite =
29231	FS_proto.onabort =
29232	FS_proto.onerror =
29233	FS_proto.onwriteend =
29234		null;
29235
29236	return saveAs;
29237}(
29238	   typeof self !== "undefined" && self
29239	|| typeof window !== "undefined" && window
29240	|| this.content
29241));
29242// `self` is undefined in Firefox for Android content script context
29243// while `this` is nsIContentFrameMessageManager
29244// with an attribute `content` that corresponds to the window
29245
29246if (typeof module !== "undefined" && module.exports) {
29247  module.exports.saveAs = saveAs;
29248} else if ((typeof define !== "undefined" && define !== null) && (define.amd !== null)) {
29249  define("FileSaver.js", function() {
29250    return saveAs;
29251  });
29252}
29253
29254},{}],8:[function(_dereq_,module,exports){
29255exports.read = function (buffer, offset, isLE, mLen, nBytes) {
29256  var e, m
29257  var eLen = nBytes * 8 - mLen - 1
29258  var eMax = (1 << eLen) - 1
29259  var eBias = eMax >> 1
29260  var nBits = -7
29261  var i = isLE ? (nBytes - 1) : 0
29262  var d = isLE ? -1 : 1
29263  var s = buffer[offset + i]
29264
29265  i += d
29266
29267  e = s & ((1 << (-nBits)) - 1)
29268  s >>= (-nBits)
29269  nBits += eLen
29270  for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {}
29271
29272  m = e & ((1 << (-nBits)) - 1)
29273  e >>= (-nBits)
29274  nBits += mLen
29275  for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {}
29276
29277  if (e === 0) {
29278    e = 1 - eBias
29279  } else if (e === eMax) {
29280    return m ? NaN : ((s ? -1 : 1) * Infinity)
29281  } else {
29282    m = m + Math.pow(2, mLen)
29283    e = e - eBias
29284  }
29285  return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
29286}
29287
29288exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
29289  var e, m, c
29290  var eLen = nBytes * 8 - mLen - 1
29291  var eMax = (1 << eLen) - 1
29292  var eBias = eMax >> 1
29293  var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
29294  var i = isLE ? 0 : (nBytes - 1)
29295  var d = isLE ? 1 : -1
29296  var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0
29297
29298  value = Math.abs(value)
29299
29300  if (isNaN(value) || value === Infinity) {
29301    m = isNaN(value) ? 1 : 0
29302    e = eMax
29303  } else {
29304    e = Math.floor(Math.log(value) / Math.LN2)
29305    if (value * (c = Math.pow(2, -e)) < 1) {
29306      e--
29307      c *= 2
29308    }
29309    if (e + eBias >= 1) {
29310      value += rt / c
29311    } else {
29312      value += rt * Math.pow(2, 1 - eBias)
29313    }
29314    if (value * c >= 2) {
29315      e++
29316      c /= 2
29317    }
29318
29319    if (e + eBias >= eMax) {
29320      m = 0
29321      e = eMax
29322    } else if (e + eBias >= 1) {
29323      m = (value * c - 1) * Math.pow(2, mLen)
29324      e = e + eBias
29325    } else {
29326      m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)
29327      e = 0
29328    }
29329  }
29330
29331  for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
29332
29333  e = (e << mLen) | m
29334  eLen += mLen
29335  for (; eLen > 0;
29335 buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
29336
29337  buffer[offset + i - d] |= s * 128
29338}
29339
29340},{}],9:[function(_dereq_,module,exports){
29341var toString = {}.toString;
29342
29343module.exports = Array.isArray || function (arr) {
29344  return toString.call(arr) == '[object Array]';
29345};
29346
29347},{}],10:[function(_dereq_,module,exports){
29348(function (Buffer){
29349/**
29350 * https://opentype.js.org v0.7.3 | (c) Frederik De Bleser and other contributors | MIT License | Uses tiny-inflate by Devon Govett
29351 */
29352
29353(function (global, factory) {
29354	typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
29355	typeof define === 'function' && define.amd ? define(['exports'], factory) :
29356	(factory((global.opentype = global.opentype || {})));
29357}(this, (function (exports) { 'use strict';
29358
29359var TINF_OK = 0;
29360var TINF_DATA_ERROR = -3;
29361
29362function Tree() {
29363  this.table = new Uint16Array(16);   /* table of code length counts */
29364  this.trans = new Uint16Array(288);  /* code -> symbol translation table */
29365}
29366
29367function Data(source, dest) {
29368  this.source = source;
29369  this.sourceIndex = 0;
29370  this.tag = 0;
29371  this.bitcount = 0;
29372  
29373  this.dest = dest;
29374  this.destLen = 0;
29375  
29376  this.ltree = new Tree();  /* dynamic length/symbol tree */
29377  this.dtree = new Tree();  /* dynamic distance tree */
29378}
29379
29380/* --------------------------------------------------- *
vendor: 7,409 bytes, lines 29381-29681
29381 * -- uninitialized global data (static structures) -- *
29382 * --------------------------------------------------- */
29383
29384var sltree = new Tree();
29385var sdtree = new Tree();
29386
29387/* extra bits and base tables for length codes */
29388var length_bits = new Uint8Array(30);
29389var length_base = new Uint16Array(30);
29390
29391/* extra bits and base tables for distance codes */
29392var dist_bits = new Uint8Array(30);
29393var dist_base = new Uint16Array(30);
29394
29395/* special ordering of code length codes */
29396var clcidx = new Uint8Array([
29397  16, 17, 18, 0, 8, 7, 9, 6,
29398  10, 5, 11, 4, 12, 3, 13, 2,
29399  14, 1, 15
29400]);
29401
29402/* used by tinf_decode_trees, avoids allocations every call */
29403var code_tree = new Tree();
29404var lengths = new Uint8Array(288 + 32);
29405
29406/* ----------------------- *
29407 * -- utility functions -- *
29408 * ----------------------- */
29409
29410/* build extra bits and base tables */
29411function tinf_build_bits_base(bits, base, delta, first) {
29412  var i, sum;
29413
29414  /* build bits table */
29415  for (i = 0; i < delta; ++i) { bits[i] = 0; }
29416  for (i = 0; i < 30 - delta; ++i) { bits[i + delta] = i / delta | 0; }
29417
29418  /* build base table */
29419  for (sum = first, i = 0; i < 30; ++i) {
29420    base[i] = sum;
29421    sum += 1 << bits[i];
29422  }
29423}
29424
29425/* build the fixed huffman trees */
29426function tinf_build_fixed_trees(lt, dt) {
29427  var i;
29428
29429  /* build fixed length tree */
29430  for (i = 0; i < 7; ++i) { lt.table[i] = 0; }
29431
29432  lt.table[7] = 24;
29433  lt.table[8] = 152;
29434  lt.table[9] = 112;
29435
29436  for (i = 0; i < 24; ++i) { lt.trans[i] = 256 + i; }
29437  for (i = 0; i < 144; ++i) { lt.trans[24 + i] = i; }
29438  for (i = 0; i < 8; ++i) { lt.trans[24 + 144 + i] = 280 + i; }
29439  for (i = 0; i < 112; ++i) { lt.trans[24 + 144 + 8 + i] = 144 + i; }
29440
29441  /* build fixed distance tree */
29442  for (i = 0; i < 5; ++i) { dt.table[i] = 0; }
29443
29444  dt.table[5] = 32;
29445
29446  for (i = 0; i < 32; ++i) { dt.trans[i] = i; }
29447}
29448
29449/* given an array of code lengths, build a tree */
29450var offs = new Uint16Array(16);
29451
29452function tinf_build_tree(t, lengths, off, num) {
29453  var i, sum;
29454
29455  /* clear code length count table */
29456  for (i = 0; i < 16; ++i) { t.table[i] = 0; }
29457
29458  /* scan symbol lengths, and sum code length counts */
29459  for (i = 0; i < num; ++i) { t.table[lengths[off + i]]++; }
29460
29461  t.table[0] = 0;
29462
29463  /* compute offset table for distribution sort */
29464  for (sum = 0, i = 0; i < 16; ++i) {
29465    offs[i] = sum;
29466    sum += t.table[i];
29467  }
29468
29469  /* create code->symbol translation table (symbols sorted by code) */
29470  for (i = 0; i < num; ++i) {
29471    if (lengths[off + i]) { t.trans[offs[lengths[off + i]]++] = i; }
29472  }
29473}
29474
29475/* ---------------------- *
29476 * -- decode functions -- *
29477 * ---------------------- */
29478
29479/* get one bit from source stream */
29480function tinf_getbit(d) {
29481  /* check if tag is empty */
29482  if (!d.bitcount--) {
29483    /* load next tag */
29484    d.tag = d.source[d.sourceIndex++];
29485    d.bitcount = 7;
29486  }
29487
29488  /* shift bit out of tag */
29489  var bit = d.tag & 1;
29490  d.tag >>>= 1;
29491
29492  return bit;
29493}
29494
29495/* read a num bit value from a stream and add base */
29496function tinf_read_bits(d, num, base) {
29497  if (!num)
29498    { return base; }
29499
29500  while (d.bitcount < 24) {
29501    d.tag |= d.source[d.sourceIndex++] << d.bitcount;
29502    d.bitcount += 8;
29503  }
29504
29505  var val = d.tag & (0xffff >>> (16 - num));
29506  d.tag >>>= num;
29507  d.bitcount -= num;
29508  return val + base;
29509}
29510
29511/* given a data stream and a tree, decode a symbol */
29512function tinf_decode_symbol(d, t) {
29513  while (d.bitcount < 24) {
29514    d.tag |= d.source[d.sourceIndex++] << d.bitcount;
29515    d.bitcount += 8;
29516  }
29517  
29518  var sum = 0, cur = 0, len = 0;
29519  var tag = d.tag;
29520
29521  /* get more bits while code value is above sum */
29522  do {
29523    cur = 2 * cur + (tag & 1);
29524    tag >>>= 1;
29525    ++len;
29526
29527    sum += t.table[len];
29528    cur -= t.table[len];
29529  } while (cur >= 0);
29530  
29531  d.tag = tag;
29532  d.bitcount -= len;
29533
29534  return t.trans[sum + cur];
29535}
29536
29537/* given a data stream, decode dynamic trees from it */
29538function tinf_decode_trees(d, lt, dt) {
29539  var hlit, hdist, hclen;
29540  var i, num, length;
29541
29542  /* get 5 bits HLIT (257-286) */
29543  hlit = tinf_read_bits(d, 5, 257);
29544
29545  /* get 5 bits HDIST (1-32) */
29546  hdist = tinf_read_bits(d, 5, 1);
29547
29548  /* get 4 bits HCLEN (4-19) */
29549  hclen = tinf_read_bits(d, 4, 4);
29550
29551  for (i = 0; i < 19; ++i) { lengths[i] = 0; }
29552
29553  /* read code lengths for code length alphabet */
29554  for (i = 0; i < hclen; ++i) {
29555    /* get 3 bits code length (0-7) */
29556    var clen = tinf_read_bits(d, 3, 0);
29557    lengths[clcidx[i]] = clen;
29558  }
29559
29560  /* build code length tree */
29561  tinf_build_tree(code_tree, lengths, 0, 19);
29562
29563  /* decode code lengths for the dynamic trees */
29564  for (num = 0; num < hlit + hdist;) {
29565    var sym = tinf_decode_symbol(d, code_tree);
29566
29567    switch (sym) {
29568      case 16:
29569        /* copy previous code length 3-6 times (read 2 bits) */
29570        var prev = lengths[num - 1];
29571        for (length = tinf_read_bits(d, 2, 3); length; --length) {
29572          lengths[num++] = prev;
29573        }
29574        break;
29575      case 17:
29576        /* repeat code length 0 for 3-10 times (read 3 bits) */
29577        for (length = tinf_read_bits(d, 3, 3); length; --length) {
29578          lengths[num++] = 0;
29579        }
29580        break;
29581      case 18:
29582        /* repeat code length 0 for 11-138 times (read 7 bits) */
29583        for (length = tinf_read_bits(d, 7, 11); length; --length) {
29584          lengths[num++] = 0;
29585        }
29586        break;
29587      default:
29588        /* values 0-15 represent the actual code lengths */
29589        lengths[num++] = sym;
29590        break;
29591    }
29592  }
29593
29594  /* build dynamic trees */
29595  tinf_build_tree(lt, lengths, 0, hlit);
29596  tinf_build_tree(dt, lengths, hlit, hdist);
29597}
29598
29599/* ----------------------------- *
29600 * -- block inflate functions -- *
29601 * ----------------------------- */
29602
29603/* given a stream and two trees, inflate a block of data */
29604function tinf_inflate_block_data(d, lt, dt) {
29605  while (1) {
29606    var sym = tinf_decode_symbol(d, lt);
29607
29608    /* check for end of block */
29609    if (sym === 256) {
29610      return TINF_OK;
29611    }
29612
29613    if (sym < 256) {
29614      d.dest[d.destLen++] = sym;
29615    } else {
29616      var length, dist, offs;
29617      var i;
29618
29619      sym -= 257;
29620
29621      /* possibly get more bits from length code */
29622      length = tinf_read_bits(d, length_bits[sym], length_base[sym]);
29623
29624      dist = tinf_decode_symbol(d, dt);
29625
29626      /* possibly get more bits from distance code */
29627      offs = d.destLen - tinf_read_bits(d, dist_bits[dist], dist_base[dist]);
29628
29629      /* copy match */
29630      for (i = offs; i < offs + length; ++i) {
29631        d.dest[d.destLen++] = d.dest[i];
29632      }
29633    }
29634  }
29635}
29636
29637/* inflate an uncompressed block of data */
29638function tinf_inflate_uncompressed_block(d) {
29639  var length, invlength;
29640  var i;
29641  
29642  /* unread from bitbuffer */
29643  while (d.bitcount > 8) {
29644    d.sourceIndex--;
29645    d.bitcount -= 8;
29646  }
29647
29648  /* get length */
29649  length = d.source[d.sourceIndex + 1];
29650  length = 256 * length + d.source[d.sourceIndex];
29651
29652  /* get one's complement of length */
29653  invlength = d.source[d.sourceIndex + 3];
29654  invlength = 256 * invlength + d.source[d.sourceIndex + 2];
29655
29656  /* check length */
29657  if (length !== (~invlength & 0x0000ffff))
29658    { return TINF_DATA_ERROR; }
29659
29660  d.sourceIndex += 4;
29661
29662  /* copy block */
29663  for (i = length; i; --i)
29664    { d.dest[d.destLen++] = d.source[d.sourceIndex++]; }
29665
29666  /* make sure we start next block on a byte boundary */
29667  d.bitcount = 0;
29668
29669  return TINF_OK;
29670}
29671
29672/* inflate stream from source to dest */
29673function tinf_uncompress(source, dest) {
29674  var d = new Data(source, dest);
29675  var bfinal, btype, res;
29676
29677  do {
29678    /* read final block flag */
29679    bfinal = tinf_getbit(d);
29680
29681    /* read block type (2 bits) */
29682    btype = tinf_read_bits(d, 2, 0);
29683
29684    /* decompress block */
29685    switch (btype) {
29686      case 0:
29687        /* decompress uncompressed block */
29688        res = tinf_inflate_uncompressed_block(d);
29689        break;
29690      case 1:
29691        /* decompress block with fixed huffman trees */
29692        res = tinf_inflate_block_data(d, sltree, sdtree);
29693        break;
29694      case 2:
29695        /* decompress block with dynamic huffman trees */
29696        tinf_decode_trees(d, d.ltree, d.dtree);
29697        res = tinf_inflate_block_data(d, d.ltree, d.dtree);
29698        break;
29699      default:
29700        res = TINF_DATA_ERROR;
29701    }
29702
29703    if (res !== TINF_OK)
29704      { throw new Error('Data error'); }
29705
29706  } while (!bfinal);
29707
29708  if (d.destLen < d.dest.length) {
29709    if (typeof d.dest.slice === 'function')
29710      { return d.dest.slice(0, d.destLen); }
29711    else
29712      { return d.dest.subarray(0, d.destLen); }
29713  }
29714  
29715  return d.dest;
29716}
29717
29718/* -------------------- *
29719 * -- initialization -- *
29720 * -------------------- */
29721
29722/* build fixed huffman trees */
29723tinf_build_fixed_trees(sltree, sdtree);
29724
29725/* build extra bits and base tables */
29726tinf_build_bits_base(length_bits, length_base, 4, 3);
29727tinf_build_bits_base(dist_bits, dist_base, 2, 1);
29728
29729/* fix a special case */
29730length_bits[28] = 0;
29731length_base[28] = 258;
29732
29733var index = tinf_uncompress;
29734
29735// The Bounding Box object
29736
29737function derive(v0, v1, v2, v3, t) {
29738    return Math.pow(1 - t, 3) * v0 +
29739        3 * Math.pow(1 - t, 2) * t * v1 +
29740        3 * (1 - t) * Math.pow(t, 2) * v2 +
29741        Math.pow(t, 3) * v3;
29742}
29743/**
29744 * A bounding box is an enclosing box that describes the smallest measure within which all the points lie.
29745 * It is used to calculate the bounding box of a glyph or text path.
29746 *
29747 * On initialization, x1/y1/x2/y2 will be NaN. Check if the bounding box is empty using `isEmpty()`.
29748 *
29749 * @exports opentype.BoundingBox
29750 * @class
29751 * @constructor
29752 */
29753function BoundingBox() {
29754    this.x1 = Number.NaN;
29755    this.y1 = Number.NaN;
29756    this.x2 = Number.NaN;
29757    this.y2 = Number.NaN;
29758}
29759
29760/**
29761 * Returns true if the bounding box is empty, that is, no points have been added to the box yet.
29762 */
29763BoundingBox.prototype.isEmpty = function() {
29764    return isNaN(this.x1) || isNaN(this.y1) || isNaN(this.x2) || isNaN(this.y2);
29765};
29766
29767/**
29768 * Add the point to the bounding box.
29769 * The x1/y1/x2/y2 coordinates of the bounding box will now encompass the given point.
29770 * @param {number} x - The X coordinate of the point.
29771 * @param {number} y - The Y coordinate of the point.
29772 */
29773BoundingBox.prototype.addPoint = function(x, y) {
29774    if (typeof x === 'number') {
29775        if (isNaN(this.x1) || isNaN(this.x2)) {
29776            this.x1 = x;
29777            this.x2 = x;
29778        }
29779        if (x < this.x1) {
29780            this.x1 = x;
29781        }
29782        if (x > this.x2) {
29783            this.x2 = x;
29784        }
29785    }
29786    if (typeof y === 'number') {
29787        if (isNaN(this.y1) || isNaN(this.y2)) {
29788            this.y1 = y;
29789            this.y2 = y;
29790        }
29791        if (y < this.y1) {
29792            this.y1 = y;
29793        }
29794        if (y > this.y2) {
29795            this.y2 = y;
29796        }
29797    }
29798};
29799
29800/**
29801 * Add a X coordinate to the bounding box.
29802 * This extends the bounding box to include the X coordinate.
29803 * This function is used internally inside of addBezier.
29804 * @param {number} x - The X coordinate of the point.
29805 */
29806BoundingBox.prototype.addX = function(x) {
29807    this.addPoint(x, null);
29808};
29809
29810/**
29811 * Add a Y coordinate to the bounding box.
29812 * This extends the bounding box to include the Y coordinate.
29813 * This function is used internally inside of addBezier.
29814 * @param {number} y - The Y coordinate of the point.
29815 */
29816BoundingBox.prototype.addY = function(y) {
29817    this.addPoint(null, y);
29818};
29819
29820/**
29821 * Add a Bézier curve to the bounding box.
29822 * This extends the bounding box to include the entire Bézier.
29823 * @param {number} x0 - The starting X coordinate.
29824 * @param {number} y0 - The starting Y coordinate.
29825 * @param {number} x1 - The X coordinate of the first control point.
29826 * @param {number} y1 - The Y coordinate of the first control point.
29827 * @param {number} x2 - The X coordinate of the second control point.
29828 * @param {number} y2 - The Y coordinate of the second control point.
29829 * @param {number} x - The ending X coordinate.
29830 * @param {number} y - The ending Y coordinate.
29831 */
29832BoundingBox.prototype.addBezier = function(x0, y0, x1, y1, x2, y2, x, y) {
29833    var this$1 = this;
29834
29835    // This code is based on http://nishiohirokazu.blogspot.com/2009/06/how-to-calculate-bezier-curves-bounding.html
29836    // and https://github.com/icons8/svg-path-bounding-box
29837
29838    var p0 = [x0, y0];
29839    var p1 = [x1, y1];
29840    var p2 = [x2, y2];
29841    var p3 = [x, y];
29842
29843    this.addPoint(x0, y0);
29844    this.addPoint(x, y);
29845
29846    for (var i = 0; i <= 1; i++) {
29847        var b = 6 * p0[i] - 12 * p1[i] + 6 * p2[i];
29848        var a = -3 * p0[i] + 9 * p1[i] - 9 * p2[i] + 3 * p3[i];
29849        var c = 3 * p1[i] - 3 * p0[i];
29850
29851        if (a === 0) {
29852            if (b === 0) { continue; }
29853            var t = -c / b;
29854            if (0 < t && t < 1) {
29855                if (i === 0) { this$1.addX(derive(p0[i], p1[i], p2[i], p3[
29855i], t)); }
29856                if (i === 1) { this$1.addY(derive(p0[i], p1[i], p2[i], p3[i], t)); }
29857            }
29858            continue;
29859        }
29860
29861        var b2ac = Math.pow(b, 2) - 4 * c * a;
29862        if (b2ac < 0) { continue; }
29863        var t1 = (-b + Math.sqrt(b2ac)) / (2 * a);
29864        if (0 < t1 && t1 < 1) {
29865            if (i === 0) { this$1.addX(derive(p0[i], p1[i], p2[i], p3[i], t1)); }
29866            if (i === 1) { this$1.addY(derive(p0[i], p1[i], p2[i], p3[i], t1)); }
29867        }
29868        var t2 = (-b - Math.sqrt(b2ac)) / (2 * a);
29869        if (0 < t2 && t2 < 1) {
29870            if (i === 0) { this$1.addX(derive(p0[i], p1[i], p2[i], p3[i], t2)); }
29871            if (i === 1) { this$1.addY(derive(p0[i], p1[i], p2[i], p3[i], t2)); }
29872        }
29873    }
29874};
29875
29876/**
29877 * Add a quadratic curve to the bounding box.
29878 * This extends the bounding box to include the entire quadratic curve.
29879 * @param {number} x0 - The starting X coordinate.
29880 * @param {number} y0 - The starting Y coordinate.
29881 * @param {number} x1 - The X coordinate of the control point.
29882 * @param {number} y1 - The Y coordinate of the control point.
29883 * @param {number} x - The ending X coordinate.
29884 * @param {number} y - The ending Y coordinate.
29885 */
29886BoundingBox.prototype.addQuad = function(x0, y0, x1, y1, x, y) {
29887    var cp1x = x0 + 2 / 3 * (x1 - x0);
29888    var cp1y = y0 + 2 / 3 * (y1 - y0);
29889    var cp2x = cp1x + 1 / 3 * (x - x0);
29890    var cp2y = cp1y + 1 / 3 * (y - y0);
29891    this.addBezier(x0, y0, cp1x, cp1y, cp2x, cp2y, x, y);
29892};
29893
29894// Geometric objects
29895
29896/**
29897 * A bézier path containing a set of path commands similar to a SVG path.
29898 * Paths can be drawn on a context using `draw`.
29899 * @exports opentype.Path
29900 * @class
29901 * @constructor
29902 */
29903function Path() {
29904    this.commands = [];
29905    this.fill = 'black';
29906    this.stroke = null;
29907    this.strokeWidth = 1;
29908}
29909
29910/**
29911 * @param  {number} x
29912 * @param  {number} y
29913 */
29914Path.prototype.moveTo = function(x, y) {
29915    this.commands.push({
29916        type: 'M',
29917        x: x,
29918        y: y
29919    });
29920};
29921
29922/**
29923 * @param  {number} x
29924 * @param  {number} y
29925 */
29926Path.prototype.lineTo = function(x, y) {
29927    this.commands.push({
29928        type: 'L',
29929        x: x,
29930        y: y
29931    });
29932};
29933
29934/**
29935 * Draws cubic curve
29936 * @function
29937 * curveTo
29938 * @memberof opentype.Path.prototype
29939 * @param  {number} x1 - x of control 1
29940 * @param  {number} y1 - y of control 1
29941 * @param  {number} x2 - x of control 2
29942 * @param  {number} y2 - y of control 2
29943 * @param  {number} x - x of path point
29944 * @param  {number} y - y of path point
29945 */
29946
29947/**
29948 * Draws cubic curve
29949 * @function
29950 * bezierCurveTo
29951 * @memberof opentype.Path.prototype
29952 * @param  {number} x1 - x of control 1
29953 * @param  {number} y1 - y of control 1
29954 * @param  {number} x2 - x of control 2
29955 * @param  {number} y2 - y of control 2
29956 * @param  {number} x - x of path point
29957 * @param  {number} y - y of path point
29958 * @see curveTo
29959 */
29960Path.prototype.curveTo = Path.prototype.bezierCurveTo = function(x1, y1, x2, y2, x, y) {
29961    this.commands.push({
29962        type: 'C',
29963        x1: x1,
29964        y1: y1,
29965        x2: x2,
29966        y2: y2,
29967        x: x,
29968        y: y
29969    });
29970};
29971
29972/**
29973 * Draws quadratic curve
29974 * @function
29975 * quadraticCurveTo
29976 * @memberof opentype.Path.prototype
29977 * @param  {number} x1 - x of control
29978 * @param  {number} y1 - y of control
29979 * @param  {number} x - x of path point
29980 * @param  {number} y - y of path point
29981 */
29982
29983/**
29984 * Draws quadratic curve
29985 * @function
29986 * quadTo
29987 * @memberof opentype.Path.prototype
29988 * @param  {number} x1 - x of control
29989 * @param  {number} y1 - y of control
29990 * @param  {number} x - x of path point
29991 * @param  {number} y - y of path point
29992 */
29993Path.prototype.quadTo = Path.prototype.quadraticCurveTo = function(x1, y1, x, y) {
29994    this.commands.push({
29995        type: 'Q',
29996        x1: x1,
29997        y1: y1,
29998        x: x,
29999        y: y
30000    });
30001};
30002
30003/**
30004 * Closes the path
30005 * @function closePath
30006 * @memberof opentype.Path.prototype
30007 */
30008
30009/**
30010 * Close the path
30011 * @function close
30012 * @memberof opentype.Path.prototype
30013 */
30014Path.prototype.close = Path.prototype.closePath = function() {
30015    this.commands.push({
30016        type: 'Z'
30017    });
30018};
30019
30020/**
30021 * Add the given path or list of commands to the commands of this path.
30022 * @param  {Array} pathOrCommands - another opentype.Path, an opentype.BoundingBox, or an array of commands.
30023 */
30024Path.prototype.extend = function(pathOrCommands) {
30025    if (pathOrCommands.commands) {
30026        pathOrCommands = pathOrCommands.commands;
30027    } else if (pathOrCommands instanceof BoundingBox) {
30028        var box = pathOrCommands;
30029        this.moveTo(box.x1, box.y1);
30030        this.lineTo(box.x2, box.y1);
30031        this.lineTo(box.x2, box.y2);
30032        this.lineTo(box.x1, box.y2);
30033        this.close();
30034        return;
30035    }
30036
30037    Array.prototype.push.apply(this.commands, pathOrCommands);
30038};
30039
30040/**
30041 * Calculate the bounding box of the path.
30042 * @returns {opentype.BoundingBox}
30043 */
30044Path.prototype.getBoundingBox = function() {
30045    var this$1 = this;
30046
30047    var box = new BoundingBox();
30048
30049    var startX = 0;
30050    var startY = 0;
30051    var prevX = 0;
30052    var prevY = 0;
30053    for (var i = 0; i < this.commands.length; i++) {
30054        var cmd = this$1.commands[i];
30055        switch (cmd.type) {
30056            case 'M':
30057                box.addPoint(cmd.x, cmd.y);
30058                startX = prevX = cmd.x;
30059                startY = prevY = cmd.y;
30060                break;
30061            case 'L':
30062                box.addPoint(cmd.x, cmd.y);
30063                prevX = cmd.x;
30064                prevY = cmd.y;
30065                break;
30066            case 'Q':
30067                box.addQuad(prevX, prevY, cmd.x1, cmd.y1, cmd.x, cmd.y);
30068                prevX = cmd.x;
30069                prevY = cmd.y;
30070                break;
30071            case 'C':
30072                box.addBezier(prevX, prevY, cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y);
30073                prevX = cmd.x;
30074                prevY = cmd.y;
30075                break;
30076            case 'Z':
30077                prevX = startX;
30078                prevY = startY;
30079                break;
30080            default:
30081                throw new Error('Unexpected path command ' + cmd.type);
30082        }
30083    }
30084    if (box.isEmpty()) {
30085        box.addPoint(0, 0);
30086    }
30087    return box;
30088};
30089
30090/**
30091 * Draw the path to a 2D context.
30092 * @param {CanvasRenderingContext2D} ctx - A 2D drawing context.
30093 */
30094Path.prototype.draw = function(ctx) {
30095    var this$1 = this;
30096
30097    ctx.beginPath();
30098    for (var i = 0; i < this.commands.length; i += 1) {
30099        var cmd = this$1.commands[i];
30100        if (cmd.type === 'M') {
30101            ctx.moveTo(cmd.x, cmd.y);
30102        } else if (cmd.type === 'L') {
30103            ctx.lineTo(cmd.x, cmd.y);
30104        } else if (cmd.type === 'C') {
30105            ctx.bezierCurveTo(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y);
30106        } else if (cmd.type === 'Q') {
30107            ctx.quadraticCurveTo(cmd.x1, cmd.y1, cmd.x, cmd.y);
30108        } else if (cmd.type === 'Z') {
30109            ctx.closePath();
30110        }
30111    }
30112
30113    if (this.fill) {
30114        ctx.fillStyle = this.fill;
30115        ctx.fill();
30116    }
30117
30118    if (this.stroke) {
30119        ctx.strokeStyle = this.stroke;
30120        ctx.lineWidth = this.strokeWidth;
30121        ctx.stroke();
30122    }
30123};
30124
30125/**
30126 * Convert the Path to a string of path data instructions
30127 * See http://www.w3.org/TR/SVG/paths.html#PathData
30128 * @param  {number} [decimalPlaces=2] - The amount of decimal places for floating-point values
30129 * @return {string}
30130 */
30131Path.prototype.toPathData = function(decimalPlaces) {
30132    var this$1 = this;
30133
30134    decimalPlaces = decimalPlaces !== undefined ? decimalPlaces : 2;
30135
30136    function floatToString(v) {
30137        if (Math.round(v) === v) {
30138            return '' + Math.round(v);
30139        } else {
30140            return v.toFixed(decimalPlaces);
30141        }
30142    }
30143
30144    function packValues() {
30145        var arguments$1 = arguments;
30146
30147        var s = '';
30148        for (var i = 0; i < arguments.length; i += 1) {
30149            var v = arguments$1[i];
30150            if (v >= 0 && i > 0) {
30151                s += ' ';
30152            }
30153
30154            s += floatToString(v);
30155        }
30156
30157        return s;
30158    }
30159
30160    var d = '';
30161    for (var i = 0; i < this.commands.length; i += 1) {
30162        var cmd = this$1.commands[i];
30163        if (cmd.type === 'M') {
30164            d += 'M' + packValues(cmd.x, cmd.y);
30165        } else if (cmd.type === 'L') {
30166            d += 'L' + packValues(cmd.x, cmd.y);
30167        } else if (cmd.type === 'C') {
30168            d += 'C' + packValues(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y);
30169        } else if (cmd.type === 'Q') {
30170            d += 'Q' + packValues(cmd.x1, cmd.y1, cmd.x, cmd.y);
30171        } else if (cmd.type === 'Z') {
30172            d += 'Z';
30173        }
30174    }
30175
30176    return d;
30177};
30178
30179/**
30180 * Convert the path to an SVG <path> element, as a string.
30181 * @param  {number} [decimalPlaces=2] - The amount of decimal places for floating-point values
30182 * @return {string}
30183 */
30184Path.prototype.toSVG = function(decimalPlaces) {
30185    var svg = '<path d="';
30186    svg += this.toPathData(decimalPlaces);
30187    svg += '"';
30188    if (this.fill && this.fill !== 'black') {
30189        if (this.fill === null) {
30190            svg += ' fill="none"';
30191        } else {
30192            svg += ' fill="' + this.fill + '"';
30193        }
30194    }
30195
30196    if (this.stroke) {
30197        svg += ' stroke="' + this.stroke + '" stroke-width="' + this.strokeWidth + '"';
30198    }
30199
30200    svg += '/>';
30201    return svg;
30202};
30203
30204/**
30205 * Convert the path to a DOM element.
30206 * @param  {number} [decimalPlaces=2] - The amount of decimal places for floating-point values
30207 * @return {SVGPathElement}
30208 */
30209Path.prototype.toDOMElement = function(decimalPlaces) {
30210    var temporaryPath = this.toPathData(decimalPlaces);
30211    var newPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
30212
30213    newPath.setAttribute('d', temporaryPath);
30214
30215    return newPath;
30216};
30217
30218// Run-time checking of preconditions.
30219
30220function fail(message) {
30221    throw new Error(message);
30222}
30223
30224// Precondition function that checks if the given predicate is true.
30225// If not, it will throw an error.
30226function argument(predicate, message) {
30227    if (!predicate) {
30228        fail(message);
30229    }
30230}
30231
30232var check = { fail: fail, argument: argument, assert: argument };
30233
30234// Data types used in the OpenType font file.
30235// All OpenType fonts use Motorola-style byte ordering (Big Endian)
30236
30237var LIMIT16 = 32768; // The limit at which a 16-bit number switches signs == 2^15
30238var LIMIT32 = 2147483648; // The limit at which a 32-bit number switches signs == 2 ^ 31
30239
30240/**
30241 * @exports opentype.decode
30242 * @class
30243 */
30244var decode = {};
30245/**
30246 * @exports opentype.encode
30247 * @class
30248 */
30249var encode = {};
30250/**
30251 * @exports opentype.sizeOf
30252 * @class
30253 */
30254var sizeOf = {};
30255
30256// Return a function that always returns the same value.
30257function constant(v) {
30258    return function() {
30259        return v;
30260    };
30261}
30262
30263// OpenType data types //////////////////////////////////////////////////////
30264
30265/**
30266 * Convert an 8-bit unsigned integer to a list of 1 byte.
30267 * @param {number}
30268 * @returns {Array}
30269 */
30270encode.BYTE = function(v) {
30271    check.argument(v >= 0 && v <= 255, 'Byte value should be between 0 and 255.');
30272    return [v];
30273};
30274/**
30275 * @constant
30276 * @type {number}
30277 */
30278sizeOf.BYTE = constant(1);
30279
30280/**
30281 * Convert a 8-bit signed integer to a list of 1 byte.
30282 * @param {string}
30283 * @returns {Array}
30284 */
30285encode.CHAR = function(v) {
30286    return [v.charCodeAt(0)];
30287};
30288
30289/**
30290 * @constant
30291 * @type {number}
30292 */
30293sizeOf.CHAR = constant(1);
30294
30295/**
30296 * Convert an ASCII string to a list of bytes.
30297 * @param {string}
30298 * @returns {Array}
30299 */
30300encode.CHARARRAY = function(v) {
30301    var b = [];
30302    for (var i = 0; i < v.length; i += 1) {
30303        b[i] = v.charCodeAt(i);
30304    }
30305
30306    return b;
30307};
30308
30309/**
30310 * @param {Array}
30311 * @returns {number}
30312 */
30313sizeOf.CHARARRAY = function(v) {
30314    return v.length;
30315};
30316
30317/**
30318 * Convert a 16-bit unsigned integer to a list of 2 bytes.
30319 * @param {number}
30320 * @returns {Array}
30321 */
30322encode.USHORT = function(v) {
30323    return [(v >> 8) & 0xFF, v & 0xFF];
30324};
30325
30326/**
30327 * @constant
30328 * @type {number}
30329 */
30330sizeOf.USHORT = constant(2);
30331
30332/**
30333 * Convert a 16-bit signed integer to a list of 2 bytes.
30334 * @param {number}
30335 * @returns {Array}
30336 */
30337encode.SHORT = function(v) {
30338    // Two's complement
30339    if (v >= LIMIT16) {
30340        v = -(2 * LIMIT16 - v);
30341    }
30342
30343    return [(v >> 8) & 0xFF, v & 0xFF];
30344};
30345
30346/**
30347 * @constant
30348 * @type {number}
30349 */
30350sizeOf.SHORT = constant(2);
30351
30352/**
30353 * Convert a 24-bit unsigned integer to a list of 3 bytes.
30354 * @param {number}
30355 * @returns {Array}
30356 */
30357encode.UINT24 = function(v) {
30358    return [(v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];
30359};
30360
30361/**
30362 * @constant
30363 * @type {number}
30364 */
30365sizeOf.UINT24 = constant(3);
30366
30367/**
30368 * Convert a 32-bit unsigned integer to a list of 4 bytes.
30369 * @param {number}
30370 * @returns {Array}
30371 */
30372encode.ULONG = function(v) {
30373    return [(v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];
30374};
30375
30376/**
30377 * @constant
30378 * @type {number}
30379 */
30380sizeOf.ULONG = constant(4);
30381
30382/**
30383 * Convert a 32-bit unsigned integer to a list of 4 bytes.
30384 * @param {number}
30385 * @returns {Array}
30386 */
30387encode.LONG = function(v) {
30388    // Two's complement
30389    if (v >= LIMIT32) {
30390        v = -(2 * LIMIT32 - v);
30391    }
30392
30393    return [(v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];
30394};
30395
30396/**
30397 * @constant
30398 * @type {number}
30399 */
30400sizeOf.LONG = constant(4);
30401
30402encode.FIXED = encode.ULONG;
30403sizeOf.FIXED = sizeOf.ULONG;
30404
30405encode.FWORD = encode.SHORT;
30406sizeOf.FWORD = sizeOf.SHORT;
30407
30408encode.UFWORD = encode.USHORT;
30409sizeOf.UFWORD = sizeOf.USHORT;
30410
30411/**
30412 * Convert a 32-bit Apple Mac timestamp integer to a list of 8 bytes, 64-bit timestamp.
30413 * @param {number}
30414 * @returns {Array}
30415 */
30416encode.LONGDATETIME = function(v) {
30417    return [0, 0, 0, 0, (v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];
30418};
30419
30420/**
30421 * @constant
30422 * @type {number}
30423 */
30424sizeOf.LONGDATETIME = constant(8);
30425
30426/**
30427 * Convert a 4-char tag to a list of 4 bytes.
30428 * @param {string}
30429 * @returns {Array}
30430 */
30431encode.TAG = function(v) {
30432    check.argument(v.length === 4, 'Tag should be exactly 4 ASCII characters.');
30433    return [v.charCodeAt(0),
30434            v.charCodeAt(1),
30435            v.charCodeAt(2),
30436            v.charCodeAt(3)];
30437};
30438
30439/**
30440 * @constant
30441 * @type {number}
30442 */
30443sizeOf.TAG = constant(4);
30444
30445// CFF data types ///////////////////////////////////////////////////////////
30446
30447encode.Card8 = encode.BYTE;
30448sizeOf.Card8 = sizeOf.BYTE;
30449
30450encode.Card16 = encode.USHORT;
30451sizeOf.Card16 = sizeOf.USHORT;
30452
30453encode.OffSize = encode.BYTE;
30454sizeOf.OffSize = sizeOf.BYTE;
30455
30456encode.SID = encode.USHORT;
30457sizeOf.SID = sizeOf.USHORT;
30458
30459// Convert a numeric operand or charstring number to a variable-size list of bytes.
30460/**
30461 * Convert a numeric operand or charstring number to a variable-size list of bytes.
30462 * @param {number}
30463 * @returns {Array}
30464 */
30465encode.NUMBER = function(v) {
30466    if (v >= -107 && v <= 107) {
30467        return [v + 139];
30468    } else if (v >= 108 && v <= 1131) {
30469        v = v - 108;
30470        return [(v >> 8) + 247, v & 0xFF];
30471    } else if (v >= -1131 && v <= -108) {
30472        v = -v - 108;
30473        return [(v >> 8) + 251, v & 0xFF];
30474    } else if (v >= -32768 && v <= 32767) {
30475        return encode.NUMBER16(v);
30476    } else {
30477        return encode.NUMBER32(v);
30478    }
30479};
30480
30481/**
30482 * @param {number}
30483 * @returns {number}
30484 */
30485sizeOf.NUMBER = function(v) {
30486    return encode.NUMBER(v).length;
30487};
30488
30489/**
30490 * Convert a signed number between -32768 and +32767 to a three-byte value.
30491 * This ensures we always use three bytes, but is not the most compact format.
30492 * @param {number}
30493 * @returns {Array}
30494 */
30495encode.NUMBER16 = function(v) {
30496    return [28, (v >> 8) & 0xFF, v & 0xFF];
30497};
30498
30499/**
30500 * @constant
30501 * @type {number}
30502 */
30503sizeOf.NUMBER16 = constant(3);
30504
30505/**
30506 * Convert a signed number between -(2^31) and +(2^31-1) to a five-byte value.
30507 * This is useful if you want to be sure you always use four bytes,
30508 * at the expense of wasting a few bytes for smaller numbers.
30509 * @param {number}
30510 * @returns {Array}
30511 */
30512encode.NUMBER32 = function(v) {
30513    return [29, (v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];
30514};
30515
30516/**
30517 * @constant
30518 * @type {number}
30519 */
30520sizeOf.NUMBER32 = constant(5);
30521
30522/**
30523 * @param {number}
30524 * @returns {Array}
30525 */
30526encode.REAL = function(v) {
30527    var value = v.toString();
30528
30529    // Some numbers use an epsilon to encode the value. (e.g. JavaScript will store 0.0000001 as 1e-7)
30530    // This code converts it back to a number without the epsilon.
30531    var m = /\.(\d*?)(?:9{5,20}|0{5,20})\d{0,2}(?:e(.+)|$)/.exec(value);
30532    if (m) {
30533        var epsilon = parseFloat('1e' + ((m[2] ? +m[2] : 0) + m[1].length));
30534        value = (Math.round(v * epsilon) / epsilon).toString();
30535    }
30536
30537    var nibbles = '';
30538    for (var i = 0, ii = value.length; i < ii; i += 1) {
30539        var c = value[i];
30540        if (c === 'e') {
30541            nibbles += value[++i] === '-' ? 'c' : 'b';
30542        } else if (c === '.') {
30543            nibbles += 'a';
30544        } else if (c === '-') {
30545            nibbles += 'e';
30546        } else {
30547            nibbles += c;
30548        }
30549    }
30550
30551    nibbles += (nibbles.length & 1) ? 'f' : 'ff';
30552    var out = [30];
30553    for (var i$1 = 0, ii$1 = nibbles.length; i$1 < ii$1; i$1 += 2) {
30554        out.push(parseInt(nibbles.substr(i$1, 2), 16));
30555    }
30556
30557    return out;
30558};
30559
30560/**
30561 * @param {number}
30562 * @returns {number}
30563 */
30564sizeOf.REAL = function(v) {
30565    return encode.REAL(v).length;
30566};
30567
30568encode.NAME = encode.CHARARRAY;
30569sizeOf.NAME = sizeOf.CHARARRAY;
30570
30571encode.STRING = encode.CHARARRAY;
30572sizeOf.STRING = sizeOf.CHARARRAY;
30573
30574/**
30575 * @param {DataView} data
30576 * @param {number} offset
30577 * @param {number} numBytes
30578 * @returns {string}
30579 */
30580decode.UTF8 = function(data, offset, numBytes) {
30581    var codePoints = [];
30582    var numChars = numBytes;
30583    for (var j = 0; j < numChars; j++, offset += 1) {
30584        codePoints[j] = data.getUint8(offset);
30585    }
30586
30587    return String.fromCharCode.apply(null, codePoints);
30588};
30589
30590/**
30591 * @param {DataView} data
30592 * @param {number} offset
30593 * @param {number} numBytes
30594 * @returns {string}
30595 */
30596decode.UTF16 = function(data, offset, numBytes) {
30597    var codePoints = [];
30598    var numChars = numBytes / 2;
30599    for (var j = 0; j < numChars; j++, offset += 2) {
30600        codePoints[j] = data.getUint16(offset);
30601    }
30602
30603    return String.fromCharCode.apply(null, codePoints);
30604};
30605
30606/**
30607 * Convert a JavaScript string to UTF16-BE.
30608 * @param {string}
30609 * @returns {Array}
30610 */
30611encode.UTF16 = function(v) {
30612    var b = [];
30613    for (var i = 0; i < v.length; i += 1) {
30614        var codepoint = v.charCodeAt(i);
30615        b[b.length] = (codepoint >> 8) & 0xFF;
30616        b[b.length] = codepoint & 0xFF;
30617    }
30618
30619    return b;
30620};
30621
30622/**
30623 * @param {string}
30624 * @returns {number}
30625 */
30626sizeOf.UTF16 = function(v) {
30627    return v.length * 2;
30628};
30629
30630// Data for converting old eight-bit Macintosh encodings to Unicode.
30631// This representation is optimized for decoding; encoding is slower
30632// and needs more memory. The assumption is that all opentype.js users
30633// want to open fonts, but saving a font will be comparatively rare
30634// so it can be more expensive. Keyed by IANA character set name.
30635//
30636// Python script for generating these strings:
30637//
30638//     s = u''.join([chr(c).decode('mac_greek') for c in range(128, 256)])
30639//     print(s.encode('utf-8'))
30640/**
30641 * @private
30642 */
30643var eightBitMacEncodings = {
30644    'x-mac-croatian':  // Python: 'mac_croatian'
30645    'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®Š™´¨≠ŽØ∞±≤≥∆µ∂∑∏š∫ªºΩžø' +
30646    '¿¡¬√ƒ≈ƫȅ ÀÃÕŒœĐ—“”‘’÷◊©⁄€‹›Æ»–·‚„‰ÂćÁčÈÍÎÏÌÓÔđÒÚÛÙıˆ˜¯πË˚¸Êæˇ',
30647    'x-mac-cyrillic':  // Python: 'mac_cyrillic'
30648    'АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ†°Ґ£§•¶І®©™Ђђ≠Ѓѓ∞±≤≥іµґЈЄєЇїЉљЊњ' +
30649    'јЅ¬√ƒ≈∆«»… ЋћЌќѕ–—“”‘’÷„ЎўЏџ№Ёёяабвгдежзийклмнопрстуфхцчшщъыьэю',
30650    'x-mac-gaelic': // http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/GAELIC.TXT
30651    'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØḂ±≤≥ḃĊċḊḋḞḟĠġṀæø' +
30652    'ṁṖṗɼƒſṠ«»… ÀÃÕŒœ–—“”‘’ṡẛÿŸṪ€‹›Ŷŷṫ·Ỳỳ⁊ÂÊÁËÈÍÎÏÌÓÔ♣ÒÚÛÙıÝýŴŵẄẅẀẁẂẃ',
30653    'x-mac-greek':  // Python: 'mac_greek'
30654    'Ĺ²É³ÖÜ΅àâä΄¨çéèê룙î‰ôö¦€ùûü†ΓΔΘΛΞΠß®©ΣΪ§≠°·Α±≤≥¥ΒΕΖΗΙΚΜΦΫΨΩ' +
30655    'άΝ¬ΟΡ≈Τ«»… ΥΧΆΈœ–―“”‘’÷ΉΊΌΎέήίόΏύαβψδεφγηιξκλμνοπώρστθωςχυζϊϋΐΰ\u00AD',
30656    'x-mac-icelandic':  // Python: 'mac_iceland'
30657    'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûüݰ¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø' +
30658    '¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄€ÐðÞþý·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ',
30659    'x-mac-inuit': // http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/INUIT.TXT
30660    'ᐃᐄᐅᐆᐊᐋᐱᐲᐳᐴᐸᐹᑉᑎᑏᑐᑑᑕᑖᑦᑭᑮᑯᑰᑲᑳᒃᒋᒌᒍᒎᒐᒑ°ᒡᒥᒦ•¶ᒧ®©™ᒨᒪᒫᒻᓂᓃᓄᓅᓇᓈᓐᓯᓰᓱᓲᓴᓵᔅᓕᓖᓗ' +
30661    'ᓘᓚᓛᓪᔨᔩᔪᔫᔭ… ᔮᔾᕕᕖᕗ–—“”‘’ᕘᕙᕚᕝᕆᕇᕈᕉᕋᕌᕐᕿᖀᖁᖂᖃᖄᖅᖏᖐᖑᖒᖓᖔᖕᙱᙲᙳᙴᙵᙶᖖᖠᖡᖢᖣᖤᖥᖦᕼŁł',
30662    'x-mac-ce':  // Python: 'mac_latin2'
30663    'ÄĀāÉĄÖÜáąČäčĆć鏟ĎíďĒēĖóėôöõúĚěü†°Ę£§•¶ß®©™ę¨≠ģĮįĪ≤≥īĶ∂∑łĻļĽľĹĺŅ' +
30664    'ņѬ√ńŇ∆«»… ňŐÕőŌ–—“”‘’÷◊ōŔŕŘ‹›řŖŗŠ‚„šŚśÁŤťÍŽžŪÓÔūŮÚůŰűŲųÝýķŻŁżĢˇ',
30665    macintosh:  // Python: 'mac_roman'
30666    'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø' +
30667    '¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄€‹›fifl‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ',
30668    'x-mac-romanian':  // Python: 'mac_romanian'
30669    'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ĂȘ∞±≤≥¥µ∂∑∏π∫ªºΩăș' +
30670    '¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄€‹›Țț‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ',
30671    'x-mac-turkish':  // Python: 'mac_turkish'
30672    'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø' +
30673    '¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸĞğİıŞş‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙˆ˜¯˘˙˚¸˝˛ˇ'
30674};
30675
30676/**
30677 * Decodes an old-style Macintosh string. Returns either a Unicode JavaScript
30678 * string, or 'undefined' if the encoding is unsupported. For example, we do
30679 * not support Chinese, Japanese or Korean because these would need large
30680 * mapping tables.
30681 * @param {DataView} dataView
30682 * @param {number} offset
30683 * @param {number} dataLength
30684 * @param {string} encoding
30685 * @returns {string}
30686 */
30687decode.MACSTRING = function(dataView, offset, dataLength, encoding) {
30688    var table = eightBitMacEncodings[encoding];
30689    if (table === undefined) {
30690        return undefined;
30691    }
30692
30693    var result = '';
30694    for (var i = 0; i < dataLength; i++) {
30695        var c = dataView.getUint8(offset + i);
30696        // In all eight-bit Mac encodings, the characters 0x00..0x7F are
30697        // mapped to U+0000..U+007F; we only need to look up the others.
30698        if (c <= 0x7F) {
30699            result += String.fromCharCode(c);
30700        } else {
30701            result += table[c & 0x7F];
30702        }
30703    }
30704
30705    return result;
30706};
30707
30708// Helper function for encode.MACSTRING. Returns a dictionary for mapping
30709// Unicode character codes to their 8-bit MacOS equivalent. This table
30710// is not exactly a super cheap data structure, but we do not care because
30711// encoding Macintosh strings is only rarely needed in typical applications.
30712var macEncodingTableCache = typeof WeakMap === 'function' && new WeakMap();
30713var macEncodingCacheKeys;
30714var getMacEncodingTable = function (encoding) {
30715    // Since we use encoding as a cache key for WeakMap, it has to be
30716    // a String object and not a literal. And at least on NodeJS 2.10.1,
30717    // WeakMap requires that the same String instance is passed for cache hits.
30718    if (!macEncodingCacheKeys) {
30719        macEncodingCacheKeys = {};
30720        for (var e in eightBitMacEncodings) {
30721            /*jshint -W053 */  // Suppress "Do not use String as a constructor."
30722            macEncodingCacheKeys[e] = new String(e);
30723        }
30724    }
30725
30726    var cacheKey = macEncodingCacheKeys[encoding];
30727    if (cacheKey === undefined) {
30728        return undefined;
30729    }
30730
30731    // We can't do "if (cache.has(key)) {return cache.get(key)}" here:
30732    // since garbage collection may run at any time, it could also kick in
30733    // between the calls to cache.has() and cache.get(). In that case,
30734    // we would return 'undefined' even though we do support the encoding.
30735    if (macEncodingTableCache) {
30736        var cachedTable = macEncodingTableCache.get(cacheKey);
30737        if (cachedTable !== undefined) {
30738            return cachedTable;
30739        }
30740    }
30741
30742    var decodingTable = eightBitMacEncodings[encoding];
30743    if (decodingTable === undefined) {
30744        return undefined;
30745    }
30746
30747    var encodingTable = {};
30748    for (var i = 0; i < decodingTable.length; i++) {
30749        encodingTable[decodingTable.charCodeAt(i)] = i + 0x80;
30750    }
30751
30752    if (macEncodingTableCache) {
30753        macEncodingTableCache.set(cacheKey, encodingTable);
30754    }
30755
30756    return encodingTable;
30757};
30758
30759/**
30760 * Encodes an old-style Macintosh string. Returns a byte array upon success.
30761 * If the requested encoding is unsupported, or if the input string contains
30762 * a character that cannot be expressed in the encoding, the function returns
30763 * 'undefined'.
30764 * @param {string} str
30765 * @param {string} encoding
30766 * @returns {Array}
30767 */
30768encode.MACSTRING = function(str, encoding) {
30769    var table = getMacEncodingTable(encoding);
30770    if (table === undefined) {
30771        return undefined;
30772    }
30773
30774    var result = [];
30775    for (var i = 0; i < str.length; i++) {
30776        var c = str.charCodeAt(i);
30777
30778        // In all eight-bit Mac encodings, the characters 0x00..0x7F are
30779        // mapped to U+0000..U+007F; we only need to look up the others.
30780        if (c >= 0x80) {
30781            c = table[c];
30782            if (c === undefined) {
30783                // str contains a Unicode character that cannot be encoded
30784                // in the requested encoding.
30785                return undefined;
30786            }
30787        }
30788        result[i] = c;
30789        // result.push(c);
30790    }
30791
30792    return result;
30793};
30794
30795/**
30796 * @param {string} str
30797 * @param {string} encoding
30798 * @returns {number}
30799 */
30800sizeOf.MACSTRING = function(str, encoding) {
30801    var b = encode.MACSTRING(str, encoding);
30802    if (b !== undefined) {
30803        return b.length;
30804    } else {
30805        return 0;
30806    }
30807};
30808
30809// Helper for encode.VARDELTAS
30810function isByteEncodable(value) {
30811    return value >= -128 && value <= 127;
30812}
30813
30814// Helper for encode.VARDELTAS
30815function encodeVarDeltaRunAsZeroes(deltas, pos, result) {
30816    var runLength = 0;
30817    var numDeltas = deltas.length;
30818    while (pos < numDeltas && runLength < 64 && deltas[pos] === 0) {
30819        ++pos;
30820        ++runLength;
30821    }
30822    result.push(0x80 | (runLength - 1));
30823    return pos;
30824}
30825
30826// Helper for encode.VARDELTAS
30827function encodeVarDeltaRunAsBytes(deltas, offset, result) {
30828    var runLength = 0;
30829    var numDeltas = deltas.length;
30830    var pos = offset;
30831    while (pos < numDeltas && runLength < 64) {
30832        var value = deltas[pos];
30833        if (!isByteEncodable(value)) {
30834            break;
30835   
30835     }
30836
30837        // Within a byte-encoded run of deltas, a single zero is best
30838        // stored literally as 0x00 value. However, if we have two or
30839        // more zeroes in a sequence, it is better to start a new run.
30840        // Fore example, the sequence of deltas [15, 15, 0, 15, 15]
30841        // becomes 6 bytes (04 0F 0F 00 0F 0F) when storing the zero
30842        // within the current run, but 7 bytes (01 0F 0F 80 01 0F 0F)
30843        // when starting a new run.
30844        if (value === 0 && pos + 1 < numDeltas && deltas[pos + 1] === 0) {
30845            break;
30846        }
30847
30848        ++pos;
30849        ++runLength;
30850    }
30851    result.push(runLength - 1);
30852    for (var i = offset; i < pos; ++i) {
30853        result.push((deltas[i] + 256) & 0xff);
30854    }
30855    return pos;
30856}
30857
30858// Helper for encode.VARDELTAS
30859function encodeVarDeltaRunAsWords(deltas, offset, result) {
30860    var runLength = 0;
30861    var numDeltas = deltas.length;
30862    var pos = offset;
30863    while (pos < numDeltas && runLength < 64) {
30864        var value = deltas[pos];
30865
30866        // Within a word-encoded run of deltas, it is easiest to start
30867        // a new run (with a different encoding) whenever we encounter
30868        // a zero value. For example, the sequence [0x6666, 0, 0x7777]
30869        // needs 7 bytes when storing the zero inside the current run
30870        // (42 66 66 00 00 77 77), and equally 7 bytes when starting a
30871        // new run (40 66 66 80 40 77 77).
30872        if (value === 0) {
30873            break;
30874        }
30875
30876        // Within a word-encoded run of deltas, a single value in the
30877        // range (-128..127) should be encoded within the current run
30878        // because it is more compact. For example, the sequence
30879        // [0x6666, 2, 0x7777] becomes 7 bytes when storing the value
30880        // literally (42 66 66 00 02 77 77), but 8 bytes when starting
30881        // a new run (40 66 66 00 02 40 77 77).
30882        if (isByteEncodable(value) && pos + 1 < numDeltas && isByteEncodable(deltas[pos + 1])) {
30883            break;
30884        }
30885
30886        ++pos;
30887        ++runLength;
30888    }
30889    result.push(0x40 | (runLength - 1));
30890    for (var i = offset; i < pos; ++i) {
30891        var val = deltas[i];
30892        result.push(((val + 0x10000) >> 8) & 0xff, (val + 0x100) & 0xff);
30893    }
30894    return pos;
30895}
30896
30897/**
30898 * Encode a list of variation adjustment deltas.
30899 *
30900 * Variation adjustment deltas are used in ‘gvar’ and ‘cvar’ tables.
30901 * They indicate how points (in ‘gvar’) or values (in ‘cvar’) get adjusted
30902 * when generating instances of variation fonts.
30903 *
30904 * @see https://www.microsoft.com/typography/otspec/gvar.htm
30905 * @see https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6gvar.html
30906 * @param {Array}
30907 * @return {Array}
30908 */
30909encode.VARDELTAS = function(deltas) {
30910    var pos = 0;
30911    var result = [];
30912    while (pos < deltas.length) {
30913        var value = deltas[pos];
30914        if (value === 0) {
30915            pos = encodeVarDeltaRunAsZeroes(deltas, pos, result);
30916        } else if (value >= -128 && value <= 127) {
30917            pos = encodeVarDeltaRunAsBytes(deltas, pos, result);
30918        } else {
30919            pos = encodeVarDeltaRunAsWords(deltas, pos, result);
30920        }
30921    }
30922    return result;
30923};
30924
30925// Convert a list of values to a CFF INDEX structure.
30926// The values should be objects containing name / type / value.
30927/**
30928 * @param {Array} l
30929 * @returns {Array}
30930 */
30931encode.INDEX = function(l) {
30932    //var offset, offsets, offsetEncoder, encodedOffsets, encodedOffset, data,
30933    //    i, v;
30934    // Because we have to know which data type to use to encode the offsets,
30935    // we have to go through the values twice: once to encode the data and
30936    // calculate the offsets, then again to encode the offsets using the fitting data type.
30937    var offset = 1; // First offset is always 1.
30938    var offsets = [offset];
30939    var data = [];
30940    for (var i = 0; i < l.length; i += 1) {
30941        var v = encode.OBJECT(l[i]);
30942        Array.prototype.push.apply(data, v);
30943        offset += v.length;
30944        offsets.push(offset);
30945    }
30946
30947    if (data.length === 0) {
30948        return [0, 0];
30949    }
30950
30951    var encodedOffsets = [];
30952    var offSize = (1 + Math.floor(Math.log(offset) / Math.log(2)) / 8) | 0;
30953    var offsetEncoder = [undefined, encode.BYTE, encode.USHORT, encode.UINT24, encode.ULONG][offSize];
30954    for (var i$1 = 0; i$1 < offsets.length; i$1 += 1) {
30955        var encodedOffset = offsetEncoder(offsets[i$1]);
30956        Array.prototype.push.apply(encodedOffsets, encodedOffset);
30957    }
30958
30959    return Array.prototype.concat(encode.Card16(l.length),
30960                           encode.OffSize(offSize),
30961                           encodedOffsets,
30962                           data);
30963};
30964
30965/**
30966 * @param {Array}
30967 * @returns {number}
30968 */
30969sizeOf.INDEX = function(v) {
30970    return encode.INDEX(v).length;
30971};
30972
30973/**
30974 * Convert an object to a CFF DICT structure.
30975 * The keys should be numeric.
30976 * The values should be objects containing name / type / value.
30977 * @param {Object} m
30978 * @returns {Array}
30979 */
30980encode.DICT = function(m) {
30981    var d = [];
30982    var keys = Object.keys(m);
30983    var length = keys.length;
30984
30985    for (var i = 0; i < length; i += 1) {
30986        // Object.keys() return string keys, but our keys are always numeric.
30987        var k = parseInt(keys[i], 0);
30988        var v = m[k];
30989        // Value comes before the key.
30990        d = d.concat(encode.OPERAND(v.value, v.type));
30991        d = d.concat(encode.OPERATOR(k));
30992    }
30993
30994    return d;
30995};
30996
30997/**
30998 * @param {Object}
30999 * @returns {number}
31000 */
31001sizeOf.DICT = function(m) {
31002    return encode.DICT(m).length;
31003};
31004
31005/**
31006 * @param {number}
31007 * @returns {Array}
31008 */
31009encode.OPERATOR = function(v) {
31010    if (v < 1200) {
31011        return [v];
31012    } else {
31013        return [12, v - 1200];
31014    }
31015};
31016
31017/**
31018 * @param {Array} v
31019 * @param {string}
31020 * @returns {Array}
31021 */
31022encode.OPERAND = function(v, type) {
31023    var d = [];
31024    if (Array.isArray(type)) {
31025        for (var i = 0; i < type.length; i += 1) {
31026            check.argument(v.length === type.length, 'Not enough arguments given for type' + type);
31027            d = d.concat(encode.OPERAND(v[i], type[i]));
31028        }
31029    } else {
31030        if (type === 'SID') {
31031            d = d.concat(encode.NUMBER(v));
31032        } else if (type === 'offset') {
31033            // We make it easy for ourselves and always encode offsets as
31034            // 4 bytes. This makes offset calculation for the top dict easier.
31035            d = d.concat(encode.NUMBER32(v));
31036        } else if (type === 'number') {
31037            d = d.concat(encode.NUMBER(v));
31038        } else if (type === 'real') {
31039            d = d.concat(encode.REAL(v));
31040        } else {
31041            throw new Error('Unknown operand type ' + type);
31042            // FIXME Add support for booleans
31043        }
31044    }
31045
31046    return d;
31047};
31048
31049encode.OP = encode.BYTE;
31050sizeOf.OP = sizeOf.BYTE;
31051
31052// memoize charstring encoding using WeakMap if available
31053var wmm = typeof WeakMap === 'function' && new WeakMap();
31054
31055/**
31056 * Convert a list of CharString operations to bytes.
31057 * @param {Array}
31058 * @returns {Array}
31059 */
31060encode.CHARSTRING = function(ops) {
31061    // See encode.MACSTRING for why we don't do "if (wmm && wmm.has(ops))".
31062    if (wmm) {
31063        var cachedValue = wmm.get(ops);
31064        if (cachedValue !== undefined) {
31065            return cachedValue;
31066        }
31067    }
31068
31069    var d = [];
31070    var length = ops.length;
31071
31072    for (var i = 0; i < length; i += 1) {
31073        var op = ops[i];
31074        d = d.concat(encode[op.type](op.value));
31075    }
31076
31077    if (wmm) {
31078        wmm.set(ops, d);
31079    }
31080
31081    return d;
31082};
31083
31084/**
31085 * @param {Array}
31086 * @returns {number}
31087 */
31088sizeOf.CHARSTRING = function(ops) {
31089    return encode.CHARSTRING(ops).length;
31090};
31091
31092// Utility functions ////////////////////////////////////////////////////////
31093
31094/**
31095 * Convert an object containing name / type / value to bytes.
31096 * @param {Object}
31097 * @returns {Array}
31098 */
31099encode.OBJECT = function(v) {
31100    var encodingFunction = encode[v.type];
31101    check.argument(encodingFunction !== undefined, 'No encoding function for type ' + v.type);
31102    return encodingFunction(v.value);
31103};
31104
31105/**
31106 * @param {Object}
31107 * @returns {number}
31108 */
31109sizeOf.OBJECT = function(v) {
31110    var sizeOfFunction = sizeOf[v.type];
31111    check.argument(sizeOfFunction !== undefined, 'No sizeOf function for type ' + v.type);
31112    return sizeOfFunction(v.value);
31113};
31114
31115/**
31116 * Convert a table object to bytes.
31117 * A table contains a list of fields containing the metadata (name, type and default value).
31118 * The table itself has the field values set as attributes.
31119 * @param {opentype.Table}
31120 * @returns {Array}
31121 */
31122encode.TABLE = function(table) {
31123    var d = [];
31124    var length = table.fields.length;
31125    var subtables = [];
31126    var subtableOffsets = [];
31127
31128    for (var i = 0; i < length; i += 1) {
31129        var field = table.fields[i];
31130        var encodingFunction = encode[field.type];
31131        check.argument(encodingFunction !== undefined, 'No encoding function for field type ' + field.type + ' (' + field.name + ')');
31132        var value = table[field.name];
31133        if (value === undefined) {
31134            value = field.value;
31135        }
31136
31137        var bytes = encodingFunction(value);
31138
31139        if (field.type === 'TABLE') {
31140            subtableOffsets.push(d.length);
31141            d = d.concat([0, 0]);
31142            subtables.push(bytes);
31143        } else {
31144            d = d.concat(bytes);
31145        }
31146    }
31147
31148    for (var i$1 = 0; i$1 < subtables.length; i$1 += 1) {
31149        var o = subtableOffsets[i$1];
31150        var offset = d.length;
31151        check.argument(offset < 65536, 'Table ' + table.tableName + ' too big.');
31152        d[o] = offset >> 8;
31153        d[o + 1] = offset & 0xff;
31154        d = d.concat(subtables[i$1]);
31155    }
31156
31157    return d;
31158};
31159
31160/**
31161 * @param {opentype.Table}
31162 * @returns {number}
31163 */
31164sizeOf.TABLE = function(table) {
31165    var numBytes = 0;
31166    var length = table.fields.length;
31167
31168    for (var i = 0; i < length; i += 1) {
31169        var field = table.fields[i];
31170        var sizeOfFunction = sizeOf[field.type];
31171        check.argument(sizeOfFunction !== undefined, 'No sizeOf function for field type ' + field.type + ' (' + field.name + ')');
31172        var value = table[field.name];
31173        if (value === undefined) {
31174            value = field.value;
31175        }
31176
31177        numBytes += sizeOfFunction(value);
31178
31179        // Subtables take 2 more bytes for offsets.
31180        if (field.type === 'TABLE') {
31181            numBytes += 2;
31182        }
31183    }
31184
31185    return numBytes;
31186};
31187
31188encode.RECORD = encode.TABLE;
31189sizeOf.RECORD = sizeOf.TABLE;
31190
31191// Merge in a list of bytes.
31192encode.LITERAL = function(v) {
31193    return v;
31194};
31195
31196sizeOf.LITERAL = function(v) {
31197    return v.length;
31198};
31199
31200// Table metadata
31201
31202/**
31203 * @exports opentype.Table
31204 * @class
31205 * @param {string} tableName
31206 * @param {Array} fields
31207 * @param {Object} options
31208 * @constructor
31209 */
31210function Table(tableName, fields, options) {
31211    var this$1 = this;
31212
31213    for (var i = 0; i < fields.length; i += 1) {
31214        var field = fields[i];
31215        this$1[field.name] = field.value;
31216    }
31217
31218    this.tableName = tableName;
31219    this.fields = fields;
31220    if (options) {
31221        var optionKeys = Object.keys(options);
31222        for (var i$1 = 0; i$1 < optionKeys.length; i$1 += 1) {
31223            var k = optionKeys[i$1];
31224            var v = options[k];
31225            if (this$1[k] !== undefined) {
31226                this$1[k] = v;
31227            }
31228        }
31229    }
31230}
31231
31232/**
31233 * Encodes the table and returns an array of bytes
31234 * @return {Array}
31235 */
31236Table.prototype.encode = function() {
31237    return encode.TABLE(this);
31238};
31239
31240/**
31241 * Get the size of the table.
31242 * @return {number}
31243 */
31244Table.prototype.sizeOf = function() {
31245    return sizeOf.TABLE(this);
31246};
31247
31248/**
31249 * @private
31250 */
31251function ushortList(itemName, list, count) {
31252    if (count === undefined) {
31253        count = list.length;
31254    }
31255    var fields = new Array(list.length + 1);
31256    fields[0] = {name: itemName + 'Count', type: 'USHORT', value: count};
31257    for (var i = 0; i < list.length; i++) {
31258        fields[i + 1] = {name: itemName + i, type: 'USHORT', value: list[i]};
31259    }
31260    return fields;
31261}
31262
31263/**
31264 * @private
31265 */
31266function tableList(itemName, records, itemCallback) {
31267    var count = records.length;
31268    var fields = new Array(count + 1);
31269    fields[0] = {name: itemName + 'Count', type: 'USHORT', value: count};
31270    for (var i = 0; i < count; i++) {
31271        fields[i + 1] = {name: itemName + i, type: 'TABLE', value: itemCallback(records[i], i)};
31272    }
31273    return fields;
31274}
31275
31276/**
31277 * @private
31278 */
31279function recordList(itemName, records, itemCallback) {
31280    var count = records.length;
31281    var fields = [];
31282    fields[0] = {name: itemName + 'Count', type: 'USHORT', value: count};
31283    for (var i = 0; i < count; i++) {
31284        fields = fields.concat(itemCallback(records[i], i));
31285    }
31286    return fields;
31287}
31288
31289// Common Layout Tables
31290
31291/**
31292 * @exports opentype.Coverage
31293 * @class
31294 * @param {opentype.Table}
31295 * @constructor
31296 * @extends opentype.Table
31297 */
31298function Coverage(coverageTable) {
31299    if (coverageTable.format === 1) {
31300        Table.call(this, 'coverageTable',
31301            [{name: 'coverageFormat', type: 'USHORT', value: 1}]
31302            .concat(ushortList('glyph', coverageTable.glyphs))
31303        );
31304    } else {
31305        check.assert(false, 'Can\'t create coverage table format 2 yet.');
31306    }
31307}
31308Coverage.prototype = Object.create(Table.prototype);
31309Coverage.prototype.constructor = Coverage;
31310
31311function ScriptList(scriptListTable) {
31312    Table.call(this, 'scriptListTable',
31313        recordList('scriptRecord', scriptListTable, function(scriptRecord, i) {
31314            var script = scriptRecord.script;
31315            var defaultLangSys = script.defaultLangSys;
31316            check.assert(!!defaultLangSys, 'Unable to write GSUB: script ' + scriptRecord.tag + ' has no default language system.');
31317            return [
31318                {name: 'scriptTag' + i, type: 'TAG', value: scriptRecord.tag},
31319                {name: 'script' + i, type: 'TABLE', value: new Table('scriptTable', [
31320                    {name: 'defaultLangSys', type: 'TABLE', value: new Table('defaultLangSys', [
31321                        {name: 'lookupOrder', type: 'USHORT', value: 0},
31322                        {name: 'reqFeatureIndex', type: 'USHORT', value: defaultLangSys.reqFeatureIndex}]
31323                        .concat(ushortList('featureIndex', defaultLangSys.featureIndexes)))}
31324                    ].concat(recordList('langSys', script.langSysRecords, function(langSysRecord, i) {
31325                        var langSys = langSysRecord.langSys;
31326                        return [
31327                            {name: 'langSysTag' + i, type: 'TAG', value: langSysRecord.tag},
31328                            {name: 'langSys' + i, type: 'TABLE', value: new Table('langSys', [
31329                                {name: 'lookupOrder', type: 'USHORT', value: 0},
31330                                {name: 'reqFeatureIndex', type: 'USHORT', value: langSys.reqFeatureIndex}
31331                                ].concat(ushortList('featureIndex', langSys.featureIndexes)))}
31332                        ];
31333                    })))}
31334            ];
31335        })
31336    );
31337}
31338ScriptList.prototype = Object.create(Table.prototype);
31339ScriptList.prototype.constructor = ScriptList;
31340
31341/**
31342 * @exports opentype.FeatureList
31343 * @class
31344 * @param {opentype.Table}
31345 * @constructor
31346 * @extends opentype.Table
31347 */
31348function FeatureList(featureListTable) {
31349    Table.call(this, 'featureListTable',
31350        recordList('featureRecord', featureListTable, function(featureRecord, i) {
31351            var feature = featureRecord.feature;
31352            return [
31353                {name: 'featureTag' + i, type: 'TAG', value: featureRecord.tag},
31354                {name: 'feature' + i, type: 'TABLE', value: new Table('featureTable', [
31355                    {name: 'featureParams', type: 'USHORT', value: feature.featureParams} ].concat(ushortList('lookupListIndex', feature.lookupListIndexes)))}
31356            ];
31357        })
31358    );
31359}
31360FeatureList.prototype = Object.create(Table.prototype);
31361FeatureList.prototype.constructor = FeatureList;
31362
31363/**
31364 * @exports opentype.LookupList
31365 * @class
31366 * @param {opentype.Table}
31367 * @param {Object}
31368 * @constructor
31369 * @extends opentype.Table
31370 */
31371function LookupList(lookupListTable, subtableMakers) {
31372    Table.call(this, 'lookupListTable', tableList('lookup', lookupListTable, function(lookupTable) {
31373        var subtableCallback = subtableMakers[lookupTable.lookupType];
31374        check.assert(!!subtableCallback, 'Unable to write GSUB lookup type ' + lookupTable.lookupType + ' tables.');
31375        return new Table('lookupTable', [
31376            {name: 'lookupType', type: 'USHORT', value: lookupTable.lookupType},
31377            {name: 'lookupFlag', type: 'USHORT', value: lookupTable.lookupFlag}
31378        ].concat(tableList('subtable', lookupTable.subtables, subtableCallback)));
31379    }));
31380}
31381LookupList.prototype = Object.create(Table.prototype);
31382LookupList.prototype.constructor = LookupList;
31383
31384// Record = same as Table, but inlined (a Table has an offset and its data is further in the stream)
31385// Don't use offsets inside Records (probable bug), only in Tables.
31386var table = {
31387    Table: Table,
31388    Record: Table,
31389    Coverage: Coverage,
31390    ScriptList: ScriptList,
31391    FeatureList: FeatureList,
31392    LookupList: LookupList,
31393    ushortList: ushortList,
31394    tableList: tableList,
31395    recordList: recordList,
31396};
31397
31398// Parsing utility functions
31399
31400// Retrieve an unsigned byte from the DataView.
31401function getByte(dataView, offset) {
31402    return dataView.getUint8(offset);
31403}
31404
31405// Retrieve an unsigned 16-bit short from the DataView.
31406// The value is stored in big endian.
31407function getUShort(dataView, offset) {
31408    return dataView.getUint16(offset, false);
31409}
31410
31411// Retrieve a signed 16-bit short from the DataView.
31412// The value is stored in big endian.
31413function getShort(dataView, offset) {
31414    return dataView.getInt16(offset, false);
31415}
31416
31417// Retrieve an unsigned 32-bit long from the DataView.
31418// The value is stored in big endian.
31419function getULong(dataView, offset) {
31420    return dataView.getUint32(offset, false);
31421}
31422
31423// Retrieve a 32-bit signed fixed-point number (16.16) from the DataView.
31424// The value is stored in big endian.
31425function getFixed(dataView, offset) {
31426    var decimal = dataView.getInt16(offset, false);
31427    var fraction = dataView.getUint16(offset + 2, false);
31428    return decimal + fraction / 65535;
31429}
31430
31431// Retrieve a 4-character tag from the DataView.
31432// Tags are used to identify tables.
31433function getTag(dataView, offset) {
31434    var tag = '';
31435    for (var i = offset; i < offset + 4; i += 1) {
31436        tag += String.fromCharCode(dataView.getInt8(i));
31437    }
31438
31439    return tag;
31440}
31441
31442// Retrieve an offset from the DataView.
31443// Offsets are 1 to 4 bytes in length, depending on the offSize argument.
31444function getOffset(dataView, offset, offSize) {
31445    var v = 0;
31446    for (var i = 0; i < offSize; i += 1) {
31447        v <<= 8;
31448        v += dataView.getUint8(offset + i);
31449    }
31450
31451    return v;
31452}
31453
31454// Retrieve a number of bytes from start offset to the end offset from the DataView.
31455function getBytes(dataView, startOffset, endOffset) {
31456    var bytes = [];
31457    for (var i = startOffset; i < endOffset; i += 1) {
31458        bytes.push(dataView.getUint8(i));
31459    }
31460
31461    return bytes;
31462}
31463
31464// Convert the list of bytes to a string.
31465function bytesToString(bytes) {
31466    var s = '';
31467    for (var i = 0; i < bytes.length; i += 1) {
31468        s += String.fromCharCode(bytes[i]);
31469    }
31470
31471    return s;
31472}
31473
31474var typeOffsets = {
31475    byte: 1,
31476    uShort: 2,
31477    short: 2,
31478    uLong: 4,
31479    fixed: 4,
31480    longDateTime: 8,
31481    tag: 4
31482};
31483
31484// A stateful parser that changes the offset whenever a value is retrieved.
31485// The data is a DataView.
31486function Parser(data, offset) {
31487    this.data = data;
31488    this.offset = offset;
31489    this.relativeOffset = 0;
31490}
31491
31492Parser.prototype.parseByte = function() {
31493    var v = this.data.getUint8(this.offset + this.relativeOffset);
31494    this.relativeOffset += 1;
31495    return v;
31496};
31497
31498Parser.prototype.parseChar = function() {
31499    var v = this.data.getInt8(this.offset + this.relativeOffset);
31500    this.relativeOffset += 1;
31501    return v;
31502};
31503
31504Parser.prototype.parseCard8 = Parser.prototype.parseByte;
31505
31506Parser.prototype.parseUShort = function() {
31507    var v = this.data.getUint16(this.offset + this.relativeOffset);
31508    this.relativeOffset += 2;
31509    return v;
31510};
31511
31512Parser.prototype.parseCard16 = Parser.prototype.parseUShort;
31513Parser.prototype.parseSID = Parser.prototype.parseUShort;
31514Parser.prototype.parseOffset16 = Parser.prototype.parseUShort;
31515
31516Parser.prototype.parseShort = function() {
31517    var v = this.data.getInt16(this.offset + this.relativeOffset);
31518    this.relativeOffset += 2;
31519    return v;
31520};
31521
31522Parser.prototype.parseF2Dot14 = function() {
31523    var v = this.data.getInt16(this.offset + this.relativeOffset) / 16384;
31524    this.relativeOffset += 2;
31525    return v;
31526};
31527
31528Parser.prototype.parseULong = function() {
31529    var v = getULong(this.data, this.offset + this.relativeOffset);
31530    this.relativeOffset += 4;
31531    return v;
31532};
31533
31534Parser.prototype.parseFixed = function() {
31535    var v = getFixed(this.data, this.offset + this.relativeOffset);
31536    this.relativeOffset += 4;
31537    return v;
31538};
31539
31540Parser.prototype.parseString = function(length) {
31541    var dataView = this.data;
31542    var offset = this.offset + this.relativeOffset;
31543    var string = '';
31544    this.relativeOffset += length;
31545    for (var i = 0; i < length; i++) {
31546        string += String.fromCharCode(dataView.getUint8(offset + i));
31547    }
31548
31549    return string;
31550};
31551
31552Parser.prototype.parseTag = function() {
31553    return this.parseString(4);
31554};
31555
31556// LONGDATETIME is a 64-bit integer.
31557// JavaScript and unix timestamps traditionally use 32 bits, so we
31558// only take the last 32 bits.
31559// + Since until 2038 those bits will be filled by zeros we can ignore them.
31560Parser.prototype.parseLongDateTime = function() {
31561    var v = getULong(this.data, this.offset + this.relativeOffset + 4);
31562    // Subtract seconds between 01/01/1904 and 01/01/1970
31563    // to convert Apple Mac timestamp to Standard Unix timestamp
31564    v -= 2082844800;
31565    this.relativeOffset += 8;
31566    return v;
31567};
31568
31569Parser.prototype.parseVersion = function() {
31570    var major = getUShort(this.data, this.offset + this.relativeOffset);
31571
31572    // How to interpret the minor version is very vague in the spec. 0x5000 is 5, 0x1000 is 1
31573    // This returns the correct number if minor = 0xN000 where N is 0-9
31574    var minor = getUShort(this.data, this.offset + this.relativeOffset + 2);
31575    this.relativeOffset += 4;
31576    return major + minor / 0x1000 / 10;
31577};
31578
31579Parser.prototype.skip = function(type, amount) {
31580    if (amount === undefined) {
31581        amount = 1;
31582    }
31583
31584    this.relativeOffset += typeOffsets[type] * amount;
31585};
31586
31587///// Parsing lists and records ///////////////////////////////
31588
31589// Parse a list of 16 bit unsigned integers. The length of the list can be read on the stream
31590// or provided as an argument.
31591Parser.prototype.parseOffset16List =
31592Parser.prototype.parseUShortList = function(count) {
31593    if (count === undefined) { count = this.parseUShort(); }
31594    var offsets = new Array(count);
31595    var dataView = this.data;
31596    var offset = this.offset + this.relativeOffset;
31597    for (var i = 0; i < count; i++) {
31598        offsets[i] = dataView.getUint16(offset);
31599        offset += 2;
31600    }
31601
31602    this.relativeOffset += count * 2;
31603    return offsets;
31604};
31605
31606// Parses a list of 16 bit signed integers.
31607Parser.prototype.parseShortList = function(count) {
31608    var list = new Array(count);
31609    var dataView = this.data;
31610    var offset = this.offset + this.relativeOffset;
31611    for (var i = 0; i < count; i++) {
31612        list[i] = dataView.getInt16(offset);
31613        offset += 2;
31614    }
31615
31616    this.relativeOffset += count * 2;
31617    return list;
31618};
31619
31620// Parses a list of bytes.
31621Parser.prototype.parseByteList = function(count) {
31622    var list = new Array(count);
31623    var dataView = this.data;
31624    var offset = this.offset + this.relativeOffset;
31625    for (var i = 0; i < count; i++) {
31626        list[i] = dataView.getUint8(offset++);
31627    }
31628
31629    this.relativeOffset += count;
31630    return list;
31631};
31632
31633/**
31634 * Parse a list of items.
31635 * Record count is optional, if omitted it is read from the stream.
31636 * itemCallback is one of the Parser methods.
31637 */
31638Parser.prototype.parseList = function(count, itemCallback) {
31639    var this$1 = this;
31640
31641    if (!itemCallback) {
31642        itemCallback = count;
31643        count = this.parseUShort();
31644    }
31645    var list = new Array(count);
31646    for (var i = 0; i < count; i++) {
31647        list[i] = itemCallback.call(this$1);
31648    }
31649    return list;
31650};
31651
31652/**
31653 * Parse a list of records.
31654 * Record count is optional, if omitted it is read from the stream.
31655 * Example of recordDescription: { sequenceIndex: Parser.uShort, lookupListIndex: Parser.uShort }
31656 */
31657Parser.prototype.parseRecordList = function(count, recordDescription) {
31658    var this$1 = this;
31659
31660    // If the count argument is absent, read it in the stream.
31661    if (!recordDescription) {
31662        recordDescription = count;
31663        count = this.parseUShort();
31664    }
31665    var records = new Array(count);
31666    var fields = Object.keys(recordDescription);
31667    for (var i = 0; i < count; i++) {
31668        var rec = {};
31669        for (var j = 0; j < fields.length; j++) {
31670            var fieldName = fields[j];
31671            var fieldType = recordDescription[fieldName];
31672            rec[fieldName] = fieldType.call(this$1);
31673        }
31674        records[i] = rec;
31675    }
31676    return records;
31677};
31678
31679// Parse a data structure into an object
31680// Example of description: { sequenceIndex: Parser.uShort, lookupListIndex: Parser.uShort }
31681Parser.prototype.parseStruct = function(description) {
31682    var this$1 = this;
31683
31684    if (typeof description === 'function') {
31685        return description.call(this);
31686    } else {
31687        var fields = Object.keys(description);
31688        var struct = {};
31689        for (var j = 0; j < fields.length; j++) {
31690            var fieldName = fields[j];
31691            var fieldType = description[fieldName];
31692            struct[fieldName] = fieldType.call(this$1);
31693        }
31694        return struct;
31695    }
31696};
31697
31698Parser.prototype.parsePointer = function(description) {
31699    var structOffset = this.parseOffset16();
31700    if (structOffset > 0) {                         // NULL offset => return undefined
31701        return new Parser(this.data, this.offset + structOffset).parseStruct(description);
31702    }
31703    return undefined;
31704};
31705
31706/**
31707 * Parse a list of offsets to lists of 16-bit integers,
31708 * or a list of offsets to lists of offsets to any kind of items.
31709 * If itemCallback is not provided, a list of list of UShort is assumed.
31710 * If provided, itemCallback is called on each item and must parse the item.
31711 * See examples in tables/gsub.js
31712 */
31713Parser.prototype.parseListOfLists = function(itemCallback) {
31714    var this$1 = this;
31715
31716    var offsets = this.parseOffset16List();
31717    var count = offsets.length;
31718    var relativeOffset = this.relativeOffset;
31719    var list = new Array(count);
31720    for (var i = 0; i < count; i++) {
31721        var start = offsets[i];
31722        if (start === 0) {                  // NULL offset
31723            list[i] = undefined;            // Add i as owned property to list. Convenient with assert.
31724            continue;
31725        }
31726        this$1.relativeOffset = start;
31727        if (itemCallback) {
31728            var subOffsets = this$1.parseOffset16List();
31729            var subList = new Array(subOffsets.length);
31730            for (var j = 0; j < subOffsets.length; j++) {
31731                this$1.relativeOffset = start + subOffsets[j];
31732                subList[j] = itemCallback.call(this$1);
31733            }
31734            list[i] = subList;
31735        } else {
31736            list[i] = this$1.parseUShortList();
31737        }
31738    }
31739    this.relativeOffset = relativeOffset;
31740    return list;
31741};
31742
vendor: 4,374 bytes, lines 31743-31873
31743///// Complex tables parsing //////////////////////////////////
31744
31745// Parse a coverage table in a GSUB, GPOS or GDEF table.
31746// https://www.microsoft.com/typography/OTSPEC/chapter2.htm
31747// parser.offset must point to the start of the table containing the coverage.
31748Parser.prototype.parseCoverage = function() {
31749    var this$1 = this;
31750
31751    var startOffset = this.offset + this.relativeOffset;
31752    var format = this.parseUShort();
31753    var count = this.parseUShort();
31754    if (format === 1) {
31755        return {
31756            format: 1,
31757            glyphs: this.parseUShortList(count)
31758        };
31759    } else if (format === 2) {
31760        var ranges = new Array(count);
31761        for (var i = 0; i < count; i++) {
31762            ranges[i] = {
31763                start: this$1.parseUShort(),
31764                end: this$1.parseUShort(),
31765                index: this$1.parseUShort()
31766            };
31767        }
31768        return {
31769            format: 2,
31770            ranges: ranges
31771        };
31772    }
31773    throw new Error('0x' + startOffset.toString(16) + ': Coverage format must be 1 or 2.');
31774};
31775
31776// Parse a Class Definition Table in a GSUB, GPOS or GDEF table.
31777// https://www.microsoft.com/typography/OTSPEC/chapter2.htm
31778Parser.prototype.parseClassDef = function() {
31779    var startOffset = this.offset + this.relativeOffset;
31780    var format = this.parseUShort();
31781    if (format === 1) {
31782        return {
31783            format: 1,
31784            startGlyph: this.parseUShort(),
31785            classes: this.parseUShortList()
31786        };
31787    } else if (format === 2) {
31788        return {
31789            format: 2,
31790            ranges: this.parseRecordList({
31791                start: Parser.uShort,
31792                end: Parser.uShort,
31793                classId: Parser.uShort
31794            })
31795        };
31796    }
31797    throw new Error('0x' + startOffset.toString(16) + ': ClassDef format must be 1 or 2.');
31798};
31799
31800///// Static methods ///////////////////////////////////
31801// These convenience methods can be used as callbacks and should be called with "this" context set to a Parser instance.
31802
31803Parser.list = function(count, itemCallback) {
31804    return function() {
31805        return this.parseList(count, itemCallback);
31806    };
31807};
31808
31809Parser.recordList = function(count, recordDescription) {
31810    return function() {
31811        return this.parseRecordList(count, recordDescription);
31812    };
31813};
31814
31815Parser.pointer = function(description) {
31816    return function() {
31817        return this.parsePointer(description);
31818    };
31819};
31820
31821Parser.tag = Parser.prototype.parseTag;
31822Parser.byte = Parser.prototype.parseByte;
31823Parser.uShort = Parser.offset16 = Parser.prototype.parseUShort;
31824Parser.uShortList = Parser.prototype.parseUShortList;
31825Parser.struct = Parser.prototype.parseStruct;
31826Parser.coverage = Parser.prototype.parseCoverage;
31827Parser.classDef = Parser.prototype.parseClassDef;
31828
31829///// Script, Feature, Lookup lists ///////////////////////////////////////////////
31830// https://www.microsoft.com/typography/OTSPEC/chapter2.htm
31831
31832var langSysTable = {
31833    reserved: Parser.uShort,
31834    reqFeatureIndex: Parser.uShort,
31835    featureIndexes: Parser.uShortList
31836};
31837
31838Parser.prototype.parseScriptList = function() {
31839    return this.parsePointer(Parser.recordList({
31840        tag: Parser.tag,
31841        script: Parser.pointer({
31842            defaultLangSys: Parser.pointer(langSysTable),
31843            langSysRecords: Parser.recordList({
31844                tag: Parser.tag,
31845                langSys: Parser.pointer(langSysTable)
31846            })
31847        })
31848    }));
31849};
31850
31851Parser.prototype.parseFeatureList = function() {
31852    return this.parsePointer(Parser.recordList({
31853        tag: Parser.tag,
31854        feature: Parser.pointer({
31855            featureParams: Parser.offset16,
31856            lookupListIndexes: Parser.uShortList
31857        })
31858    }));
31859};
31860
31861Parser.prototype.parseLookupList = function(lookupTableParsers) {
31862    return this.parsePointer(Parser.list(Parser.pointer(function() {
31863        var lookupType = this.parseUShort();
31864        check.argument(1 <= lookupType && lookupType <= 8, 'GSUB lookup type ' + lookupType + ' unknown.');
31865        var lookupFlag = this.parseUShort();
31866        var useMarkFilteringSet = lookupFlag & 0x10;
31867        return {
31868            lookupType: lookupType,
31869            lookupFlag: lookupFlag,
31870            subtables: this.parseList(Parser.pointer(lookupTableParsers[lookupType])),
31871            markFilteringSet: useMarkFilteringSet ? this.parseUShort() : undefined
31872        };
31873    }
31873)));
31874};
31875
31876var parse = {
31877    getByte: getByte,
31878    getCard8: getByte,
31879    getUShort: getUShort,
31880    getCard16: getUShort,
31881    getShort: getShort,
31882    getULong: getULong,
31883    getFixed: getFixed,
31884    getTag: getTag,
31885    getOffset: getOffset,
31886    getBytes: getBytes,
31887    bytesToString: bytesToString,
31888    Parser: Parser,
31889};
31890
31891// The `cmap` table stores the mappings from characters to glyphs.
31892// https://www.microsoft.com/typography/OTSPEC/cmap.htm
31893
31894function parseCmapTableFormat12(cmap, p) {
31895    //Skip reserved.
31896    p.parseUShort();
31897
31898    // Length in bytes of the sub-tables.
31899    cmap.length = p.parseULong();
31900    cmap.language = p.parseULong();
31901
31902    var groupCount;
31903    cmap.groupCount = groupCount = p.parseULong();
31904    cmap.glyphIndexMap = {};
31905
31906    for (var i = 0; i < groupCount; i += 1) {
31907        var startCharCode = p.parseULong();
31908        var endCharCode = p.parseULong();
31909        var startGlyphId = p.parseULong();
31910
31911        for (var c = startCharCode; c <= endCharCode; c += 1) {
31912            cmap.glyphIndexMap[c] = startGlyphId;
31913            startGlyphId++;
31914        }
31915    }
31916}
31917
31918function parseCmapTableFormat4(cmap, p, data, start, offset) {
31919    // Length in bytes of the sub-tables.
31920    cmap.length = p.parseUShort();
31921    cmap.language = p.parseUShort();
31922
31923    // segCount is stored x 2.
31924    var segCount;
31925    cmap.segCount = segCount = p.parseUShort() >> 1;
31926
31927    // Skip searchRange, entrySelector, rangeShift.
31928    p.skip('uShort', 3);
31929
31930    // The "unrolled" mapping from character codes to glyph indices.
31931    cmap.glyphIndexMap = {};
31932    var endCountParser = new parse.Parser(data, start + offset + 14);
31933    var startCountParser = new parse.Parser(data, start + offset + 16 + segCount * 2);
31934    var idDeltaParser = new parse.Parser(data, start + offset + 16 + segCount * 4);
31935    var idRangeOffsetParser = new parse.Parser(data, start + offset + 16 + segCount * 6);
31936    var glyphIndexOffset = start + offset + 16 + segCount * 8;
31937    for (var i = 0; i < segCount - 1; i += 1) {
31938        var glyphIndex = (void 0);
31939        var endCount = endCountParser.parseUShort();
31940        var startCount = startCountParser.parseUShort();
31941        var idDelta = idDeltaParser.parseShort();
31942        var idRangeOffset = idRangeOffsetParser.parseUShort();
31943        for (var c = startCount; c <= endCount; c += 1) {
31944            if (idRangeOffset !== 0) {
31945                // The idRangeOffset is relative to the current position in the idRangeOffset array.
31946                // Take the current offset in the idRangeOffset array.
31947                glyphIndexOffset = (idRangeOffsetParser.offset + idRangeOffsetParser.relativeOffset - 2);
31948
31949                // Add the value of the idRangeOffset, which will move us into the glyphIndex array.
31950                glyphIndexOffset += idRangeOffset;
31951
31952                // Then add the character index of the current segment, multiplied by 2 for USHORTs.
31953                glyphIndexOffset += (c - startCount) * 2;
31954                glyphIndex = parse.getUShort(data, glyphIndexOffset);
31955                if (glyphIndex !== 0) {
31956                    glyphIndex = (glyphIndex + idDelta) & 0xFFFF;
31957                }
31958            } else {
31959                glyphIndex = (c + idDelta) & 0xFFFF;
31960            }
31961
31962            cmap.glyphIndexMap[c] = glyphIndex;
31963        }
31964    }
31965}
31966
31967// Parse the `cmap` table. This table stores the mappings from characters to glyphs.
31968// There are many available formats, but we only support the Windows format 4 and 12.
31969// This function returns a `CmapEncoding` object or null if no supported format could be found.
31970function parseCmapTable(data, start) {
31971    var cmap = {};
31972    cmap.version = parse.getUShort(data, start);
31973    check.argument(cmap.version === 0, 'cmap table version should be 0.');
31974
31975    // The cmap table can contain many sub-tables, each with their own format.
31976    // We're only interested in a "platform 3" table. This is a Windows format.
31977    cmap.numTables = parse.getUShort(data, start + 2);
31978    var offset = -1;
31979    for (var i = cmap.numTables - 1; i >= 0; i -= 1) {
31980        var platformId = parse.getUShort(data, start + 4 + (i * 8));
31981        var encodingId = parse.getUShort(data, start + 4 + (i * 8) + 2);
31982        if (platformId === 3 && (encodingId === 0 || encodingId === 1 || encodingId === 10)) {
31983            offset = parse.getULong(data, start + 4 + (i * 8) + 4);
31984            break;
31985        }
31986    }
31987
31988    if (offset === -1) {
31989        // There is no cmap table in the font that we support.
31990        throw new Error('No valid cmap sub-tables found.');
31991    }
31992
31993    var p = new parse.Parser(data, start + offset);
31994    cmap.format = p.parseUShort();
31995
31996    if (cmap.format === 12) {
31997        parseCmapTableFormat12(cmap, p);
31998    } else if (cmap.format === 4) {
31999        parseCmapTableFormat4(cmap, p, data, start, offset);
32000    } else {
32001        throw new Error('Only format 4 and 12 cmap tables are supported (found format ' + cmap.format + ').');
32002    }
32003
32004    return cmap;
32005}
32006
32007function addSegment(t, code, glyphIndex) {
32008    t.segments.push({
32009        end: code,
32010        start: code,
32011        delta: -(code - glyphIndex),
32012        offset: 0
32013    });
32014}
32015
32016function addTerminatorSegment(t) {
32017    t.segments.push({
32018        end: 0xFFFF,
32019        start: 0xFFFF,
32020        delta: 1,
32021        offset: 0
32022    });
32023}
32024
32025function makeCmapTable(glyphs) {
32026    var t = new table.Table('cmap', [
32027        {name: 'version', type: 'USHORT', value: 0},
32028        {name: 'numTables', type: 'USHORT', value: 1},
32029        {name: 'platformID', type: 'USHORT', value: 3},
32030        {name: 'encodingID', type: 'USHORT', value: 1},
32031        {name: 'offset', type: 'ULONG', value: 12},
32032        {name: 'format', type: 'USHORT', value: 4},
32033        {name: 'length', type: 'USHORT', value: 0},
32034        {name: 'language', type: 'USHORT', value: 0},
32035        {name: 'segCountX2', type: 'USHORT', value: 0},
32036        {name: 'searchRange', type: 'USHORT', value: 0},
32037        {name: 'entrySelector', type: 'USHORT', value: 0},
32038        {name: 'rangeShift', type: 'USHORT', value: 0}
32039    ]);
32040
32041    t.segments = [];
32042    for (var i = 0; i < glyphs.length; i += 1) {
32043        var glyph = glyphs.get(i);
32044        for (var j = 0; j < glyph.unicodes.length; j += 1) {
32045            addSegment(t, glyph.unicodes[j], i);
32046        }
32047
32048        t.segments = t.segments.sort(function(a, b) {
32049            return a.start - b.start;
32050        });
32051    }
32052
32053    addTerminatorSegment(t);
32054
32055    var segCount;
32056    segCount = t.segments.length;
32057    t.segCountX2 = segCount * 2;
32058    t.searchRange = Math.pow(2, Math.floor(Math.log(segCount) / Math.log(2))) * 2;
32059    t.entrySelector = Math.log(t.searchRange / 2) / Math.log(2);
32060    t.rangeShift = t.segCountX2 - t.searchRange;
32061
32062    // Set up parallel segment arrays.
32063    var endCounts = [];
32064    var startCounts = [];
32065    var idDeltas = [];
32066    var idRangeOffsets = [];
32067    var glyphIds = [];
32068
32069    for (var i$1 = 0; i$1 < segCount; i$1 += 1) {
32070        var segment = t.segments[i$1];
32071        endCounts = endCounts.concat({name: 'end_' + i$1, type: 'USHORT', value: segment.end});
32072        startCounts = startCounts.concat({name: 'start_' + i$1, type: 'USHORT', value: segment.start});
32073        idDeltas = idDeltas.concat({name: 'idDelta_' + i$1, type: 'SHORT', value: segment.delta});
32074        idRangeOffsets = idRangeOffsets.concat({name: 'idRangeOffset_' + i$1, type: 'USHORT', value: segment.offset});
32075        if (segment.glyphId !== undefined) {
32076            glyphIds = glyphIds.concat({name: 'glyph_' + i$1, type: 'USHORT', value: segment.glyphId});
32077        }
32078    }
32079
32080    t.fields = t.fields.concat(endCounts);
32081    t.fields.push({name: 'reservedPad', type: 'USHORT', value: 0});
32082    t.fields = t.fields.concat(startCounts);
32083    t.fields = t.fields.concat(idDeltas);
32084    t.fields = t.fields.concat(idRangeOffsets);
32085    t.fields = t.fields.concat(glyphIds);
32086
32087    t.length = 14 + // Subtable header
32088        endCounts.length * 2 +
32089        2 + // reservedPad
32090        startCounts.length * 2 +
32091        idDeltas.length * 2 +
32092        idRangeOffsets.length * 2 +
32093        glyphIds.length * 2;
32094
32095    return t;
32096}
32097
32098var cmap = { parse: parseCmapTable, make: makeCmapTable };
32099
32100// Glyph encoding
32101
32102var cffStandardStrings = [
32103    '.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', 'ampersand', 'quoteright',
32104    'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two',
32105    'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater',
32106    'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
32107    'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore',
32108    'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
32109    'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', 'exclamdown', 'cent', 'sterling',
32110    'fraction', 'yen', 'florin', 'section', 'currency', 'quotesingle', 'quotedblleft', 'guillemotleft',
32111    'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'endash', 'dagger', 'daggerdbl', 'periodcentered', 'paragraph',
32112    'bullet', 'quotesinglbase', 'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis', 'perthousand',
32113    'questiondown', 'grave', 'acute', 'circumflex', 'tilde', 'macron', 'breve', 'dotaccent', 'dieresis', 'ring',
32114    'cedilla', 'hungarumlaut', 'ogonek', 'caron', 'emdash', 'AE', 'ordfeminine', 'Lslash', 'Oslash', 'OE',
32115    'ordmasculine', 'ae', 'dotlessi', 'lslash', 'oslash', 'oe', 'germandbls', 'onesuperior', 'logicalnot', 'mu',
32116    'trademark', 'Eth', 'onehalf', 'plusminus', 'Thorn', 'onequarter', 'divide', 'brokenbar', 'degree', 'thorn',
32117    'threequarters', 'twosuperior', 'registered', 'minus', 'eth', 'multiply', 'threesuperior', 'copyright',
32118    'Aacute', 'Acircumflex', 'Adieresis', 'Agrave', 'Aring', 'Atilde', 'Ccedilla', 'Eacute', 'Ecircumflex',
32119    'Edieresis', 'Egrave', 'Iacute', 'Icircumflex', 'Idieresis', 'Igrave', 'Ntilde', 'Oacute', 'Ocircumflex',
32120    'Odieresis', 'Ograve', 'Otilde', 'Scaron', 'Uacute', 'Ucircumflex', 'Udieresis', 'Ugrave', 'Yacute',
32121    'Ydieresis', 'Zcaron', 'aacute', 'acircumflex', 'adieresis', 'agrave', 'aring', 'atilde', 'ccedilla', 'eacute',
32122    'ecircumflex', 'edieresis', 'egrave', 'iacute', 'icircumflex', 'idieresis', 'igrave', 'ntilde', 'oacute',
32123    'ocircumflex', 'odieresis', 'ograve', 'otilde', 'scaron', 'uacute', 'ucircumflex', 'udieresis', 'ugrave',
32124    'yacute', 'ydieresis', 'zcaron', 'exclamsmall', 'Hungarumlautsmall', 'dollaroldstyle', 'dollarsuperior',
32125    'ampersandsmall', 'Acutesmall', 'parenleftsuperior', 'parenrightsuperior', '266 ff', 'onedotenleader',
32126    'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle',
32127    'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'commasuperior', 'threequartersemdash', 'periodsuperior',
32128    'questionsmall', 'asuperior', 'bsuperior', 'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior',
32129    'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior', 'tsuperior', 'ff', 'ffi', 'ffl',
32130    'parenleftinferior', 'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', 'Asmall',
32131    'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall',
32132    'Msmall', 'Nsmall', 'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall',
32133    'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', 'Tildesmall', 'exclamdownsmall',
32134    'centoldstyle', 'Lslashsmall', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', 'Brevesmall', 'Caronsmall',
32135    'Dotaccentsmall', 'Macronsmall', 'figuredash', 'hypheninferior', 'Ogoneksmall', 'Ringsmall', 'Cedillasmall',
32136    'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths', 'seveneighths', 'onethird', 'twothirds',
32137    'zerosuperior', 'foursuperior', 'fivesuperior', 'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior',
32138    'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior',
32139    'seveninferior', 'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior', 'periodinferior',
32140    'commainferior', 'Agravesmall', 'Aacutesmall', 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall',
32141    'Aringsmall', 'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall', 'Ecircumflexsmall', 'Edieresissmall',
32142    'Igravesmall', 'Iacutesmall', 'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall', 'Ogravesmall',
32143    'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall', 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall',
32144    'Uacutesmall', 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall', 'Ydieresissmall', '001.000',
32145    '001.001', '001.002', '001.003', 'Black', 'Bold', 'Book', 'Light', 'Medium', 'Regular', 'Roman', 'Semibold'];
32146
32147var cffStandardEncoding = [
32148    '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
32149    '', '', '', '', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', 'ampersand', 'quoteright',
32150    'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two',
32151    'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater',
32152    'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
32153    'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore',
32154    'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
32155    'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', '', '', '', '', '', '', '', '',
32156    '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
32157    'exclamdown', 'cent', 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency', 'quotesingle',
32158    'quotedblleft', 'guillemotleft', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', '', 'endash', 'dagger',
32159    'daggerdbl', 'periodcentered', '', 'paragraph', 'bullet', 'quotesinglbase', 'quotedblbase', 'quotedblright',
32160    'guillemotright', 'ellipsis', 'perthousand', '', 'questiondown', '', 'grave', 'acute', 'circumflex', 'tilde',
32161    'macron', 'breve', 'dotaccent', 'dieresis', '', 'ring', 'cedilla', '', 'hungarumlaut', 'ogonek', 'caron',
32162    'emdash', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'AE', '', 'ordfeminine', '', '', '',
32163    '', 'Lslash', 'Oslash', 'OE', 'ordmasculine', '', '', '', '', '', 'ae', '', '', '', 'dotlessi', '', '',
32164    'lslash', 'oslash', 'oe', 'germandbls'];
32165
32166var cffExpertEncoding = [
32167    '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
32168    '', '', '', '', 'space', 'exclamsmall', 'Hungarumlautsmall', '', 'dollaroldstyle', 'dollarsuperior',
32169    'ampersandsmall', 'Acutesmall', 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader', 'onedotenleader',
32170    'comma', 'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle',
32171    'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'colon',
32172    'semicolon', 'commasuperior', 'threequartersemdash', 'periodsuperior', 'questionsmall', '', 'asuperior',
32173    'bsuperior', 'centsuperior', 'dsuperior', 'esuperior', '', '', 'isuperior', '', '', 'lsuperior', 'msuperior',
32174    'nsuperior', 'osuperior', '', '', 'rsuperior', 'ssuperior', 'tsuperior', '', 'ff', 'fi', 'fl', 'ffi', 'ffl',
32175    'parenleftinferior', '', 'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', 'Asmall',
32176    'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall',
32177    'Msmall', 'Nsmall', 'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall',
32178    'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', 'Tildesmall', '', '', '', '', '', '', '',
32179    '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
32180    'exclamdownsmall', 'centoldstyle', 'Lslashsmall', '', '', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall',
32181    'Brevesmall', 'Caronsmall', '', 'Dotaccentsmall', '', '', 'Macronsmall', '', '', 'figuredash', 'hypheninferior',
32182    '', '', 'Ogoneksmall', 'Ringsmall', 'Cedillasmall', '', '', '', 'onequarter', 'onehalf', 'threequarters',
32183    'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths', 'seveneighths', 'onethird', 'twothirds', '',
32184    '', 'zerosuperior', 'onesuperior', 'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior',
32185    'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior', 'zeroinferior', 'oneinferior', 'twoinferior',
32186    'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior', 'eightinferior',
32187    'nineinferior', 'centinferior', 'dollarinferior', 'periodinferior', 'commainferior', 'Agravesmall',
32188    'Aacutesmall', 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall', 'Aringsmall', 'AEsmall', 'Ccedillasmall',
32189    'Egravesmall', 'Eacutesmall', 'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall',
32190    'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall', 'Ogravesmall', 'Oacutesmall',
32191    'Ocircumflexsmall', 'Otildesmall', 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall',
32192    'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall', 'Ydieresissmall'];
32193
32194var standardNames = [
32195    '.notdef', '.null', 'nonmarkingreturn', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent',
32196    'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash',
32197    'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less',
32198    'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
32199    'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright',
32200    'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
32201    'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde',
32202    'Adieresis', 'Aring', 'Ccedilla', 'Eacute', 'Ntilde', 'Odieresis', 'Udieresis', 'aacute', 'agrave',
32203    'acircumflex', 'adieresis', 'atilde', 'aring', 'ccedilla', 'eacute', 'egrave', 'ecircumflex', 'edieresis',
32204    'iacute', 'igrave', 'icircumflex', 'idieresis', 'ntilde', 'oacute', 'ograve', 'ocircumflex', 'odieresis',
32205    'otilde', 'uacute', 'ugrave', 'ucircumflex', 'udieresis', 'dagger', 'degree', 'cent', 'sterling', 'section',
32206    'bullet', 'paragraph', 'germandbls', 'registered', 'copyright', 'trademark', 'acute', 'dieresis', 'notequal',
32207    'AE', 'Oslash', 'infinity', 'plusminus', 'lessequal', 'greaterequal', 'yen', 'mu', 'partialdiff', 'summation',
32208    'product', 'pi', 'integral', 'ordfeminine', 'ordmasculine', 'Omega', 'ae', 'oslash', 'questiondown',
32209    'exclamdown', 'logicalnot', 'radical', 'florin', 'approxequal', 'Delta', 'guillemotleft', 'guillemotright',
32210    'ellipsis', 'nonbreakingspace', 'Agrave', 'Atilde', 'Otilde', 'OE', 'oe', 'endash', 'emdash', 'quotedblleft',
32211    'quotedblright', 'quoteleft', 'quoteright', 'divide', 'lozenge', 'ydieresis', 'Ydieresis', 'fraction',
32212    'currency', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'daggerdbl', 'periodce
32212ntered', 'quotesinglbase',
32213    'quotedblbase', 'perthousand', 'Acircumflex', 'Ecircumflex', 'Aacute', 'Edieresis', 'Egrave', 'Iacute',
32214    'Icircumflex', 'Idieresis', 'Igrave', 'Oacute', 'Ocircumflex', 'apple', 'Ograve', 'Uacute', 'Ucircumflex',
32215    'Ugrave', 'dotlessi', 'circumflex', 'tilde', 'macron', 'breve', 'dotaccent', 'ring', 'cedilla', 'hungarumlaut',
32216    'ogonek', 'caron', 'Lslash', 'lslash', 'Scaron', 'scaron', 'Zcaron', 'zcaron', 'brokenbar', 'Eth', 'eth',
32217    'Yacute', 'yacute', 'Thorn', 'thorn', 'minus', 'multiply', 'onesuperior', 'twosuperior', 'threesuperior',
32218    'onehalf', 'onequarter', 'threequarters', 'franc', 'Gbreve', 'gbreve', 'Idotaccent', 'Scedilla', 'scedilla',
32219    'Cacute', 'cacute', 'Ccaron', 'ccaron', 'dcroat'];
32220
32221/**
32222 * This is the encoding used for fonts created from scratch.
32223 * It loops through all glyphs and finds the appropriate unicode value.
32224 * Since it's linear time, other encodings will be faster.
32225 * @exports opentype.DefaultEncoding
32226 * @class
32227 * @constructor
32228 * @param {opentype.Font}
32229 */
32230function DefaultEncoding(font) {
32231    this.font = font;
32232}
32233
32234DefaultEncoding.prototype.charToGlyphIndex = function(c) {
32235    var code = c.charCodeAt(0);
32236    var glyphs = this.font.glyphs;
32237    if (glyphs) {
32238        for (var i = 0; i < glyphs.length; i += 1) {
32239            var glyph = glyphs.get(i);
32240            for (var j = 0; j < glyph.unicodes.length; j += 1) {
32241                if (glyph.unicodes[j] === code) {
32242                    return i;
32243                }
32244            }
32245        }
32246    }
32247    return null;
32248};
32249
32250/**
32251 * @exports opentype.CmapEncoding
32252 * @class
32253 * @constructor
32254 * @param {Object} cmap - a object with the cmap encoded data
32255 */
32256function CmapEncoding(cmap) {
32257    this.cmap = cmap;
32258}
32259
32260/**
32261 * @param  {string} c - the character
32262 * @return {number} The glyph index.
32263 */
32264CmapEncoding.prototype.charToGlyphIndex = function(c) {
32265    return this.cmap.glyphIndexMap[c.charCodeAt(0)] || 0;
32266};
32267
32268/**
32269 * @exports opentype.CffEncoding
32270 * @class
32271 * @constructor
32272 * @param {string} encoding - The encoding
32273 * @param {Array} charset - The character set.
32274 */
32275function CffEncoding(encoding, charset) {
32276    this.encoding = encoding;
32277    this.charset = charset;
32278}
32279
32280/**
32281 * @param  {string} s - The character
32282 * @return {number} The index.
32283 */
32284CffEncoding.prototype.charToGlyphIndex = function(s) {
32285    var code = s.charCodeAt(0);
32286    var charName = this.encoding[code];
32287    return this.charset.indexOf(charName);
32288};
32289
32290/**
32291 * @exports opentype.GlyphNames
32292 * @class
32293 * @constructor
32294 * @param {Object} post
32295 */
32296function GlyphNames(post) {
32297    var this$1 = this;
32298
32299    switch (post.version) {
32300        case 1:
32301            this.names = standardNames.slice();
32302            break;
32303        case 2:
32304            this.names = new Array(post.numberOfGlyphs);
32305            for (var i = 0; i < post.numberOfGlyphs; i++) {
32306                if (post.glyphNameIndex[i] < standardNames.length) {
32307                    this$1.names[i] = standardNames[post.glyphNameIndex[i]];
32308                } else {
32309                    this$1.names[i] = post.names[post.glyphNameIndex[i] - standardNames.length];
32310                }
32311            }
32312
32313            break;
32314        case 2.5:
32315            this.names = new Array(post.numberOfGlyphs);
32316            for (var i$1 = 0; i$1 < post.numberOfGlyphs; i$1++) {
32317                this$1.names[i$1] = standardNames[i$1 + post.glyphNameIndex[i$1]];
32318            }
32319
32320            break;
32321        case 3:
32322            this.names = [];
32323            break;
32324        default:
32325            this.names = [];
32326            break;
32327    }
32328}
32329
32330/**
32331 * Gets the index of a glyph by name.
32332 * @param  {string} name - The glyph name
32333 * @return {number} The index
32334 */
32335GlyphNames.prototype.nameToGlyphIndex = function(name) {
32336    return this.names.indexOf(name);
32337};
32338
32339/**
32340 * @param  {number} gid
32341 * @return {string}
32342 */
32343GlyphNames.prototype.glyphIndexToName = function(gid) {
32344    return this.names[gid];
32345};
32346
32347/**
32348 * @alias opentype.addGlyphNames
32349 * @param {opentype.Font}
32350 */
32351function addGlyphNames(font) {
32352    var glyph;
32353    var glyphIndexMap = font.tables.cmap.glyphIndexMap;
32354    var charCodes = Object.keys(glyphIndexMap);
32355
32356    for (var i = 0; i < charCodes.length; i += 1) {
32357        var c = charCodes[i];
32358        var glyphIndex = glyphIndexMap[c];
32359        glyph = font.glyphs.get(glyphIndex);
32360        glyph.addUnicode(parseInt(c));
32361    }
32362
32363    for (var i$1 = 0; i$1 < font.glyphs.length; i$1 += 1) {
vendor: 11,569 bytes, lines 32364-32696
32364        glyph = font.glyphs.get(i$1);
32365        if (font.cffEncoding) {
32366            if (font.isCIDFont) {
32367                glyph.name = 'gid' + i$1;
32368            } else {
32369                glyph.name = font.cffEncoding.charset[i$1];
32370            }
32371        } else if (font.glyphNames.names) {
32372            glyph.name = font.glyphNames.glyphIndexToName(i$1);
32373        }
32374    }
32375}
32376
32377// Drawing utility functions.
32378
32379// Draw a line on the given context from point `x1,y1` to point `x2,y2`.
32380function line(ctx, x1, y1, x2, y2) {
32381    ctx.beginPath();
32382    ctx.moveTo(x1, y1);
32383    ctx.lineTo(x2, y2);
32384    ctx.stroke();
32385}
32386
32387var draw = { line: line };
32388
32389// The `glyf` table describes the glyphs in TrueType outline format.
32390// http://www.microsoft.com/typography/otspec/glyf.htm
32391
32392// Parse the coordinate data for a glyph.
32393function parseGlyphCoordinate(p, flag, previousValue, shortVectorBitMask, sameBitMask) {
32394    var v;
32395    if ((flag & shortVectorBitMask) > 0) {
32396        // The coordinate is 1 byte long.
32397        v = p.parseByte();
32398        // The `same` bit is re-used for short values to signify the sign of the value.
32399        if ((flag & sameBitMask) === 0) {
32400            v = -v;
32401        }
32402
32403        v = previousValue + v;
32404    } else {
32405        //  The coordinate is 2 bytes long.
32406        // If the `same` bit is set, the coordinate is the same as the previous coordinate.
32407        if ((flag & sameBitMask) > 0) {
32408            v = previousValue;
32409        } else {
32410            // Parse the coordinate as a signed 16-bit delta value.
32411            v = previousValue + p.parseShort();
32412        }
32413    }
32414
32415    return v;
32416}
32417
32418// Parse a TrueType glyph.
32419function parseGlyph(glyph, data, start) {
32420    var p = new parse.Parser(data, start);
32421    glyph.numberOfContours = p.parseShort();
32422    glyph._xMin = p.parseShort();
32423    glyph._yMin = p.parseShort();
32424    glyph._xMax = p.parseShort();
32425    glyph._yMax = p.parseShort();
32426    var flags;
32427    var flag;
32428
32429    if (glyph.numberOfContours > 0) {
32430        // This glyph is not a composite.
32431        var endPointIndices = glyph.endPointIndices = [];
32432        for (var i = 0; i < glyph.numberOfContours; i += 1) {
32433            endPointIndices.push(p.parseUShort());
32434        }
32435
32436        glyph.instructionLength = p.parseUShort();
32437        glyph.instructions = [];
32438        for (var i$1 = 0; i$1 < glyph.instructionLength; i$1 += 1) {
32439            glyph.instructions.push(p.parseByte());
32440        }
32441
32442        var numberOfCoordinates = endPointIndices[endPointIndices.length - 1] + 1;
32443        flags = [];
32444        for (var i$2 = 0; i$2 < numberOfCoordinates; i$2 += 1) {
32445            flag = p.parseByte();
32446            flags.push(flag);
32447            // If bit 3 is set, we repeat this flag n times, where n is the next byte.
32448            if ((flag & 8) > 0) {
32449                var repeatCount = p.parseByte();
32450                for (var j = 0; j < repeatCount; j += 1) {
32451                    flags.push(flag);
32452                    i$2 += 1;
32453                }
32454            }
32455        }
32456
32457        check.argument(flags.length === numberOfCoordinates, 'Bad flags.');
32458
32459        if (endPointIndices.length > 0) {
32460            var points = [];
32461            var point;
32462            // X/Y coordinates are relative to the previous point, except for the first point which is relative to 0,0.
32463            if (numberOfCoordinates > 0) {
32464                for (var i$3 = 0; i$3 < numberOfCoordinates; i$3 += 1) {
32465                    flag = flags[i$3];
32466                    point = {};
32467                    point.onCurve = !!(flag & 1);
32468                    point.lastPointOfContour = endPointIndices.indexOf(i$3) >= 0;
32469                    points.push(point);
32470                }
32471
32472                var px = 0;
32473                for (var i$4 = 0; i$4 < numberOfCoordinates; i$4 += 1) {
32474                    flag = flags[i$4];
32475                    point = points[i$4];
32476                    point.x = parseGlyphCoordinate(p, flag, px, 2, 16);
32477                    px = point.x;
32478                }
32479
32480                var py = 0;
32481                for (var i$5 = 0; i$5 < numberOfCoordinates; i$5 += 1) {
32482                    flag = flags[i$5];
32483                    point = points[i$5];
32484                    point.y = parseGlyphCoordinate(p, flag, py, 4, 32);
32485                    py = point.y;
32486                }
32487            }
32488
32489            glyph.points = points;
32490        } else {
32491            glyph.points = [];
32492        }
32493    } else if (glyph.numberOfContours === 0) {
32494        glyph.points = [];
32495    } else {
32496        glyph.isComposite = true;
32497        glyph.points = [];
32498        glyph.components = [];
32499        var moreComponents = true;
32500        while (moreComponents) {
32501            flags = p.parseUShort();
32502            var component = {
32503                glyphIndex: p.parseUShort(),
32504                xScale: 1,
32505                scale01: 0,
32506                scale10: 0,
32507                yScale: 1,
32508                dx: 0,
32509                dy: 0
32510            };
32511            if ((flags & 1) > 0) {
32512                // The arguments are words
32513                if ((flags & 2) > 0) {
32514                    // values are offset
32515                    component.dx = p.parseShort();
32516                    component.dy = p.parseShort();
32517                } else {
32518                    // values are matched points
32519                    component.matchedPoints = [p.parseUShort(), p.parseUShort()];
32520                }
32521
32522            } else {
32523                // The arguments are bytes
32524                if ((flags & 2) > 0) {
32525                    // values are offset
32526                    component.dx = p.parseChar();
32527                    component.dy = p.parseChar();
32528                } else {
32529                    // values are matched points
32530                    component.matchedPoints = [p.parseByte(), p.parseByte()];
32531                }
32532            }
32533
32534            if ((flags & 8) > 0) {
32535                // We have a scale
32536                component.xScale = component.yScale = p.parseF2Dot14();
32537            } else if ((flags & 64) > 0) {
32538                // We have an X / Y scale
32539                component.xScale = p.parseF2Dot14();
32540                component.yScale = p.parseF2Dot14();
32541            } else if ((flags & 128) > 0) {
32542                // We have a 2x2 transformation
32543                component.xScale = p.parseF2Dot14();
32544                component.scale01 = p.parseF2Dot14();
32545                component.scale10 = p.parseF2Dot14();
32546                component.yScale = p.parseF2Dot14();
32547            }
32548
32549            glyph.components.push(component);
32550            moreComponents = !!(flags & 32);
32551        }
32552        if (flags & 0x100) {
32553            // We have instructions
32554            glyph.instructionLength = p.parseUShort();
32555            glyph.instructions = [];
32556            for (var i$6 = 0; i$6 < glyph.instructionLength; i$6 += 1) {
32557                glyph.instructions.push(p.parseByte());
32558            }
32559        }
32560    }
32561}
32562
32563// Transform an array of points and return a new array.
32564function transformPoints(points, transform) {
32565    var newPoints = [];
32566    for (var i = 0; i < points.length; i += 1) {
32567        var pt = points[i];
32568        var newPt = {
32569            x: transform.xScale * pt.x + transform.scale01 * pt.y + transform.dx,
32570            y: transform.scale10 * pt.x + transform.yScale * pt.y + transform.dy,
32571            onCurve: pt.onCurve,
32572            lastPointOfContour: pt.lastPointOfContour
32573        };
32574        newPoints.push(newPt);
32575    }
32576
32577    return newPoints;
32578}
32579
32580function getContours(points) {
32581    var contours = [];
32582    var currentContour = [];
32583    for (var i = 0; i < points.length; i += 1) {
32584        var pt = points[i];
32585        currentContour.push(pt);
32586        if (pt.lastPointOfContour) {
32587            contours.push(currentContour);
32588            currentContour = [];
32589        }
32590    }
32591
32592    check.argument(currentContour.length === 0, 'There are still points left in the current contour.');
32593    return contours;
32594}
32595
32596// Convert the TrueType glyph outline to a Path.
32597function getPath(points) {
32598    var p = new Path();
32599    if (!points) {
32600        return p;
32601    }
32602
32603    var contours = getContours(points);
32604
32605    for (var contourIndex = 0; contourIndex < contours.length; ++contourIndex) {
32606        var contour = contours[contourIndex];
32607
32608        var prev = null;
32609        var curr = contour[contour.length - 1];
32610        var next = contour[0];
32611
32612        if (curr.onCurve) {
32613            p.moveTo(curr.x, curr.y);
32614        } else {
32615            if (next.onCurve) {
32616                p.moveTo(next.x, next.y);
32617            } else {
32618                // If both first and last points are off-curve, start at their middle.
32619                var start = {x: (curr.x + next.x) * 0.5, y: (curr.y + next.y) * 0.5};
32620                p.moveTo(start.x, start.y);
32621            }
32622        }
32623
32624        for (var i = 0; i < contour.length; ++i) {
32625            prev = curr;
32626            curr = next;
32627            next = contour[(i + 1) % contour.length];
32628
32629            if (curr.onCurve) {
32630                // This is a straight line.
32631                p.lineTo(curr.x, curr.y);
32632            } else {
32633                var prev2 = prev;
32634                var next2 = next;
32635
32636                if (!prev.onCurve) {
32637                    prev2 = { x: (curr.x + prev.x) * 0.5, y: (curr.y + prev.y) * 0.5 };
32638                    p.lineTo(prev2.x, prev2.y);
32639                }
32640
32641                if (!next.onCurve) {
32642                    next2 = { x: (curr.x + next.x) * 0.5, y: (curr.y + next.y) * 0.5 };
32643                }
32644
32645                p.lineTo(prev2.x, prev2.y);
32646                p.quadraticCurveTo(curr.x, curr.y, next2.x, next2.y);
32647            }
32648        }
32649
32650        p.closePath();
32651    }
32652    return p;
32653}
32654
32655function buildPath(glyphs, glyph) {
32656    if (glyph.isComposite) {
32657        for (var j = 0; j < glyph.components.length; j += 1) {
32658            var component = glyph.components[j];
32659            var componentGlyph = glyphs.get(component.glyphIndex);
32660            // Force the ttfGlyphLoader to parse the glyph.
32661            componentGlyph.getPath();
32662            if (componentGlyph.points) {
32663                var transformedPoints = (void 0);
32664                if (component.matchedPoints === undefined) {
32665                    // component positioned by offset
32666                    transformedPoints = transformPoints(componentGlyph.points, component);
32667                } else {
32668                    // component positioned by matched points
32669                    if ((component.matchedPoints[0] > glyph.points.length - 1) ||
32670                        (component.matchedPoints[1] > componentGlyph.points.length - 1)) {
32671                        throw Error('Matched points out of range in ' + glyph.name);
32672                    }
32673                    var firstPt = glyph.points[component.matchedPoints[0]];
32674                    var secondPt = componentGlyph.points[component.matchedPoints[1]];
32675                    var transform = {
32676                        xScale: component.xScale, scale01: component.scale01,
32677                        scale10: component.scale10, yScale: component.yScale,
32678                        dx: 0, dy: 0
32679                    };
32680                    secondPt = transformPoints([secondPt], transform)[0];
32681                    transform.dx = firstPt.x - secondPt.x;
32682                    transform.dy = firstPt.y - secondPt.y;
32683                    transformedPoints = transformPoints(componentGlyph.points, transform);
32684                }
32685                glyph.points = glyph.points.concat(transformedPoints);
32686            }
32687        }
32688    }
32689
32690    return getPath(glyph.points);
32691}
32692
32693// Parse all the glyphs according to the offsets from the `loca` table.
32694function parseGlyfTable(data, start, loca, font) {
32695    var glyphs = new glyphset.GlyphSet(font);
32696
32697    // The last element of the loca table is invalid.
32698    for (var i = 0; i < loca.length - 1; i += 1) {
32699        var offset = loca[i];
32700        var nextOffset = loca[i + 1];
32701        if (offset !== nextOffset) {
32702            glyphs.push(i, glyphset.ttfGlyphLoader(font, i, parseGlyph, data, start + offset, buildPath));
32703        } else {
32704            glyphs.push(i, glyphset.glyphLoader(font, i));
32705        }
32706    }
32707
32708    return glyphs;
32709}
32710
32711var glyf = { getPath: getPath, parse: parseGlyfTable };
32712
32713// The Glyph object
32714
32715function getPathDefinition(glyph, path) {
32716    var _path = path || {commands: []};
32717    return {
32718        configurable: true,
32719
32720        get: function() {
32721            if (typeof _path === 'function') {
32722                _path = _path();
32723            }
32724
32725            return _path;
32726        },
32727
32728        set: function(p) {
32729            _path = p;
32730        }
32731    };
32732}
32733/**
32734 * @typedef GlyphOptions
32735 * @type Object
32736 * @property {string} [name] - The glyph name
32737 * @property {number} [unicode]
32738 * @property {Array} [unicodes]
32739 * @property {number} [xMin]
32740 * @property {number} [yMin]
32741 * @property {number} [xMax]
32742 * @property {number} [yMax]
32743 * @property {number} [advanceWidth]
32744 */
32745
32746// A Glyph is an individual mark that often corresponds to a character.
32747// Some glyphs, such as ligatures, are a combination of many characters.
32748// Glyphs are the basic building blocks of a font.
32749//
32750// The `Glyph` class contains utility methods for drawing the path and its points.
32751/**
32752 * @exports opentype.Glyph
32753 * @class
32754 * @param {GlyphOptions}
32755 * @constructor
32756 */
32757function Glyph(options) {
32758    // By putting all the code on a prototype function (which is only declared once)
32759    // we reduce the memory requirements for larger fonts by some 2%
32760    this.bindConstructorValues(options);
32761}
32762
32763/**
32764 * @param  {GlyphOptions}
32765 */
32766Glyph.prototype.bindConstructorValues = function(options) {
32767    this.index = options.index || 0;
32768
32769    // These three values cannot be deferred for memory optimization:
32770    this.name = options.name || null;
32771    this.unicode = options.unicode || undefined;
32772    this.unicodes = options.unicodes || options.unicode !== undefined ? [options.unicode] : [];
32773
32774    // But by binding these values only when necessary, we reduce can
32775    // the memory requirements by almost 3% for larger fonts.
32776    if (options.xMin) {
32777        this.xMin = options.xMin;
32778    }
32779
32780    if (options.yMin) {
32781        this.yMin = options.yMin;
32782    }
32783
32784    if (options.xMax) {
32785        this.xMax = options.xMax;
32786    }
32787
32788    if (options.yMax) {
32789        this.yMax = options.yMax;
32790    }
32791
32792    if (options.advanceWidth) {
32793        this.advanceWidth = options.advanceWidth;
32794    }
32795
32796    // The path for a glyph is the most memory intensive, and is bound as a value
32797    // with a getter/setter to ensure we actually do path parsing only once the
32798    // path is actually needed by anything.
32799    Object.defineProperty(this, 'path', getPathDefinition(this, options.path));
32800};
32801
32802/**
32803 * @param {number}
32804 */
32805Glyph.prototype.addUnicode = function(unicode) {
32806    if (this.unicodes.length === 0) {
32807        this.unicode = unicode;
32808    }
32809
32810    this.unicodes.push(unicode);
32811};
32812
32813/**
32814 * Calculate the minimum bounding box for this glyph.
32815 * @return {opentype.BoundingBox}
32816 */
32817Glyph.prototype.getBoundingBox = function() {
32818    return this.path.getBoundingBox();
32819};
32820
32821/**
32822 * Convert the glyph to a Path we can draw on a drawing context.
32823 * @param  {number} [x=0] - Horizontal position of the beginning of the text.
32824 * @param  {number} [y=0] - Vertical position of the *baseline* of the text.
32825 * @param  {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`.
32826 * @param  {Object=} options - xScale, yScale to stretch the glyph.
32827 * @param  {opentype.Font} if hinting is to be used, the font
32828 * @return {opentype.Path}
32829 */
32830Glyph.prototype.getPath = function(x, y, fontSize, options, font) {
32831    x = x !== undefined ? x : 0;
32832    y = y !== undefined ? y : 0;
32833    fontSize = fontSize !== undefined ? fontSize : 72;
32834    var commands;
32835    var hPoints;
32836    if (!options) { options = { }; }
32837    var xScale = options.xScale;
32838    var yScale = options.yScale;
32839
32840    if (options.hinting && font && font.hinting) {
32841        // in case of hinting, the hinting engine takes care
32842        // of scaling the points (not the path) before hinting.
32843        hPoints = this.path && font.hinting.exec(this, fontSize);
32844        // in case the hinting engine failed hPoints is undefined
32845        // and thus reverts to plain rending
32846    }
32847
32848    if (hPoints) {
32849        commands = glyf.getPath(hPoints).commands;
32850        x = Math.round(x);
32851        y = Math.round(y);
32852        // TODO in case of hinting xyScaling is not yet supported
32853        xScale = yScale = 1;
32854    } else {
32855        commands = this.path.commands;
32856        var scale = 1 / this.path.unitsPerEm * fontSize;
32857        if (xScale === undefined) { xScale = scale; }
32858        if (yScale === undefined) { yScale = scale; }
32859    }
32860
32861    var p = new Path();
32862    for (var i = 0; i < commands.length; i += 1) {
32863        var cmd = commands[i];
32864        if (cmd.type === 'M') {
32865            p.moveTo(x + (cmd.x * xScale), y + (-cmd.y * yScale));
32866        } else if (cmd.type === 'L') {
32867            p.lineTo(x + (cmd.x * xScale), y + (-cmd.y * yScale));
32868        } else if (cmd.type === 'Q') {
32869            p.quadraticCurveTo(x + (cmd.x1 * xScale), y + (-cmd.y1 * yScale),
32870                               x + (cmd.x * xScale), y + (-cmd.y * yScale));
32871        } else if (cmd.type === 'C') {
32872            p.curveTo(x + (cmd.x1 * xScale), y + (-cmd.y1 * yScale),
32873                      x + (cmd.x2 * xScale), y + (-cmd.y2 * yScale),
32874                      x + (cmd.x * xScale), y + (-cmd.y * yScale));
32875        } else if (cmd.type === 'Z') {
32876            p.closePath();
32877        }
32878    }
32879
32880    return p;
32881};
32882
32883/**
32884 * Split the glyph into contours.
32885 * This function is here for backwards compatibility, and to
32886 * provide raw access to the TrueType glyph outlines.
32887 * @return {Array}
32888 */
32889Glyph.prototype.getContours = function() {
32890    var this$1 = this;
32891
32892    if (this.points === undefined) {
32893        return [];
32894    }
32895
32896    var contours = [];
32897    var currentContour = [];
32898    for (var i = 0; i < this.points.length; i += 1) {
32899        var pt = this$1.points[i];
32900        currentContour.push(pt);
32901        if (pt.lastPointOfContour) {
32902            contours.push(currentContour);
32903            currentContour = [];
32904        }
32905    }
32906
32907    check.argument(currentContour.length === 0, 'There are still points left in the current contour.');
32908    return contours;
32909};
32910
32911/**
32912 * Calculate the xMin/yMin/xMax/yMax/lsb/rsb for a Glyph.
32913 * @return {Object}
32914 */
32915Glyph.prototype.getMetrics = function() {
32916    var commands = this.path.commands;
32917    var xCoords = [];
32918    var yCoords = [];
32919    for (var i = 0; i < commands.length; i += 1) {
32920        var cmd = commands[i];
32921        if (cmd.type !== 'Z') {
32922            xCoords.push(cmd.x);
32923            yCoords.push(cmd.y);
32924        }
32925
32926        if (cmd.type === 'Q' || cmd.type === 'C') {
32927            xCoords.push(cmd.x1);
32928            yCoords.push(cmd.y1);
32929        }
32930
32931        if (cmd.type === 'C') {
32932            xCoords.push(cmd.x2);
32933            yCoords.push(cmd.y2);
32934        }
32935    }
32936
32937    var metrics = {
32938        xMin: Math.min.apply(null, xCoords),
32939        yMin: Math.min.apply(null, yCoords),
32940        xMax: Math.max.apply(null, xCoords),
32941        yMax: Math.max.apply(null, yCoords),
32942        leftSideBearing: this.leftSideBearing
32943    };
32944
32945    if (!isFinite(metrics.xMin)) {
32946        metrics.xMin = 0;
32947    }
32948
32949    if (!isFinite(metrics.xMax)) {
32950        metrics.xMax = this.advanceWidth;
32951    }
32952
32953    if (!isFinite(metrics.yMin)) {
32954        metrics.yMin = 0;
32955    }
32956
32957    if (!isFinite(metrics.yMax)) {
32958        metrics.yMax = 0;
32959    }
32960
32961    metrics.rightSideBearing = this.advanceWidth - metrics.leftSideBearing - (metrics.xMax - metrics.xMin);
32962    return metrics;
32963};
32964
32965/**
32966 * Draw the glyph on the given context.
32967 * @param  {CanvasRenderingContext2D} ctx - A 2D drawing context, like Canvas.
32968 * @param  {number} [x=0] - Horizontal position of the beginning of the text.
32969 * @param  {number} [y=0] - Vertical position of the *baseline* of the text.
32970 * @param  {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`.
32971 * @param  {Object=} options - xScale, yScale to stretch the glyph.
32972 */
32973Glyph.prototype.draw = function(ctx, x, y, fontSize, options) {
32974    this.getPath(x, y, fontSize, options).draw(ctx);
32975};
32976
32977/**
32978 * Draw the points of the glyph.
32979 * On-curve points will be drawn in blue, off-curve points will be drawn in red.
32980 * @param  {CanvasRenderingContext2D} ctx - A 2D drawing context, like Canvas.
32981 * @param  {number} [x=0] - Horizontal position of the beginning of the text.
32982 * @param  {number} [y=0] - Vertical position of the *baseline* of the text.
32983 * @param  {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`.
32984 */
32985Glyph.prototype.drawPoints = function(ctx, x, y, fontSize) {
32986    function drawCircles(l, x, y, scale) {
32987        var PI_SQ = Math.PI * 2;
32988        ctx.beginPath();
32989        for (var j = 0; j < l.length; j += 1) {
32990            ctx.moveTo(x + (l[j].x * scale), y + (l[j].y * scale));
32991            ctx.arc(x + (l[j].x * scale), y + (l[j].y * scale), 2, 0, PI_SQ, false);
32992        }
32993
32994        ctx.closePath();
32995        ctx.fill();
32996    }
32997
32998    x = x !== undefined ? x : 0;
32999    y = y !== undefined ? y : 0;
33000    fontSize = fontSize !== undefined ? fontSize : 24;
33001    var scale = 1 / this.path.unitsPerEm * fontSize;
33002
33003    var blueCircles = [];
33004    var redCircles = [];
33005    var path = this.path;
33006    for (var i = 0; i < path.commands.length; i += 1) {
33007        var cmd = path.commands[i];
33008        if (cmd.x !== undefined) {
33009            blueCircles.push({x: cmd.x, y: -cmd.y});
33010        }
33011
33012        if (cmd.x1 !== undefined) {
33013            redCircles.push({x: cmd.x1, y: -cmd.y1});
33014        }
33015
33016        if (cmd.x2 !== undefined) {
33017            redCircles.push({x: cmd.x2, y: -cmd.y2});
33018        }
33019    }
33020
33021    ctx.fillStyle = 'blue';
33022    drawCircles(blueCircles, x, y, scale);
33023    ctx.fillStyle = 'red';
33024    drawCircles(redCircles, x, y, scale);
33025};
33026
33027/**
33028 * Draw lines indicating important font measurements.
33029 * Black lines indicate the origin of the coordinate system (point 0,0).
33030 * Blue lines indicate the glyph bounding box.
33031 * Green line indicates the advance width of the glyph.
33032 * @param  {CanvasRenderingContext2D} ctx - A 2D drawing context, like Canvas.
33033 * @param  {number} [x=0] - Horizontal position of the beginning of the text.
33034 * @param  {number} [y=0] - Vertical position of the *baseline* of the text.
33035 * @param  {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`.
33036 */
33037Glyph.prototype.drawMetrics = function(ctx, x, y, fontSize) {
33038    var scale;
33039    x = x !== undefined ? x : 0;
33040    y = y !== undefined ? y : 0;
33041    fontSize = fontSize !== undefined ? fontSize : 24;
33042    scale = 1 / this.path.unitsPerEm * fontSize;
33043    ctx.lineWidth = 1;
33044
33045    // Draw the origin
33046    ctx.strokeStyle = 'black';
33047    draw.line(ctx, x, -10000, x, 10000);
33048    draw.line(ctx, -10000, y, 10000, y);
33049
33050    // This code is here due to memory optimization: by not using
33051    // defaults in the constructor, we save a notable amount of memory.
33052    var xMin = this.xMin || 0;
33053    var yMin = this.yMin || 0;
33054    var xMax = this.xMax || 0;
33055    var yMax = this.yMax || 0;
33056    var advanceWidth = this.advanceWidth || 0;
33057
33058    // Draw the glyph box
33059    ctx.strokeStyle = 'blue';
33060    draw.line(ctx, x + (xMin * scale), -10000, x + (xMin * scale), 10000);
33061    draw.line(ctx, x + (xMax * scale), -10000, x + (xMax * scale), 10000);
33062    draw.line(ctx, -10000, y + (-yMin * scale), 10000, y + (-yMin * scale));
33063    draw.line(ctx, -10000, y + (-yMax * scale), 10000, y + (-yMax * scale));
33064
33065    // Draw the advance width
33066    ctx.strokeStyle = 'green';
33067    draw.line(ctx, x + (advanceWidth * scale), -10000, x + (advanceWidth * scale), 10000);
33068};
33069
33070// The GlyphSet object
33071
33072// Define a property on the glyph that depends on the path being loaded.
33073function defineDependentProperty(glyph, externalName, internalName) {
33074    Object.defineProperty(glyph, externalName, {
33075        get: function() {
33076            // Request the path property to make sure the path is loaded.
33077            glyph.path; // jshint ignore:line
33078            return glyph[internalName];
33079        },
33080        set: function(newValue) {
33081            glyph[internalName] = newValue;
33082        },
33083        enumerable: true,
33084        configurable: true
33085    });
33086}
33087
33088/**
33089 * A GlyphSet represents all glyphs available in the font, but modelled using
33090 * a deferred glyph loader, for retrieving glyphs only once they are absolutely
33091 * necessary, to keep the memory footprint down.
33092 * @exports opentype.GlyphSet
33093 * @class
33094 * @param {opentype.Font}
33095 * @param {Array}
33096 */
33097function GlyphSet(font, glyphs) {
33098    var this$1 = this;
33099
33100    this.font = font;
33101    this.glyphs = {};
33102    if (Array.isArray(glyphs)) {
33103        for (var i = 0; i < glyphs.length; i++) {
33104            this$1.glyphs[i] = glyphs[i];
33105        }
33106    }
33107
33108    this.length = (glyphs && glyphs.length) || 0;
33109}
33110
33111/**
33112 * @param  {number} index
33113 * @return {opentype.Glyph}
33114 */
33115GlyphSet.prototype.get = function(index) {
33116    if (typeof this.glyphs[index] === 'function') {
33117        this.glyphs[index] = this.glyphs[index]();
33118    }
33119
33120    return this.glyphs[index];
33121};
33122
33123/**
33124 * @param  {number} index
33125 * @param  {Object}
33126 */
33127GlyphSet.prototype.push = function(index, loader) {
33128    this.glyphs[index] = loader;
33129    this.length++;
33130};
33131
33132/**
33133 * @alias opentype.glyphLoader
33134 * @param  {opentype.Font} font
33135 * @param  {number} index
33136 * @return {opentype.Glyph}
33137 */
33138function glyphLoader(font, index) {
33139    return new Glyph({index: index, font: font});
33140}
33141
33142/**
33143 * Generate a stub glyph that can be filled with all metadata *except*
33144 * the "points" and "path" properties, which must be loaded only once
33145 * the glyph's path is actually requested for text shaping.
33146 * @alias opentype.ttfGlyphLoader
33147 * @param  {opentype.Font} font
33148 * @param  {number} index
33149 * @param  {Function} parseGlyph
33150 * @param  {Object} data
33151 * @param  {number} position
33152 * @param  {Function} buildPath
33153 * @return {opentype.Glyph}
33154 */
33155function ttfGlyphLoader(font, index, parseGlyph, data, position, buildPath) {
33156    return function() {
33157        var glyph = new Glyph({index: index, font: font});
33158
33159        glyph.path = function() {
33160            parseGlyph(glyph, data, position);
33161            var path = buildPath(font.glyphs, glyph);
33162            path.unitsPerEm = font.unitsPerEm;
33163            return path;
33164        };
33165
33166        defineDependentProperty(glyph, 'xMin', '_xMin');
33167        defineDependentProperty(glyph, 'xMax', '_xMax');
33168        defineDependentProperty(glyph, 'yMin', '_yMin');
33169        defineDependentProperty(glyph, 'yMax', '_yMax');
33170
33171        return glyph;
33172    };
33173}
33174/**
33175 * @alias opentype.cffGlyphLoader
33176 * @param  {opentype.Font} font
33177 * @param  {number} index
33178 * @param  {Function} parseCFFCharstring
33179 * @param  {string} charstring
33180 * @return {opentype.Glyph}
33181 */
33182function cffGlyphLoader(font, index, parseCFFCharstring, charstring) {
33183    return function() {
33184        var glyph = new Glyph({index: index, font: font});
33185
33186        glyph.path = function() {
33187            var path = parseCFFCharstring(font, glyph, charstring);
33188            path.unitsPerEm = font.unitsPerEm;
33189            return path;
33190        };
33191
33192        return glyph;
33193    };
33194}
33195
33196var glyphset = { GlyphSet: GlyphSet, glyphLoader: glyphLoader, ttfGlyphLoader: ttfGlyphLoader, cffGlyphLoader: cffGlyphLoader };
33197
33198// The `CFF` table contains the glyph outlines in PostScript format.
33199// https://www.microsoft.com/typography/OTSPEC/cff.htm
33200// http://download.microsoft.com/download/8/0/1/801a191c-029d-4af3-9642-555f6fe514ee/cff.pdf
33201// http://download.microsoft.com/download/8/0/1/801a191c-029d-4af3-9642-555f6fe514ee/type2.pdf
33202
33203// Custom equals function that can also check lists.
33204function equals(a, b) {
33205    if (a === b) {
33206        return true;
33207    } else if (Array.isArray(a) && Array.isArray(b)) {
33208        if (a.length !== b.length) {
33209            return false;
33210        }
33211
33212        for (var i = 0; i < a.length; i += 1) {
33213            if (!equals(a[i], b[i])) {
33214                return false;
vendor: 33,020 bytes, lines 33215-34113
33215            }
33216        }
33217
33218        return true;
33219    } else {
33220        return false;
33221    }
33222}
33223
33224// Subroutines are encoded using the negative half of the number space.
33225// See type 2 chapter 4.7 "Subroutine operators".
33226function calcCFFSubroutineBias(subrs) {
33227    var bias;
33228    if (subrs.length < 1240) {
33229        bias = 107;
33230    } else if (subrs.length < 33900) {
33231        bias = 1131;
33232    } else {
33233        bias = 32768;
33234    }
33235
33236    return bias;
33237}
33238
33239// Parse a `CFF` INDEX array.
33240// An index array consists of a list of offsets, then a list of objects at those offsets.
33241function parseCFFIndex(data, start, conversionFn) {
33242    var offsets = [];
33243    var objects = [];
33244    var count = parse.getCard16(data, start);
33245    var objectOffset;
33246    var endOffset;
33247    if (count !== 0) {
33248        var offsetSize = parse.getByte(data, start + 2);
33249        objectOffset = start + ((count + 1) * offsetSize) + 2;
33250        var pos = start + 3;
33251        for (var i = 0; i < count + 1; i += 1) {
33252            offsets.push(parse.getOffset(data, pos, offsetSize));
33253            pos += offsetSize;
33254        }
33255
33256        // The total size of the index array is 4 header bytes + the value of the last offset.
33257        endOffset = objectOffset + offsets[count];
33258    } else {
33259        endOffset = start + 2;
33260    }
33261
33262    for (var i$1 = 0; i$1 < offsets.length - 1; i$1 += 1) {
33263        var value = parse.getBytes(data, objectOffset + offsets[i$1], objectOffset + offsets[i$1 + 1]);
33264        if (conversionFn) {
33265            value = conversionFn(value);
33266        }
33267
33268        objects.push(value);
33269    }
33270
33271    return {objects: objects, startOffset: start, endOffset: endOffset};
33272}
33273
33274// Parse a `CFF` DICT real value.
33275function parseFloatOperand(parser) {
33276    var s = '';
33277    var eof = 15;
33278    var lookup = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', 'E', 'E-', null, '-'];
33279    while (true) {
33280        var b = parser.parseByte();
33281        var n1 = b >> 4;
33282        var n2 = b & 15;
33283
33284        if (n1 === eof) {
33285            break;
33286        }
33287
33288        s += lookup[n1];
33289
33290        if (n2 === eof) {
33291            break;
33292        }
33293
33294        s += lookup[n2];
33295    }
33296
33297    return parseFloat(s);
33298}
33299
33300// Parse a `CFF` DICT operand.
33301function parseOperand(parser, b0) {
33302    var b1;
33303    var b2;
33304    var b3;
33305    var b4;
33306    if (b0 === 28) {
33307        b1 = parser.parseByte();
33308        b2 = parser.parseByte();
33309        return b1 << 8 | b2;
33310    }
33311
33312    if (b0 === 29) {
33313        b1 = parser.parseByte();
33314        b2 = parser.parseByte();
33315        b3 = parser.parseByte();
33316        b4 = parser.parseByte();
33317        return b1 << 24 | b2 << 16 | b3 << 8 | b4;
33318    }
33319
33320    if (b0 === 30) {
33321        return parseFloatOperand(parser);
33322    }
33323
33324    if (b0 >= 32 && b0 <= 246) {
33325        return b0 - 139;
33326    }
33327
33328    if (b0 >= 247 && b0 <= 250) {
33329        b1 = parser.parseByte();
33330        return (b0 - 247) * 256 + b1 + 108;
33331    }
33332
33333    if (b0 >= 251 && b0 <= 254) {
33334        b1 = parser.parseByte();
33335        return -(b0 - 251) * 256 - b1 - 108;
33336    }
33337
33338    throw new Error('Invalid b0 ' + b0);
33339}
33340
33341// Convert the entries returned by `parseDict` to a proper dictionary.
33342// If a value is a list of one, it is unpacked.
33343function entriesToObject(entries) {
33344    var o = {};
33345    for (var i = 0; i < entries.length; i += 1) {
33346        var key = entries[i][0];
33347        var values = entries[i][1];
33348        var value = (void 0);
33349        if (values.length === 1) {
33350            value = values[0];
33351        } else {
33352            value = values;
33353        }
33354
33355        if (o.hasOwnProperty(key) && !isNaN(o[key])) {
33356            throw new Error('Object ' + o + ' already has key ' + key);
33357        }
33358
33359        o[key] = value;
33360    }
33361
33362    return o;
33363}
33364
33365// Parse a `CFF` DICT object.
33366// A dictionary contains key-value pairs in a compact tokenized format.
33367function parseCFFDict(data, start, size) {
33368    start = start !== undefined ? start : 0;
33369    var parser = new parse.Parser(data, start);
33370    var entries = [];
33371    var operands = [];
33372    size = size !== undefined ? size : data.length;
33373
33374    while (parser.relativeOffset < size) {
33375        var op = parser.parseByte();
33376
33377        // The first byte for each dict item distinguishes between operator (key) and operand (value).
33378        // Values <= 21 are operators.
33379        if (op <= 21) {
33380            // Two-byte operators have an initial escape byte of 12.
33381            if (op === 12) {
33382                op = 1200 + parser.parseByte();
33383            }
33384
33385            entries.push([op, operands]);
33386            operands = [];
33387        } else {
33388            // Since the operands (values) come before the operators (keys), we store all operands in a list
33389            // until we encounter an operator.
33390            operands.push(parseOperand(parser, op));
33391        }
33392    }
33393
33394    return entriesToObject(entries);
33395}
33396
33397// Given a String Index (SID), return the value of the string.
33398// Strings below index 392 are standard CFF strings and are not encoded in the font.
33399function getCFFString(strings, index) {
33400    if (index <= 390) {
33401        index = cffStandardStrings[index];
33402    } else {
33403        index = strings[index - 391];
33404    }
33405
33406    return index;
33407}
33408
33409// Interpret a dictionary and return a new dictionary with readable keys and values for missing entries.
33410// This function takes `meta` which is a list of objects containing `operand`, `name` and `default`.
33411function interpretDict(dict, meta, strings) {
33412    var newDict = {};
33413    var value;
33414
33415    // Because we also want to include missing values, we start out from the meta list
33416    // and lookup values in the dict.
33417    for (var i = 0; i < meta.length; i += 1) {
33418        var m = meta[i];
33419
33420        if (Array.isArray(m.type)) {
33421            var values = [];
33422            values.length = m.type.length;
33423            for (var j = 0; j < m.type.length; j++) {
33424                value = dict[m.op] !== undefined ? dict[m.op][j] : undefined;
33425                if (value === undefined) {
33426                    value = m.value !== undefined && m.value[j] !== undefined ? m.value[j] : null;
33427                }
33428                if (m.type[j] === 'SID') {
33429                    value = getCFFString(strings, value);
33430                }
33431                values[j] = value;
33432            }
33433            newDict[m.name] = values;
33434        } else {
33435            value = dict[m.op];
33436            if (value === undefined) {
33437                value = m.value !== undefined ? m.value : null;
33438            }
33439
33440            if (m.type === 'SID') {
33441                value = getCFFString(strings, value);
33442            }
33443            newDict[m.name] = value;
33444        }
33445    }
33446
33447    return newDict;
33448}
33449
33450// Parse the CFF header.
33451function parseCFFHeader(data, start) {
33452    var header = {};
33453    header.formatMajor = parse.getCard8(data, start);
33454    header.formatMinor = parse.getCard8(data, start + 1);
33455    header.size = parse.getCard8(data, start + 2);
33456    header.offsetSize = parse.getCard8(data, start + 3);
33457    header.startOffset = start;
33458    header.endOffset = start + 4;
33459    return header;
33460}
33461
33462var TOP_DICT_META = [
33463    {name: 'version', op: 0, type: 'SID'},
33464    {name: 'notice', op: 1, type: 'SID'},
33465    {name: 'copyright', op: 1200, type: 'SID'},
33466    {name: 'fullName', op: 2, type: 'SID'},
33467    {name: 'familyName', op: 3, type: 'SID'},
33468    {name: 'weight', op: 4, type: 'SID'},
33469    {name: 'isFixedPitch', op: 1201, type: 'number', value: 0},
33470    {name: 'italicAngle', op: 1202, type: 'number', value: 0},
33471    {name: 'underlinePosition', op: 1203, type: 'number', value: -100},
33472    {name: 'underlineThickness', op: 1204, type: 'number', value: 50},
33473    {name: 'paintType', op: 1205, type: 'number', value: 0},
33474    {name: 'charstringType', op: 1206, type: 'number', value: 2},
33475    {
33476        name: 'fontMatrix',
33477        op: 1207,
33478        type: ['real', 'real', 'real', 'real', 'real', 'real'],
33479        value: [0.001, 0, 0, 0.001, 0, 0]
33480    },
33481    {name: 'uniqueId', op: 13, type: 'number'},
33482    {name: 'fontBBox', op: 5, type: ['number', 'number', 'number', 'number'], value: [0, 0, 0, 0]},
33483    {name: 'strokeWidth', op: 1208, type: 'number', value: 0},
33484    {name: 'xuid', op: 14, type: [], value: null},
33485    {name: 'charset', op: 15, type: 'offset', value: 0},
33486    {name: 'encoding', op: 16, type: 'offset', value: 0},
33487    {name: 'charStrings', op: 17, type: 'offset', value: 0},
33488    {name: 'private', op: 18, type: ['number', 'offset'], value: [0, 0]},
33489    {name: 'ros', op: 1230, type: ['SID', 'SID', 'number']},
33490    {name: 'cidFontVersion', op: 1231, type: 'number', value: 0},
33491    {name: 'cidFontRevision', op: 1232, type: 'number', value: 0},
33492    {name: 'cidFontType', op: 1233, type: 'number', value: 0},
33493    {name: 'cidCount', op: 1234, type: 'number', value: 8720},
33494    {name: 'uidBase', op: 1235, type: 'number'},
33495    {name: 'fdArray', op: 1236, type: 'offset'},
33496    {name: 'fdSelect', op: 1237, type: 'offset'},
33497    {name: 'fontName', op: 1238, type: 'SID'}
33498];
33499
33500var PRIVATE_DICT_META = [
33501    {name: 'subrs', op: 19, type: 'offset', value: 0},
33502    {name: 'defaultWidthX', op: 20, type: 'number', value: 0},
33503    {name: 'nominalWidthX', op: 21, type: 'number', value: 0}
33504];
33505
33506// Parse the CFF top dictionary. A CFF table can contain multiple fonts, each with their own top dictionary.
33507// The top dictionary contains the essential metadata for the font, together with the private dictionary.
33508function parseCFFTopDict(data, strings) {
33509    var dict = parseCFFDict(data, 0, data.byteLength);
33510    return interpretDict(dict, TOP_DICT_META, strings);
33511}
33512
33513// Parse the CFF private dictionary. We don't fully parse out all the values, only the ones we need.
33514function parseCFFPrivateDict(data, start, size, strings) {
33515    var dict = parseCFFDict(data, start, size);
33516    return interpretDict(dict, PRIVATE_DICT_META, strings);
33517}
33518
33519// Returns a list of "Top DICT"s found using an INDEX list.
33520// Used to read both the usual high-level Top DICTs and also the FDArray
33521// discovered inside CID-keyed fonts.  When a Top DICT has a reference to
33522// a Private DICT that is read and saved into the Top DICT.
33523//
33524// In addition to the expected/optional values as outlined in TOP_DICT_META
33525// the following values might be saved into the Top DICT.
33526//
33527//    _subrs []        array of local CFF subroutines from Private DICT
33528//    _subrsBias       bias value computed from number of subroutines
33529//                      (see calcCFFSubroutineBias() and parseCFFCharstring())
33530//    _defaultWidthX   default widths for CFF characters
33531//    _nominalWidthX   bias added to width embedded within glyph description
33532//
33533//    _privateDict     saved copy of parsed Private DICT from Top DICT
33534function gatherCFFTopDicts(data, start, cffIndex, strings) {
33535    var topDictArray = [];
33536    for (var iTopDict = 0; iTopDict < cffIndex.length; iTopDict += 1) {
33537        var topDictData = new DataView(new Uint8Array(cffIndex[iTopDict]).buffer);
33538        var topDict = parseCFFTopDict(topDictData, strings);
33539        topDict._subrs = [];
33540        topDict._subrsBias = 0;
33541        var privateSize = topDict.private[0];
33542        var privateOffset = topDict.private[1];
33543        if (privateSize !== 0 && privateOffset !== 0) {
33544            var privateDict = parseCFFPrivateDict(data, privateOffset + start, privateSize, strings);
33545            topDict._defaultWidthX = privateDict.defaultWidthX;
33546            topDict._nominalWidthX = privateDict.nominalWidthX;
33547            if (privateDict.subrs !== 0) {
33548                var subrOffset = privateOffset + privateDict.subrs;
33549                var subrIndex = parseCFFIndex(data, subrOffset + start);
33550                topDict._subrs = subrIndex.objects;
33551                topDict._subrsBias = calcCFFSubroutineBias(topDict._subrs);
33552            }
33553            topDict._privateDict = privateDict;
33554        }
33555        topDictArray.push(topDict);
33556    }
33557    return topDictArray;
33558}
33559
33560// Parse the CFF charset table, which contains internal names for all the glyphs.
33561// This function will return a list of glyph names.
33562// See Adobe TN #5176 chapter 13, "Charsets".
33563function parseCFFCharset(data, start, nGlyphs, strings) {
33564    var sid;
33565    var count;
33566    var parser = new parse.Parser(data, start);
33567
33568    // The .notdef glyph is not included, so subtract 1.
33569    nGlyphs -= 1;
33570    var charset = ['.notdef'];
33571
33572    var format = parser.parseCard8();
33573    if (format === 0) {
33574        for (var i = 0; i < nGlyphs; i += 1) {
33575            sid = parser.parseSID();
33576            charset.push(getCFFString(strings, sid));
33577        }
33578    } else if (format === 1) {
33579        while (charset.length <= nGlyphs) {
33580            sid = parser.parseSID();
33581            count = parser.parseCard8();
33582            for (var i$1 = 0; i$1 <= count; i$1 += 1) {
33583                charset.push(getCFFString(strings, sid));
33584                sid += 1;
33585            }
33586        }
33587    } else if (format === 2) {
33588        while (charset.length <= nGlyphs) {
33589            sid = parser.parseSID();
33590            count = parser.parseCard16();
33591            for (var i$2 = 0; i$2 <= count; i$2 += 1) {
33592                charset.push(getCFFString(strings, sid));
33593                sid += 1;
33594            }
33595        }
33596    } else {
33597        throw new Error('Unknown charset format ' + format);
33598    }
33599
33600    return charset;
33601}
33602
33603// Parse the CFF encoding data. Only one encoding can be specified per font.
33604// See Adobe TN #5176 chapter 12, "Encodings".
33605function parseCFFEncoding(data, start, charset) {
33606    var code;
33607    var enc = {};
33608    var parser = new parse.Parser(data, start);
33609    var format = parser.parseCard8();
33610    if (format === 0) {
33611        var nCodes = parser.parseCard8();
33612        for (var i = 0; i < nCodes; i += 1) {
33613            code = parser.parseCard8();
33614            enc[code] = i;
33615        }
33616    } else if (format === 1) {
33617        var nRanges = parser.parseCard8();
33618        code = 1;
33619        for (var i$1 = 0; i$1 < nRanges; i$1 += 1) {
33620            var first = parser.parseCard8();
33621            var nLeft = parser.parseCard8();
33622            for (var j = first; j <= first + nLeft; j += 1) {
33623                enc[j] = code;
33624                code += 1;
33625            }
33626        }
33627    } else {
33628        throw new Error('Unknown encoding format ' + format);
33629    }
33630
33631    return new CffEncoding(enc, charset);
33632}
33633
33634// Take in charstring code and return a Glyph object.
33635// The encoding is described in the Type 2 Charstring Format
33636// https://www.microsoft.com/typography/OTSPEC/charstr2.htm
33637function parseCFFCharstring(font, glyph, code) {
33638    var c1x;
33639    var c1y;
33640    var c2x;
33641    var c2y;
33642    var p = new Path();
33643    var stack = [];
33644    var nStems = 0;
33645    var haveWidth = false;
33646    var open = false;
33647    var x = 0;
33648    var y = 0;
33649    var subrs;
33650    var subrsBias;
33651    var defaultWidthX;
33652    var nominalWidthX;
33653    if (font.isCIDFont) {
33654        var fdIndex = font.tables.cff.topDict._fdSelect[glyph.index];
33655        var fdDict = font.tables.cff.topDict._fdArray[fdIndex];
33656        subrs = fdDict._subrs;
33657        subrsBias = fdDict._subrsBias;
33658        defaultWidthX = fdDict._defaultWidthX;
33659        nominalWidthX = fdDict._nominalWidthX;
33660    } else {
33661        subrs = font.tables.cff.topDict._subrs;
33662        subrsBias = font.tables.cff.topDict._subrsBias;
33663        defaultWidthX = font.tables.cff.topDict._defaultWidthX;
33664        nominalWidthX = font.tables.cff.topDict._nominalWidthX;
33665    }
33666    var width = defaultWidthX;
33667
33668    function newContour(x, y) {
33669        if (open) {
33670            p.closePath();
33671        }
33672
33673        p.moveTo(x, y);
33674        open = true;
33675    }
33676
33677    function parseStems() {
33678        var hasWidthArg;
33679
33680        // The number of stem operators on the stack is always even.
33681        // If the value is uneven, that means a width is specified.
33682        hasWidthArg = stack.length % 2 !== 0;
33683        if (hasWidthArg && !haveWidth) {
33684            width = stack.shift() + nominalWidthX;
33685        }
33686
33687        nStems += stack.length >> 1;
33688        stack.length = 0;
33689        haveWidth = true;
33690    }
33691
33692    function parse$$1(code) {
33693        var b1;
33694        var b2;
33695        var b3;
33696        var b4;
33697        var codeIndex;
33698        var subrCode;
33699        var jpx;
33700        var jpy;
33701        var c3x;
33702        var c3y;
33703        var c4x;
33704        var c4y;
33705
33706        var i = 0;
33707        while (i < code.length) {
33708            var v = code[i];
33709            i += 1;
33710            switch (v) {
33711                case 1: // hstem
33712                    parseStems();
33713                    break;
33714                case 3: // vstem
33715                    parseStems();
33716                    break;
33717                case 4: // vmoveto
33718                    if (stack.length > 1 && !haveWidth) {
33719                        width = stack.shift() + nominalWidthX;
33720                        haveWidth = true;
33721                    }
33722
33723                    y += stack.pop();
33724                    newContour(x, y);
33725                    break;
33726                case 5: // rlineto
33727                    while (stack.length > 0) {
33728                        x += stack.shift();
33729                        y += stack.shift();
33730                        p.lineTo(x, y);
33731                    }
33732
33733                    break;
33734                case 6: // hlineto
33735                    while (stack.length > 0) {
33736                        x += stack.shift();
33737                        p.lineTo(x, y);
33738                        if (stack.length === 0) {
33739                            break;
33740                        }
33741
33742                        y += stack.shift();
33743                        p.lineTo(x, y);
33744                    }
33745
33746                    break;
33747                case 7: // vlineto
33748                    while (stack.length > 0) {
33749                        y += stack.shift();
33750                        p.lineTo(x, y);
33751                        if (stack.length === 0) {
33752                            break;
33753                        }
33754
33755                        x += stack.shift();
33756                        p.lineTo(x, y);
33757                    }
33758
33759                    break;
33760                case 8: // rrcurveto
33761                    while (stack.length > 0) {
33762                        c1x = x + stack.shift();
33763                        c1y = y + stack.shift();
33764                        c2x = c1x + stack.shift();
33765                        c2y = c1y + stack.shift();
33766                        x = c2x + stack.shift();
33767                        y = c2y + stack.shift();
33768                        p.curveTo(c1x, c1y, c2x, c2y, x, y);
33769                    }
33770
33771                    break;
33772                case 10: // callsubr
33773                    codeIndex = stack.pop() + subrsBias;
33774                    subrCode = subrs[codeIndex];
33775                    if (subrCode) {
33776                        parse$$1(subrCode);
33777                    }
33778
33779                    break;
33780                case 11: // return
33781                    return;
33782                case 12: // flex operators
33783                    v = code[i];
33784                    i += 1;
33785                    switch (v) {
33786                        case 35: // flex
33787                            // |- dx1 dy1 dx2 dy2 dx3 dy3 dx4 dy4 dx5 dy5 dx6 dy6 fd flex (12 35) |-
33788                            c1x = x   + stack.shift();    // dx1
33789                            c1y = y   + stack.shift();    // dy1
33790                            c2x = c1x + stack.shift();    // dx2
33791                            c2y = c1y + stack.shift();    // dy2
33792                            jpx = c2x + stack.shift();    // dx3
33793                            jpy = c2y + stack.shift();    // dy3
33794                            c3x = jpx + stack.shift();    // dx4
33795                            c3y = jpy + stack.shift();    // dy4
33796                            c4x = c3x + stack.shift();    // dx5
33797                            c4y = c3y + stack.shift();    // dy5
33798                            x = c4x   + stack.shift();    // dx6
33799                            y = c4y   + stack.shift();    // dy6
33800                            stack.shift();                // flex depth
33801                            p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);
33802                            p.curveTo(c3x, c3y, c4x, c4y, x, y);
33803                            break;
33804                        case 34: // hflex
33805                            // |- dx1 dx2 dy2 dx3 dx4 dx5 dx6 hflex (12 34) |-
33806                            c1x = x   + stack.shift();    // dx1
33807                            c1y = y;                      // dy1
33808                            c2x = c1x + stack.shift();    // dx2
33809                            c2y = c1y + stack.shift();    // dy2
33810                            jpx = c2x + stack.shift();    // dx3
33811                            jpy = c2y;                    // dy3
33812                            c3x = jpx + stack.shift();    // dx4
33813                            c3y = c2y;                    // dy4
33814                            c4x = c3x + stack.shift();    // dx5
33815                            c4y = y;                      // dy5
33816                            x = c4x + stack.shift();      // dx6
33817                            p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);
33818                            p.curveTo(c3x, c3y, c4x, c4y, x, y);
33819                            break;
33820                        case 36: // hflex1
33821                            // |- dx1 dy1 dx2 dy2 dx3 dx4 dx5 dy5 dx6 hflex1 (12 36) |-
33822                            c1x = x   + stack.shift();    // dx1
33823                            c1y = y   + stack.shift();    // dy1
33824                            c2x = c1x + stack.shift();    // dx2
33825                            c2y = c1y + stack.shift();    // dy2
33826                            jpx = c2x + stack.shift();    // dx3
33827                            jpy = c2y;                    // dy3
33828                            c3x = jpx + stack.shift();    // dx4
33829                            c3y = c2y;                    // dy4
33830                            c4x = c3x + stack.shift();    // dx5
33831                            c4y = c3y + stack.shift();    // dy5
33832                            x = c4x + stack.shift();      // dx6
33833                            p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);
33834                            p.curveTo(c3x, c3y, c4x, c4y, x, y);
33835                            break;
33836                        case 37: // flex1
33837                            // |- dx1 dy1 dx2 dy2 dx3 dy3 dx4 dy4 dx5 dy5 d6 flex1 (12 37) |-
33838                            c1x = x   + stack.shift();    // dx1
33839                            c1y = y   + stack.shift();    // dy1
33840                            c2x = c1x + stack.shift();    // dx2
33841                            c2y = c1y + stack.shift();    // dy2
33842                            jpx = c2x + stack.shift();    // dx3
33843                            jpy = c2y + stack.shift();    // dy3
33844                            c3x = jpx + stack.shift();    // dx4
33845                            c3y = jpy + stack.shift();    // dy4
33846                            c4x = c3x + stack.shift();    // dx5
33847                            c4y = c3y + stack.shift();    // dy5
33848                            if (Math.abs(c4x - x) > Math.abs(c4y - y)) {
33849                                x = c4x + stack.shift();
33850                            } else {
33851                                y = c4y + stack.shift();
33852                            }
33853
33854                            p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);
33855                            p.curveTo(c3x, c3y, c4x, c4y, x, y);
33856                            break;
33857                        default:
33858                            console.log('Glyph ' + glyph.index + ': unknown operator ' + 1200 + v);
33859                            stack.length = 0;
33860                    }
33861                    break;
33862                case 14: // endchar
33863                    if (stack.length > 0 && !haveWidth) {
33864                        width = stack.shift() + nominalWidthX;
33865                        haveWidth = true;
33866                    }
33867
33868                    if (open) {
33869                        p.closePath();
33870                        open = false;
33871                    }
33872
33873                    break;
33874                case 18: // hstemhm
33875                    parseStems();
33876                    break;
33877                case 19: // hintmask
33878                case 20: // cntrmask
33879                    parseStems();
33880                    i += (nStems + 7) >> 3;
33881                    break;
33882                case 21: // rmoveto
33883                    if (stack.length > 2 && !haveWidth) {
33884                        width = stack.shift() + nominalWidthX;
33885                        haveWidth = true;
33886                    }
33887
33888                    y += stack.pop();
33889                    x += stack.pop();
33890                    newContour(x, y);
33891                    break;
33892                case 22: // hmoveto
33893                    if (stack.length > 1 && !haveWidth) {
33894                        width = stack.shift() + nominalWidthX;
33895                        haveWidth = true;
33896                    }
33897
33898                    x += stack.pop();
33899                    newContour(x, y);
33900                    break;
33901                case 23: // vstemhm
33902                    parseStems();
33903                    break;
33904                case 24: // rcurveline
33905                    while (stack.length > 2) {
33906                        c1x = x + stack.shift();
33907                        c1y = y + stack.shift();
33908                        c2x = c1x + stack.shift();
33909                        c2y = c1y + stack.shift();
33910                        x = c2x + stack.shift();
33911                        y = c2y + stack.shift();
33912                        p.curveTo(c1x, c1y, c2x, c2y, x, y);
33913                    }
33914
33915                    x += stack.shift();
33916                    y += stack.shift();
33917                    p.lineTo(x, y);
33918                    break;
33919                case 25: // rlinecurve
33920                    while (stack.length > 6) {
33921                        x += stack.shift();
33922                        y += stack.shift();
33923                        p.lineTo(x, y);
33924                    }
33925
33926                    c1x = x + stack.shift();
33927                    c1y = y + stack.shift();
33928                    c2x = c1x + stack.shift();
33929                    c2y = c1y + stack.shift();
33930                    x = c2x + stack.shift();
33931                    y = c2y + stack.shift();
33932                    p.curveTo(c1x, c1y, c2x, c2y, x, y);
33933                    break;
33934                case 26: // vvcurveto
33935                    if (stack.length % 2) {
33936                        x += stack.shift();
33937                    }
33938
33939                    while (stack.length > 0) {
33940                        c1x = x;
33941                        c1y = y + stack.shift();
33942                        c2x = c1x + stack.shift();
33943                        c2y = c1y + stack.shift();
33944                        x = c2x;
33945                        y = c2y + stack.shift();
33946                        p.curveTo(c1x, c1y, c2x, c2y, x, y);
33947                    }
33948
33949                    break;
33950                case 27: // hhcurveto
33951                    if (stack.length % 2) {
33952                        y += stack.shift();
33953                    }
33954
33955                    while (stack.length > 0) {
33956                        c1x = x + stack.shift();
33957                        c1y = y;
33958                        c2x = c1x + stack.shift();
33959                        c2y = c1y + stack.shift();
33960                        x = c2x + stack.shift();
33961                        y = c2y;
33962                        p.curveTo(c1x, c1y, c2x, c2y, x, y);
33963                    }
33964
33965                    break;
33966                case 28: // shortint
33967                    b1 = code[i];
33968                    b2 = code[i + 1];
33969                    stack.push(((b1 << 24) | (b2 << 16)) >> 16);
33970                    i += 2;
33971                    break;
33972                case 29: // callgsubr
33973                    codeIndex = stack.pop() + font.gsubrsBias;
33974                    subrCode = font.gsubrs[codeIndex];
33975                    if (subrCode) {
33976                        parse$$1(subrCode);
33977                    }
33978
33979                    break;
33980                case 30: // vhcurveto
33981                    while (stack.length > 0) {
33982                        c1x = x;
33983                        c1y = y + stack.shift();
33984                        c2x = c1x + stack.shift();
33985                        c2y = c1y + stack.shift();
33986                        x = c2x + stack.shift();
33987                        y = c2y + (stack.length === 1 ? stack.shift() : 0);
33988                        p.curveTo(c1x, c1y, c2x, c2y, x, y);
33989                        if (stack.length === 0) {
33990                            break;
33991                        }
33992
33993                        c1x = x + stack.shift();
33994                        c1y = y;
33995                        c2x = c1x + stack.shift();
33996                        c2y = c1y + stack.shift();
33997                        y = c2y + stack.shift();
33998                        x = c2x + (stack.length === 1 ? stack.shift() : 0);
33999                        p.curveTo(c1x, c1y, c2x, c2y, x, y);
34000                    }
34001
34002                    break;
34003                case 31: // hvcurveto
34004                    while (stack.length > 0) {
34005                        c1x = x + stack.shift();
34006                        c1y = y;
34007                        c2x = c1x + stack.shift();
34008                        c2y = c1y + stack.shift();
34009                        y = c2y + stack.shift();
34010                        x = c2x + (stack.length === 1 ? stack.shift() : 0);
34011                        p.curveTo(c1x, c1y, c2x, c2y, x, y);
34012                        if (stack.length === 0) {
34013                            break;
34014                        }
34015
34016                        c1x = x;
34017                        c1y = y + stack.shift();
34018                        c2x = c1x + stack.shift();
34019                        c2y = c1y + stack.shift();
34020                        x = c2x + stack.shift();
34021                        y = c2y + (stack.length === 1 ? stack.shift() : 0);
34022                        p.curveTo(c1x, c1y, c2x, c2y, x, y);
34023                    }
34024
34025                    break;
34026                default:
34027                    if (v < 32) {
34028                        console.log('Glyph ' + glyph.index + ': unknown operator ' + v);
34029                    } else if (v < 247) {
34030                        stack.push(v - 139);
34031                    } else if (v < 251) {
34032                        b1 = code[i];
34033                        i += 1;
34034                        stack.push((v - 247) * 256 + b1 + 108);
34035                    } else if (v < 255) {
34036                        b1 = code[i];
34037                        i += 1;
34038                        stack.push(-(v - 251) * 256 - b1 - 108);
34039                    } else {
34040                        b1 = code[i];
34041                        b2 = code[i + 1];
34042                        b3 = code[i + 2];
34043                        b4 = code[i + 3];
34044                        i += 4;
34045                        stack.push(((b1 << 24) | (b2 << 16) | (b3 << 8) | b4) / 65536);
34046                    }
34047            }
34048        }
34049    }
34050
34051    parse$$1(code);
34052
34053    glyph.advanceWidth = width;
34054    return p;
34055}
34056
34057function parseCFFFDSelect(data, start, nGlyphs, fdArrayCount) {
34058    var fdSelect = [];
34059    var fdIndex;
34060    var parser = new parse.Parser(data, start);
34061    var format = parser.parseCard8();
34062    if (format === 0) {
34063        // Simple list of nGlyphs elements
34064        for (var iGid = 0; iGid < nGlyphs; iGid++) {
34065            fdIndex = parser.parseCard8();
34066            if (fdIndex >= fdArrayCount) {
34067                throw new Error('CFF table CID Font FDSelect has bad FD index value ' + fdIndex + ' (FD count ' + fdArrayCount + ')');
34068            }
34069            fdSelect.push(fdIndex);
34070        }
34071    } else if (format === 3) {
34072        // Ranges
34073        var nRanges = parser.parseCard16();
34074        var first = parser.parseCard16();
34075        if (first !== 0) {
34076            throw new Error('CFF Table CID Font FDSelect format 3 range has bad initial GID ' + first);
34077        }
34078        var next;
34079        for (var iRange = 0; iRange < nRanges; iRange++) {
34080            fdIndex = parser.parseCard8();
34081            next = parser.parseCard16();
34082            if (fdIndex >= fdArrayCount) {
34083                throw new Error('CFF table CID Font FDSelect has bad FD index value ' + fdIndex + ' (FD count ' + fdArrayCount + ')');
34084            }
34085            if (next > nGlyphs) {
34086                throw new Error('CFF Table CID Font FDSelect format 3 range has bad GID ' + next);
34087            }
34088            for (; first < next; first++) {
34089                fdSelect.push(fdIndex);
34090            }
34091            first = next;
34092        }
34093        if (next !== nGlyphs) {
34094            throw new Error('CFF Table CID Font FDSelect format 3 range has bad final GID ' + next);
34095        }
34096    } else {
34097        throw new Error('CFF Table CID Font FDSelect table has unsupported format ' + format);
34098    }
34099    return fdSelect;
34100}
34101
34102// Parse the `CFF` table, which contains the glyph outlines in PostScript format.
34103function parseCFFTable(data, start, font) {
34104    font.tables.cff = {};
34105    var header = parseCFFHeader(data, start);
34106    var nameIndex = parseCFFIndex(data, header.endOffset, parse.bytesToString);
34107    var topDictIndex = parseCFFIndex(data, nameIndex.endOffset);
34108    var stringIndex = parseCFFIndex(data, topDictIndex.endOffset, parse.bytesToString);
34109    var globalSubrIndex = parseCFFIndex(data, stringIndex.endOffset);
34110    font.gsubrs = globalSubrIndex.objects;
34111    font.gsubrsBias = calcCFFSubroutineBias(font.gsubrs);
34112
34113    var topDictArray = gatherCFFTopDicts(data, start, topDictIndex.objects, str
34113ingIndex.objects);
34114    if (topDictArray.length !== 1) {
34115        throw new Error('CFF table has too many fonts in \'FontSet\' - count of fonts NameIndex.length = ' + topDictArray.length);
34116    }
34117
34118    var topDict = topDictArray[0];
34119    font.tables.cff.topDict = topDict;
34120
34121    if (topDict._privateDict) {
34122        font.defaultWidthX = topDict._privateDict.defaultWidthX;
34123        font.nominalWidthX = topDict._privateDict.nominalWidthX;
34124    }
34125
34126    if (topDict.ros[0] !== undefined && topDict.ros[1] !== undefined) {
34127        font.isCIDFont = true;
34128    }
34129
34130    if (font.isCIDFont) {
34131        var fdArrayOffset = topDict.fdArray;
34132        var fdSelectOffset = topDict.fdSelect;
34133        if (fdArrayOffset === 0 || fdSelectOffset === 0) {
34134            throw new Error('Font is marked as a CID font, but FDArray and/or FDSelect information is missing');
34135        }
34136        fdArrayOffset += start;
34137        var fdArrayIndex = parseCFFIndex(data, fdArrayOffset);
34138        var fdArray = gatherCFFTopDicts(data, start, fdArrayIndex.objects, stringIndex.objects);
34139        topDict._fdArray = fdArray;
34140        fdSelectOffset += start;
34141        topDict._fdSelect = parseCFFFDSelect(data, fdSelectOffset, font.numGlyphs, fdArray.length);
34142    }
34143
34144    var privateDictOffset = start + topDict.private[1];
34145    var privateDict = parseCFFPrivateDict(data, privateDictOffset, topDict.private[0], stringIndex.objects);
34146    font.defaultWidthX = privateDict.defaultWidthX;
34147    font.nominalWidthX = privateDict.nominalWidthX;
34148
34149    if (privateDict.subrs !== 0) {
34150        var subrOffset = privateDictOffset + privateDict.subrs;
34151        var subrIndex = parseCFFIndex(data, subrOffset);
34152        font.subrs = subrIndex.objects;
34153        font.subrsBias = calcCFFSubroutineBias(font.subrs);
34154    } else {
34155        font.subrs = [];
34156        font.subrsBias = 0;
34157    }
34158
34159    // Offsets in the top dict are relative to the beginning of the CFF data, so add the CFF start offset.
34160    var charStringsIndex = parseCFFIndex(data, start + topDict.charStrings);
34161    font.nGlyphs = charStringsIndex.objects.length;
34162
34163    var charset = parseCFFCharset(data, start + topDict.charset, font.nGlyphs, stringIndex.objects);
34164    if (topDict.encoding === 0) { // Standard encoding
34165        font.cffEncoding = new CffEncoding(cffStandardEncoding, charset);
34166    } else if (topDict.encoding === 1) { // Expert encoding
34167        font.cffEncoding = new CffEncoding(cffExpertEncoding, charset);
34168    } else {
34169        font.cffEncoding = parseCFFEncoding(data, start + topDict.encoding, charset);
34170    }
34171
34172    // Prefer the CMAP encoding to the CFF encoding.
34173    font.encoding = font.encoding || font.cffEncoding;
34174
34175    font.glyphs = new glyphset.GlyphSet(font);
34176    for (var i = 0; i < font.nGlyphs; i += 1) {
34177        var charString = charStringsIndex.objects[i];
34178        font.glyphs.push(i, glyphset.cffGlyphLoader(font, i, parseCFFCharstring, charString));
34179    }
34180}
34181
34182// Convert a string to a String ID (SID).
34183// The list of strings is modified in place.
34184function encodeString(s, strings) {
34185    var sid;
34186
34187    // Is the string in the CFF standard strings?
34188    var i = cffStandardStrings.indexOf(s);
34189    if (i >= 0) {
34190        sid = i;
34191    }
34192
34193    // Is the string already in the string index?
34194    i = strings.indexOf(s);
34195    if (i >= 0) {
34196        sid = i + cffStandardStrings.length;
34197    } else {
34198        sid = cffStandardStrings.length + strings.length;
34199        strings.push(s);
34200    }
34201
34202    return sid;
34203}
34204
34205function makeHeader() {
34206    return new table.Record('Header', [
34207        {name: 'major', type: 'Card8', value: 1},
34208        {name: 'minor', type: 'Card8', value: 0},
34209        {name: 'hdrSize', type: 'Card8', value: 4},
34210        {name: 'major', type: 'Card8', value: 1}
34211    ]);
34212}
34213
34214function makeNameIndex(fontNames) {
34215    var t = new table.Record('Name INDEX', [
34216        {name: 'names', type: 'INDEX', value: []}
34217    ]);
34218    t.names = [];
34219    for (var i = 0; i < fontNames.length; i += 1) {
34220        t.names.push({name: 'name_' + i, type: 'NAME', value: fontNames[i]});
34221    }
34222
34223    return t;
34224}
34225
34226// Given a dictionary's metadata, create a DICT structure.
34227function makeDict(meta, attrs, strings) {
34228    var m = {};
34229    for (var i = 0; i < meta.length; i += 1) {
34230        var entry = meta[i];
34231        var value = attrs[entry.name];
34232        if (value !== undefined && !equals(value, entry.value)) {
34233            if (entry.type === 'SID') {
34234                value = encodeString(value, strings);
34235            }
34236
34237            m[entry.op] = {name: entry.name, type: entry.type, value: value};
34238        }
34239    }
34240
34241    return m;
34242}
34243
34244// The Top DICT houses the global font attributes.
34245function makeTopDict(attrs, strings) {
34246    var t = new table.Record('Top DICT', [
34247        {name: 'dict', type: 'DICT', value: {}}
34248    ]);
34249    t.dict = makeDict(TOP_DICT_META, attrs, strings);
34250    return t;
34251}
34252
34253function makeTopDictIndex(topDict) {
34254    var t = new table.Record('Top DICT INDEX', [
34255        {name: 'topDicts', type: 'INDEX', value: []}
34256    ]);
34257    t.topDicts = [{name: 'topDict_0', type: 'TABLE', value: topDict}];
34258    return t;
34259}
34260
34261function makeStringIndex(strings) {
34262    var t = new table.Record('String INDEX', [
34263        {name: 'strings', type: 'INDEX', value: []}
34264    ]);
34265    t.strings = [];
34266    for (var i = 0; i < strings.length; i += 1) {
34267        t.strings.push({name: 'string_' + i, type: 'STRING', value: strings[i]});
34268    }
34269
34270    return t;
34271}
34272
34273function makeGlobalSubrIndex() {
34274    // Currently we don't use subroutines.
34275    return new table.Record('Global Subr INDEX', [
34276        {name: 'subrs', type: 'INDEX', value: []}
34277    ]);
34278}
34279
34280function makeCharsets(glyphNames, strings) {
34281    var t = new table.Record('Charsets', [
34282        {name: 'format', type: 'Card8', value: 0}
34283    ]);
34284    for (var i = 0; i < glyphNames.length; i += 1) {
34285        var glyphName = glyphNames[i];
34286        var glyphSID = encodeString(glyphName, strings);
34287        t.fields.push({name: 'glyph_' + i, type: 'SID', value: glyphSID});
34288    }
34289
34290    return t;
34291}
34292
34293function glyphToOps(glyph) {
34294    var ops = [];
34295    var path = glyph.path;
34296    ops.push({name: 'width', type: 'NUMBER', value: glyph.advanceWidth});
34297    var x = 0;
34298    var y = 0;
34299    for (var i = 0; i < path.commands.length; i += 1) {
34300        var dx = (void 0);
34301        var dy = (void 0);
34302        var cmd = path.commands[i];
34303        if (cmd.type === 'Q') {
34304            // CFF only supports bézier curves, so convert the quad to a bézier.
34305            var _13 = 1 / 3;
34306            var _23 = 2 / 3;
34307
34308            // We're going to create a new command so we don't change the original path.
34309            cmd = {
34310                type: 'C',
34311                x: cmd.x,
34312                y: cmd.y,
34313                x1: _13 * x + _23 * cmd.x1,
34314                y1: _13 * y + _23 * cmd.y1,
34315                x2: _13 * cmd.x + _23 * cmd.x1,
34316                y2: _13 * cmd.y + _23 * cmd.y1
34317            };
34318        }
34319
34320        if (cmd.type === 'M') {
34321            dx = Math.round(cmd.x - x);
34322            dy = Math.round(cmd.y - y);
34323            ops.push({name: 'dx', type: 'NUMBER', value: dx});
34324            ops.push({name: 'dy', type: 'NUMBER', value: dy});
34325            ops.push({name: 'rmoveto', type: 'OP', value: 21});
34326            x = Math.round(cmd.x);
34327            y = Math.round(cmd.y);
34328        } else if (cmd.type === 'L') {
34329            dx = Math.round(cmd.x - x);
34330            dy = Math.round(cmd.y - y);
34331            ops.push({name: 'dx', type: 'NUMBER', value: dx});
34332            ops.push({name: 'dy', type: 'NUMBER', value: dy});
34333            ops.push({name: 'rlineto', type: 'OP', value: 5});
34334            x = Math.round(cmd.x);
34335            y = Math.round(cmd.y);
34336        } else if (cmd.type === 'C') {
34337            var dx1 = Math.round(cmd.x1 - x);
34338            var dy1 = Math.round(cmd.y1 - y);
34339            var dx2 = Math.round(cmd.x2 - cmd.x1);
34340            var dy2 = Math.round(cmd.y2 - cmd.y1);
34341            dx = Math.round(cmd.x - cmd.x2);
34342            dy = Math.round(cmd.y - cmd.y2);
34343            ops.push({name: 'dx1', type: 'NUMBER', value: dx1});
34344            ops.push({name: 'dy1', type: 'NUMBER', value: dy1});
34345            ops.push({name: 'dx2', type: 'NUMBER', value: dx2});
34346            ops.push({name: 'dy2', type: 'NUMBER', value: dy2});
34347            ops.push({name: 'dx', type: 'NUMBER', value: dx});
34348            ops.push({name: 'dy', type: 'NUMBER', value: dy});
34349            ops.push({name: 'rrcurveto', type: 'OP', value: 8});
34350            x = Math.round(cmd.x);
34351            y = Math.round(cmd.y);
34352        }
34353
34354        // Contours are closed automatically.
34355    }
34356
34357    ops.push({name: 'endchar', type: 'OP', value: 14});
34358    return ops;
34359}
34360
34361function makeCharStringsIndex(glyphs) {
34362    var t = new table.Record('CharStrings INDEX', [
34363        {name: 'charStrings', type: 'INDEX', value: []}
34364    ]);
34365
34366    for (var i = 0; i < glyphs.length; i += 1) {
34367        var glyph = glyphs.get(i);
34368        var ops = glyphToOps(glyph);
34369        t.charStrings.push({name: glyph.name, type: 'CHARSTRING', value: ops});
34370    }
34371
34372    return t;
34373}
34374
34375function makePrivateDict(attrs, strings) {
34376    var t = new table.Record('Private DICT', [
34377        {name: 'dict', type: 'DICT', value: {}}
34378    ]);
34379    t.dict = makeDict(PRIVATE_DICT_META, attrs, strings);
34380    return t;
34381}
34382
34383function makeCFFTable(glyphs, options) {
34384    var t = new table.Table('CFF ', [
34385        {name: 'header', type: 'RECORD'},
34386        {name: 'nameIndex', type: 'RECORD'},
34387        {name: 'topDictIndex', type: 'RECORD'},
34388        {name: 'stringIndex', type: 'RECORD'},
34389        {name: 'globalSubrIndex', type: 'RECORD'},
34390        {name: 'charsets', type: 'RECORD'},
34391        {name: 'charStringsIndex', type: 'RECORD'},
34392        {name: 'privateDict', type: 'RECORD'}
34393    ]);
34394
34395    var fontScale = 1 / options.unitsPerEm;
34396    // We use non-zero values for the offsets so that the DICT encodes them.
34397    // This is important because the size of the Top DICT plays a role in offset calculation,
34398    // and the size shouldn't change after we've written correct offsets.
34399    var attrs = {
34400        version: options.version,
34401        fullName: options.fullName,
34402        familyName: options.familyName,
34403        weight: options.weightName,
34404        fontBBox: options.fontBBox || [0, 0, 0, 0],
34405        fontMatrix: [fontScale, 0, 0, fontScale, 0, 0],
34406        charset: 999,
34407        encoding: 0,
34408        charStrings: 999,
34409        private: [0, 999]
34410    };
34411
34412    var privateAttrs = {};
34413
34414    var glyphNames = [];
34415    var glyph;
34416
34417    // Skip first glyph (.notdef)
34418    for (var i = 1; i < glyphs.length; i += 1) {
34419        glyph = glyphs.get(i);
34420        glyphNames.push(glyph.name);
34421    }
34422
34423    var strings = [];
34424
34425    t.header = makeHeader();
34426    t.nameIndex = makeNameIndex([options.postScriptName]);
34427    var topDict = makeTopDict(attrs, strings);
34428    t.topDictIndex = makeTopDictIndex(topDict);
34429    t.globalSubrIndex = makeGlobalSubrIndex();
34430    t.charsets = makeCharsets(glyphNames, strings);
34431    t.charStringsIndex = makeCharStringsIndex(glyphs);
34432    t.privateDict = makePrivateDict(privateAttrs, strings);
34433
34434    // Needs to come at the end, to encode all custom strings used in the font.
34435    t.stringIndex = makeStringIndex(strings);
34436
34437    var startOffset = t.header.sizeOf() +
34438        t.nameIndex.sizeOf() +
34439        t.topDictIndex.sizeOf() +
34440        t.stringIndex.sizeOf() +
34441        t.globalSubrIndex.sizeOf();
34442    attrs.charset = startOffset;
34443
34444    // We use the CFF standard encoding; proper encoding will be handled in cmap.
34445    attrs.encoding = 0;
34446    attrs.charStrings = attrs.charset + t.charsets.sizeOf();
34447    attrs.private[1] = attrs.charStrings + t.charStringsIndex.sizeOf();
34448
34449    // Recreate the Top DICT INDEX with the correct offsets.
34450    topDict = makeTopDict(attrs, strings);
34451    t.topDictIndex = makeTopDictIndex(topDict);
34452
34453    return t;
34454}
34455
34456var cff = { parse: parseCFFTable, make: makeCFFTable };
34457
34458// The `head` table contains global information about the font.
34459// https://www.microsoft.com/typography/OTSPEC/head.htm
34460
34461// Parse the header `head` table
34462function parseHeadTable(data, start) {
34463    var head = {};
34464    var p = new parse.Parser(data, start);
34465    head.version = p.parseVersion();
34466    head.fontRevision = Math.round(p.parseFixed() * 1000) / 1000;
34467    head.checkSumAdjustment = p.parseULong();
34468    head.magicNumber = p.parseULong();
34469    check.argument(head.magicNumber === 0x5F0F3CF5, 'Font header has wrong magic number.');
34470    head.flags = p.parseUShort();
34471    head.unitsPerEm = p.parseUShort();
34472    head.created = p.parseLongDateTime();
34473    head.modified = p.parseLongDateTime();
34474    head.xMin = p.parseShort();
34475    head.yMin = p.parseShort();
34476    head.xMax = p.parseShort();
34477    head.yMax = p.parseShort();
34478    head.macStyle = p.parseUShort();
34479    head.lowestRecPPEM = p.parseUShort();
34480    head.fontDirectionHint = p.parseShort();
34481    head.indexToLocFormat = p.parseShort();
34482    head.glyphDataFormat = p.parseShort();
34483    return head;
34484}
34485
34486function makeHeadTable(options) {
34487    // Apple Mac timestamp epoch is 01/01/1904 not 01/01/1970
34488    var timestamp = Math.round(new Date().getTime() / 1000) + 2082844800;
34489    var createdTimestamp = timestamp;
34490
34491    if (options.createdTimestamp) {
34492        createdTimestamp = options.createdTimestamp + 2082844800;
34493    }
34494
34495    return new table.Table('head', [
34496        {name: 'version', type: 'FIXED', value: 0x00010000},
34497        {name: 'fontRevision', type: 'FIXED', value: 0x00010000},
34498        {name: 'checkSumAdjustment', type: 'ULONG', value: 0},
34499        {name: 'magicNumber', type: 'ULONG', value: 0x5F0F3CF5},
34500        {name: 'flags', type: 'USHORT', value: 0},
34501        {name: 'unitsPerEm', type: 'USHORT', value: 1000},
34502        {name: 'created', type: 'LONGDATETIME', value: createdTimestamp},
34503        {name: 'modified', type: 'LONGDATETIME', value: timestamp},
34504        {name: 'xMin', type: 'SHORT', value: 0},
34505        {name: 'yMin', type: 'SHORT', value: 0},
34506        {name: 'xMax', type: 'SHORT', value: 0},
34507        {name: 'yMax', type: 'SHORT', value: 0},
34508        {name: 'macStyle', type: 'USHORT', value: 0},
34509        {name: 'lowestRecPPEM', type: 'USHORT', value: 0},
34510        {name: 'fontDirectionHint', type: 'SHORT', value: 2},
34511        {name: 'indexToLocFormat', type: 'SHORT', value: 0},
34512        {name: 'glyphDataFormat', type: 'SHORT', value: 0}
34513    ], options);
34514}
34515
34516var head = { parse: parseHeadTable, make: makeHeadTable };
34517
34518// The `hhea` table contains information for horizontal layout.
34519// https://www.microsoft.com/typography/OTSPEC/hhea.htm
34520
34521// Parse the horizontal header `hhea` table
34522function parseHheaTable(data, start) {
34523    var hhea = {};
34524    var p = new parse.Parser(data, start);
34525    hhea.version = p.parseVersion();
34526    hhea.ascender = p.parseShort();
34527    hhea.descender = p.parseShort();
34528    hhea.lineGap = p.parseShort();
34529    hhea.advanceWidthMax = p.parseUShort();
34530    hhea.minLeftSideBearing = p.parseShort();
34531    hhea.minRightSideBearing = p.parseShort();
34532    hhea.xMaxExtent = p.parseShort();
34533    hhea.caretSlopeRise = p.parseShort();
34534    hhea.caretSlopeRun = p.parseShort();
34535    hhea.caretOffset = p.parseShort();
34536    p.relativeOffset += 8;
34537    hhea.metricDataFormat = p.parseShort();
34538    hhea.numberOfHMetrics = p.parseUShort();
34539    return hhea;
34540}
34541
34542function makeHheaTable(options) {
34543    return new table.Table('hhea', [
34544        {name: 'version', type: 'FIXED', value: 0x00010000},
34545        {name: 'ascender', type: 'FWORD', value: 0},
34546        {name: 'descender', type: 'FWORD', value: 0},
34547        {name: 'lineGap', type: 'FWORD', value: 0},
34548        {name: 'advanceWidthMax', type: 'UFWORD', value: 0},
34549        {name: 'minLeftSideBearing', type: 'FWORD', value: 0},
34550        {name: 'minRightSideBearing', type: 'FWORD', value: 0},
34551        {name: 'xMaxExtent', type: 'FWORD', value: 0},
34552        {name: 'caretSlopeRise', type: 'SHORT', value: 1},
34553        {name: 'caretSlopeRun', type: 'SHORT', value: 0},
34554        {name: 'caretOffset', type: 'SHORT', value: 0},
34555        {name: 'reserved1', type: 'SHORT', value: 0},
34556        {name: 'reserved2', type: 'SHORT', value: 0},
34557        {name: 'reserved3', type: 'SHORT', value: 0},
34558        {name: 'reserved4', type: 'SHORT', value: 0},
34559        {name: 'metricDataFormat', type: 'SHORT', value: 0},
34560        {name: 'numberOfHMetrics', type: 'USHORT', value: 0}
34561    ], options);
34562}
34563
34564var hhea = { parse: parseHheaTable, make: makeHheaTable };
34565
34566// The `hmtx` table contains the horizontal metrics for all glyphs.
34567// https://www.microsoft.com/typography/OTSPEC/hmtx.htm
34568
34569// Parse the `hmtx` table, which contains the horizontal metrics for all glyphs.
34570// This function augments the glyph array, adding the advanceWidth and leftSideBearing to each glyph.
34571function parseHmtxTable(data, start, numMetrics, numGlyphs, glyphs) {
34572    var advanceWidth;
34573    var leftSideBearing;
34574    var p = new parse.Parser(data, start);
34575    for (var i = 0; i < numGlyphs; i += 1) {
34576        // If the font is monospaced, only one entry is needed. This last entry applies to all subsequent glyphs.
34577        if (i < numMetrics) {
34578            advanceWidth = p.parseUShort();
34579            leftSideBearing = p.parseShort();
34580        }
34581
34582        var glyph = glyphs.get(i);
34583        glyph.advanceWidth = advanceWidth;
34584        glyph.leftSideBearing = leftSideBearing;
34585    }
34586}
34587
34588function makeHmtxTable(glyphs) {
34589    var t = new table.Table('hmtx', []);
34590    for (var i = 0; i < glyphs.length; i += 1) {
34591        var glyph = glyphs.get(i);
34592        var advanceWidth = glyph.advanceWidth || 0;
34593        var leftSideBearing = glyph.leftSideBearing || 0;
34594        t.fields.push({name: 'advanceWidth_' + i, type: 'USHORT', value: advanceWidth});
34595        t.fields.push({name: 'leftSideBearing_' + i, type: 'SHORT', value: leftSideBearing});
34596    }
34597
34598    return t;
34599}
34600
34601var hmtx = { parse: parseHmtxTable, make: makeHmtxTable };
34602
34603// The `ltag` table stores IETF BCP-47 language tags. It allows supporting
34604// languages for which TrueType does not assign a numeric code.
34605// https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6ltag.html
34606// http://www.w3.org/International/articles/language-tags/
34607// http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry
34608
34609function makeLtagTable(tags) {
34610    var result = new table.Table('ltag', [
34611        {name: 'version', type: 'ULONG', value: 1},
34612        {name: 'flags', type: 'ULONG', value: 0},
34613        {name: 'numTags', type: 'ULONG', value: tags.length}
34614    ]);
34615
34616    var stringPool = '';
34617    var stringPoolOffset = 12 + tags.length * 4;
34618    for (var i = 0; i < tags.length; ++i) {
34619        var pos = stringPool.indexOf(tags[i]);
34620        if (pos < 0) {
34621            pos = stringPool.length;
34622            stringPool += tags[i];
34623        }
34624
34625        result.fields.push({name: 'offset ' + i, type: 'USHORT', value: stringPoolOffset + pos});
34626        result.fields.push({name: 'length ' + i, type: 'USHORT', value: tags[i].length});
34627    }
34628
34629    result.fields.push({name: 'stringPool', type: 'CHARARRAY', value: stringPool});
34630    return result;
34631}
34632
34633function parseLtagTable(data, start) {
34634    var p = new parse.Parser(data, start);
34635    var tableVersion = p.parseULong();
34636    check.argument(tableVersion === 1, 'Unsupported ltag table version.');
34637    // The 'ltag' specification does not define any flags; skip the field.
34638    p.skip('uLong', 1);
34639    var numTags = p.parseULong();
34640
34641    var tags = [];
34642    for (var i = 0; i < numTags; i++) {
34643        var tag = '';
34644        var offset = start + p.parseUShort();
34645        var length = p.parseUShort();
34646        for (var j = offset; j < offset + length; ++j) {
34647            tag += String.fromCharCode(data.getInt8(j));
34648        }
34649
34650        tags.push(tag);
34651    }
34652
34653    return tags;
34654}
34655
34656var ltag = { make: makeLtagTable, parse: parseLtagTable };
34657
34658// The `maxp` table establishes the memory requirements for the font.
34659// We need it just to get the number of glyphs in the font.
34660// https://www.microsoft.com/typography/OTSPEC/maxp.htm
34661
34662// Parse the maximum profile `maxp` table.
34663function parseMaxpTable(data, start) {
34664    var maxp = {};
34665    var p = new parse.Parser(data, start);
34666    maxp.version = p.parseVersion();
34667    maxp.numGlyphs = p.parseUShort();
34668    if (maxp.version === 1.0) {
34669        maxp.maxPoints = p.parseUShort();
34670        maxp.maxContours = p.parseUShort();
34671        maxp.maxCompositePoints = p.parseUShort();
34672        maxp.maxCompositeContours = p.parseUShort();
34673        maxp.maxZones = p.parseUShort();
34674        maxp.maxTwilightPoints = p.parseUShort();
34675        maxp.maxStorage = p.parseUShort();
34676        maxp.maxFunctionDefs = p.parseUShort();
34677        maxp.maxInstructionDefs = p.parseUShort();
34678        maxp.maxStackElements = p.parseUShort();
34679        maxp.maxSizeOfInstructions = p.parseUShort();
34680        maxp.maxComponentElements = p.parseUShort();
34681        maxp.maxComponentDepth = p.parseUShort();
34682    }
34683
34684    return maxp;
34685}
34686
34687function makeMaxpTable(numGlyphs) {
34688    return new table.Table('maxp', [
34689        {name: 'version', type: 'FIXED', value: 0x00005000},
34690        {name: 'numGlyphs', type: 'USHORT', value: numGlyphs}
34691    ]);
34692}
34693
34694var maxp = { parse: parseMaxpTable, make: makeMaxpTable };
34695
34696// The `name` naming table.
34697// https://www.microsoft.com/typography/OTSPEC/name.htm
34698
34699// NameIDs for the name table.
34700var nameTableNames = [
34701    'copyright',              // 0
34702    'fontFamily',             // 1
34703    'fontSubfamily',          // 2
34704    'uniqueID',               // 3
34705    'fullName',               // 4
34706    'version',                // 5
34707    'postScriptName',         // 6
34708    'trademark',              // 7
34709    'manufacturer',           // 8
34710    'designer',               // 9
34711    'description',            // 10
34712    'manufacturerURL',        // 11
34713    'designerURL',            // 12
34714    'license',                // 13
34715    'licenseURL',             // 14
34716    'reserved',               // 15
34717    'preferredFamily',        // 16
34718    'preferredSubfamily',     // 17
34719    'compatibleFullName',     // 18
34720    'sampleText',             // 19
34721    'postScriptFindFontName', // 20
34722    'wwsFamily',              // 21
34723    'wwsSubfamily'            // 22
34724];
34725
34726var macLanguages = {
34727    0: 'en',
34728    1: 'fr',
34729    2: 'de',
34730    3: 'it',
34731    4: 'nl',
34732    5: 'sv',
34733    6: 'es',
34734    7: 'da',
34735    8: 'pt',
34736    9: 'no',
34737    10: 'he',
34738    11: 'ja',
34739    12: 'ar',
34740    13: 'fi',
34741    14: 'el',
34742    15: 'is',
34743    16: 'mt',
34744    17: 'tr',
34745    18: 'hr',
34746    19: 'zh-Hant',
34747    20: 'ur',
34748    21: 'hi',
34749    22: 'th',
34750    23: 'ko',
34751    24: 'lt',
34752    25: 'pl',
34753    26: 'hu',
34754    27: 'es',
34755    28: 'lv',
34756    29: 'se',
34757    30: 'fo',
34758    31: 'fa',
34759    32: 'ru',
34760    33: 'zh',
34761    34: 'nl-BE',
34762    35: 'ga',
34763    36: 'sq',
34764    37: 'ro',
34765    38: 'cz',
34766    39: 'sk',
34767    40: 'si',
34768    41: 'yi',
34769    42: 'sr',
34770    43: 'mk',
34771    44: 'bg',
34772    45: 'uk',
34773    46: 'be',
34774    47: 'uz',
34775    48: 'kk',
34776    49: 'az-Cyrl',
34777    50: 'az-Arab',
34778    51: 'hy',
34779    52: 'ka',
34780    53: 'mo',
34781    54: 'ky',
34782    55: 'tg',
34783    56: 'tk',
34784    57: 'mn-CN',
34785    58: 'mn',
34786    59: 'ps',
34787    60: 'ks',
34788    61: 'ku',
34789    62: 'sd',
34790    63: 'bo',
34791    64: 'ne',
34792    65: 'sa',
34793    66: 'mr',
34794    67: 'bn',
34795    68: 'as',
34796    69: 'gu',
34797    70: 'pa',
34798    71: 'or',
34799    72: 'ml',
34800    73: 'kn',
34801    74: 'ta',
34802    75: 'te',
34803    76: 'si',
34804    77: 'my',
34805    78: 'km',
34806    79: 'lo',
34807    80: 'vi',
34808    81: 'id',
34809    82: 'tl',
34810    83: 'ms',
34811    84: 'ms-Arab',
34812    85: 'am',
34813    86: 'ti',
34814    87: 'om',
34815    88: 'so',
34816    89: 'sw',
34817    90: 'rw',
34818    91: 'rn',
34819    92: 'ny',
34820    93: 'mg',
34821    94: 'eo',
34822    128: 'cy',
34823    129: 'eu',
34824    130: 'ca',
34825    131: 'la',
34826    132: 'qu',
34827    133: 'gn',
34828    134: 'ay',
34829    135: 'tt',
34830    136: 'ug',
34831    137: 'dz',
34832    138: 'jv',
34833    139: 'su',
34834    140: 'gl',
34835    141: 'af',
34836    142: 'br',
34837    143: 'iu',
34838    144: 'gd',
34839    145: 'gv',
34840    146: 'ga',
34841    147: 'to',
34842    148: 'el-polyton',
34843    149: 'kl',
34844    150: 'az',
34845    151: 'nn'
34846};
34847
34848// MacOS language ID → MacOS script ID
34849//
34850// Note that the script ID is not sufficient to determine what encoding
34851// to use in TrueType files. For some languages, MacOS used a modification
34852// of a mainstream script. For example, an Icelandic name would be stored
34853// with smRoman in the TrueType naming table, but the actual encoding
34854// is a special Icelandic version of the normal Macintosh Roman encoding.
34855// As another example, Inuktitut uses an 8-bit encoding for Canadian Aboriginal
34856// Syllables but MacOS had run out of available script codes, so this was
34857// done as a (pretty radical) "modification" of Ethiopic.
34858//
34859// http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/Readme.txt
34860var macLanguageToScript = {
34861    0: 0,  // langEnglish → smRoman
34862    1: 0,  // langFrench → smRoman
34863    2: 0,  // langGerman → smRoman
34864    3: 0,  // langItalian → smRoman
34865    4: 0,  // langDutch → smRoman
34866    5: 0,  // langSwedish → smRoman
34867    6: 0,  // langSpanish → smRoman
34868    7: 0,  // langDanish → smRoman
34869    8: 0,  // langPortuguese → smRoman
34870    9: 0,  // langNorwegian → smRoman
34871    10: 5,  // langHebrew → smHebrew
34872    11: 1,  // langJapanese → smJapanese
34873    12: 4,  // langArabic → smArabic
34874    13: 0,  // langFinnish → smRoman
34875    14: 6,  // langGreek → smGreek
34876    15: 0,  // langIcelandic → smRoman (modified)
34877    16: 0,  // langMaltese → smRoman
34878    17: 0,  // langTurkish → smRoman (modified)
34879    18: 0,  // langCroatian → smRoman (modified)
34880    19: 2,  // langTradChinese → smTradChinese
34881    20: 4,  // langUrdu → smArabic
34882    21: 9,  // langHindi → smDevanagari
34883    22: 21,  // langThai → smThai
34884    23: 3,  // langKorean → smKorean
34885    24: 29,  // langLithuanian → smCentralEuroRoman
34886    25: 29,  // langPolish → smCentralEuroRoman
34887    26: 29,  // langHungarian → smCentralEuroRoman
34888    27: 29,  // langEstonian → smCentralEuroRoman
34889    28: 29,  // langLatvian → smCentralEuroRoman
34890    29: 0,  // langSami → smRoman
34891    30: 0,  // langFaroese → smRoman (modified)
34892    31: 4,  // langFarsi → smArabic (modified)
34893    32: 7,  // langRussian → smCyrillic
34894    33: 25,  // langSimpChinese → smSimpChinese
34895    34: 0,  // langFlemish → smRoman
34896    35: 0,  // langIrishGaelic → smRoman (modified)
34897    36: 0,  // langAlbanian → smRoman
34898    37: 0,  // langRomanian → smRoman (modified)
34899    38: 29,  // langCzech → smCentralEuroRoman
34900    39: 29,  // langSlovak → smCentralEuroRoman
34901    40: 0,  // langSlovenian → smRoman (modified)
34902    41: 5,  // langYiddish → smHebrew
34903    42: 7,  // langSerbian → smCyrillic
34904    43: 7,  // langMacedonian → smCyrillic
34905    44: 7,  // langBulgarian → smCyrillic
34906    45: 7,  // langUkrainian → smCyrillic (modified)
34907    46: 7,  // langByelorussian → smCyrillic
34908    47: 7,  // langUzbek → smCyrillic
34909    48: 7,  // langKazakh → smCyrillic
34910    49: 7,  // langAzerbaijani → smCyrillic
34911    50: 4,  // langAzerbaijanAr → smArabic
34912    51: 24,  // langArmenian → smArmenian
34913    52: 23,  // langGeorgian → smGeorgian
34914    53: 7,  // langMoldavian → smCyrillic
34915    54: 7,  // langKirghiz → smCyrillic
34916    55: 7,  // langTajiki → smCyrillic
34917    56: 7,  // langTurkmen → smCyrillic
34918    57: 27,  // langMongolian → smMongolian
34919    58: 7,  // langMongolianCyr → smCyrillic
34920    59: 4,  // langPashto → smArabic
34921    60: 4,  // langKurdish → smArabic
34922    61: 4,  // langKashmiri → smArabic
34923    62: 4,  // langSindhi → smArabic
34924    63: 26,  // langTibetan → smTibetan
34925    64: 9,  // langNepali → smDevanagari
34926    65: 9,  // langSanskrit → smDevanagari
34927    66: 9,  // langMarathi → smDevanagari
34928    67: 13,  // langBengali → smBengali
34929    68: 13,  // langAssamese → smBengali
34930    69: 11,  // langGujarati → smGujarati
34931    70: 10,  // langPunjabi → smGurmukhi
34932    71: 12,  // langOriya → smOriya
34933    72: 17,  // langMalayalam → smMalayalam
34934    73: 16,  // langKannada → smKannada
34935    74: 14,  // langTamil → smTamil
34936    75: 15,  // langTelugu → smTelugu
34937    76: 18,  // langSinhalese → smSinhalese
34938    77: 19,  // langBurmese → smBurmese
34939    78: 20,  // langKhmer → smKhmer
34940    79: 22,  // langLao → smLao
34941    80: 30,  // langVietnamese → smVietnamese
34942    81: 0,  // langIndonesian → smRoman
34943    82: 0,  // langTagalog → smRoman
34944    83: 0,  // langMalayRoman → smRoman
34945    84: 4,  // langMalayArabic → smArabic
34946    85: 28,  // langAmharic → smEthiopic
34947    86: 28,  // langTigrinya → smEthiopic
34948    87: 28,  // langOromo → smEthiopic
34949    88: 0,  // langSomali → smRoman
34950    89: 0,  // langSwahili → smRoman
34951    90: 0,  // langKinyarwanda → smRoman
34952    91: 0,  // langRundi → smRoman
34953    92: 0,  // langNyanja → smRoman
34954    93: 0,  // langMalagasy → smRoman
34955    94: 0,  // langEsperanto → smRoman
34956    128: 0,  // langWelsh → smRoman (modified)
34957    129: 0,  // langBasque → smRoman
34958    130: 0,  // langCatalan → smRoman
34959    131: 0,  // langLatin → smRoman
34960    132: 0,  // langQuechua → smRoman
34961    133: 0,  // langGuarani → smRoman
34962    134: 0,  // langAymara → smRoman
34963    135: 7,  // langTatar → smCyrillic
34964    136: 4,  // langUighur → smArabic
34965    137: 26,  // langDzongkha → smTibetan
34966    138: 0,  // langJavaneseRom → smRoman
34967    139: 0,  // langSundaneseRom → smRoman
34968    140: 0,  // langGalician → smRoman
34969    141: 0,  // langAfrikaans → smRoman
34970    142: 0,  // langBreton → smRoman (modified)
34971    143: 28,  // langInuktitut → smEthiopic (modified)
34972    144: 0,  // langScottishGaelic → smRoman (modified)
34973    145: 0,  // langManxGaelic → smRoman (modified)
34974    146: 0,  // langIrishGaelicScript → smRoman (modified)
34975    147: 0,  // langTongan → smRoman
34976    148: 6,  // langGreekAncient → smRoman
34977    149: 0,  // langGreenlandic → smRoman
34978    150: 0,  // langAzerbaijanRoman → smRoman
34979    151: 0   // langNynorsk → smRoman
34980};
34981
34982// While Microsoft indicates a region/country for all its language
34983// IDs, we omit the region code if it's equal to the "most likely
34984// region subtag" according to Unicode CLDR. For scripts, we omit
34985// the subtag if it is equal to the Suppress-Script entry in the
34986// IANA language subtag registry for IETF BCP 47.
34987//
34988// For example, Microsoft states that its language code 0x041A is
34989// Croatian in Croatia. We transform this to the BCP 47 language code 'hr'
34990// and not 'hr-HR' because Croatia is the default country for Croatian,
34991// according to Unicode CLDR. As another example, Microsoft states
34992// that 0x101A is Croatian (Latin) in Bosnia-Herzegovina. We transform
34993// this to 'hr-BA' and not 'hr-Latn-BA' because Latin is the default script
34994// for the Croatian language, according to IANA.
34995//
34996// http://www.unicode.org/cldr/charts/latest/supplemental/likely_subtags.html
34997// http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry
34998var windowsLanguages = {
34999    0x0436: 'af',
35000    0x041C: 'sq',
35001    0x0484: 'gsw',
35002    0x045E: 'am',
35003    0x1401: 'ar-DZ',
35004    0x3C01: 'ar-BH',
35005    0x0C01: 'ar',
35006    0x0801: 'ar-IQ',
35007    0x2C01: 'ar-JO',
35008    0x3401: 'ar-KW',
35009    0x3001: 'ar-LB',
35010    0x1001: 'ar-LY',
35011    0x1801: 'ary',
35012    0x2001: 'ar-OM',
35013    0x4001: 'ar-QA',
35014    0x0401: 'ar-SA',
35015    0x2801: 'ar-SY',
35016    0x1C01: 'aeb',
35017    0x3801: 'ar-AE',
35018    0x2401: 'ar-YE',
35019    0x042B: 'hy',
35020    0x044D: 'as',
35021    0x082C: 'az-Cyrl',
35022    0x042C: 'az',
35023    0x046D: 'ba',
35024    0x042D: 'eu',
35025    0x0423: 'be',
35026    0x0845: 'bn',
35027    0x0445: 'bn-IN',
35028    0x201A: 'bs-Cyrl',
35029    0x141A: 'bs',
35030    0x047E: 'br',
35031    0x0402: 'bg',
35032    0x0403: 'ca',
35033    0x0C04: 'zh-HK',
35034    0x1404: 'zh-MO',
35035    0x0804: 'zh',
35036    0x1004: 'zh-SG',
35037    0x0404: 'zh-TW',
35038    0x0483: 'co',
35039    0x041A: 'hr',
35040    0x101A: 'hr-BA',
35041    0x0405: 'cs',
35042    0x0406: 'da',
35043    0x048C: 'prs',
35044    0x0465: 'dv',
35045    0x0813: 'nl-BE',
35046    0x0413: 'nl',
35047    0x0C09: 'en-AU',
35048    0x2809: 'en-BZ',
35049    0x1009: 'en-CA',
35050    0x2409: 'en-029',
35051    0x4009: 'en-IN',
35052    0x1809: 'en-IE',
35053    0x2009: 'en-JM',
35054    0x4409: 'en-MY',
35055    0x1409: 'en-NZ',
35056    0x3409: 'en-PH',
35057    0x4809: 'en-SG',
35058    0x1C09: 'en-ZA',
35059    0x2C09: 'en-TT',
35060    0x0809: 'en-GB',
35061    0x0409: 'en',
35062    0x3009: 'en-ZW',
35063    0x0425: 'et',
35064    0x0438: 'fo',
35065    0x0464: 'fil',
35066    0x040B: 'fi',
35067    0x080C: 'fr-BE',
35068    0x0C0C: 'fr-CA',
35069    0x040C: 'fr',
35070    0x140C: 'fr-LU',
35071    0x180C: 'fr-MC',
35072    0x100C: 'fr-CH',
35073    0x0462: 'fy',
35074    0x0456: 'gl',
35075    0x0437: 'ka',
35076    0x0C07: 'de-AT',
35077    0x0407: 'de',
35078    0x1407: 'de-LI',
35079    0x1007: 'de-LU',
35080    0x0807: 'de-CH',
35081    0x0408: 'el',
35082    0x046F: 'kl',
35083    0x0447: 'gu',
35084    0x0468: 'ha',
35085    0x040D: 'he',
35086    0x0439: 'hi',
35087    0x040E: 'hu',
35088    0x040F: 'is',
35089    0x0470: 'ig',
35090    0x0421: 'id',
35091    0x045D: 'iu',
35092    0x085D: 'iu-Latn',
35093    0x083C: 'ga',
35094    0x0434: 'xh',
35095    0x0435: 'zu',
35096    0x0410: 'it',
35097    0x0810: 'it-CH',
35098    0x0411: 'ja',
35099    0x044B: 'kn',
35100    0x043F: 'kk',
35101    0x0453: 'km',
35102    0x0486: 'quc',
35103    0x0487: 'rw',
35104    0x0441: 'sw',
35105    0x0457: 'kok',
35106    0x0412: 'ko',
35107    0x0440: 'ky',
35108    0x0454: 'lo',
35109    0x0426: 'lv',
35110    0x0427: 'lt',
35111    0x082E: 'dsb',
35112    0x046E: 'lb',
35113    0x042F: 'mk',
35114    0x083E: 'ms-BN',
35115    0x043E: 'ms',
35116    0x044C: 'ml',
35117    0x043A: 'mt',
35118    0x0481: 'mi',
35119    0x047A: 'arn',
35120    0x044E: 'mr',
35121    0x047C: 'moh',
35122    0x0450: 'mn',
35123    0x0850: 'mn-CN',
35124    0x0461: 'ne',
35125    0x0414: 'nb',
35126    0x0814: 'nn',
35127    0x0482: 'oc',
35128    0x0448: 'or',
35129    0x0463: 'ps',
35130    0x0415: 'pl',
35131    0x0416: 'pt',
35132    0x0816: 'pt-PT',
35133    0x0446: 'pa',
35134    0x046B: 'qu-BO',
35135    0x086B: 'qu-EC',
35136    0x0C6B: 'qu',
35137    0x0418: 'ro',
35138    0x0417: 'rm',
35139    0x0419: 'ru',
35140    0x243B: 'smn',
35141    0x103B: 'smj-NO',
35142    0x143B: 'smj',
35143    0x0C3B: 'se-FI',
35144    0x043B: 'se',
35145    0x083B: 'se-SE',
35146    0x203B: 'sms',
35147    0x183B: 'sma-NO',
35148    0x1C3B: 'sms',
35149    0x044F: 'sa',
35150    0x1C1A: 'sr-Cyrl-BA',
35151    0x0C1A: 'sr',
35152    0x181A: 'sr-Latn-BA',
35153    0x081A: 'sr-Latn',
35154    0x046C: 'nso',
35155    0x0432: 'tn',
35156    0x045B: 'si',
35157    0x041B: 'sk',
35158    0x0424: 'sl',
35159    0x2C0A: 'es-AR',
35160    0x400A: 'es-BO',
35161    0x340A: 'es-CL',
35162    0x240A: 'es-CO',
35163    0x140A: 'es-CR',
35164    0x1C0A: 'es-DO',
35165    0x300A: 'es-EC',
35166    0x440A: 'es-SV',
35167    0x100A: 'es-GT',
35168    0x480A: 'es-HN',
35169    0x080A: 'es-MX',
35170    0x4C0A: 'es-NI',
35171    0x180A: 'es-PA',
35172    0x3C0A: 'es-PY',
35173    0x280A: 'es-PE',
35174    0x500A: 'es-PR',
35175
35176    // Microsoft has defined two different language codes for
35177    // “Spanish with modern sorting” and “Spanish with traditional
35178    // sorting”. This makes sense for collation APIs, and it would be
35179    // possible to express this in BCP 47 language tags via Unicode
35180    // extensions (eg., es-u-co-trad is Spanish with traditional
35181    // sorting). However, for storing names in fonts, the distinction
35182    // does not make sense, so we give “es” in both cases.
35183    0x0C0A: 'es',
35184    0x040A: 'es',
35185
35186    0x540A: 'es-US',
35187    0x380A: 'es-UY',
35188    0x200A: 'es-VE',
35189    0x081D: 'sv-FI',
35190    0x041D: 'sv',
35191    0x045A: 'syr',
35192    0x0428: 'tg',
35193    0x085F: 'tzm',
35194    0x0449: 'ta',
35195    0x0444: 'tt',
35196    0x044A: 'te',
35197    0x041E: 'th',
35198    0x0451: 'bo',
35199    0x041F: 'tr',
35200    0x0442: 'tk',
35201    0x0480: 'ug',
35202    0x0422: 'uk',
35203    0x042E: 'hsb',
35204    0x0420: 'ur',
35205    0x0843: 'uz-Cyrl',
35206    0x0443: 'uz',
35207    0x042A: 'vi',
35208    0x0452: 'cy',
35209    0x0488: 'wo',
35210    0x0485: 'sah',
35211    0x0478: 'ii',
35212    0x046A: 'yo'
35213};
35214
35215// Returns a IETF BCP 47 language code, for example 'zh-Hant'
35216// for 'Chinese in the traditional script'.
35217function getLanguageCode(platformID, languageID, ltag) {
35218    switch (platformID) {
35219        case 0:  // Unicode
35220            if (languageID === 0xFFFF) {
35221                return 'und';
35222            } else if (ltag) {
35223                return ltag[languageID];
35224            }
35225
35226            break;
35227
35228        case 1:  // Macintosh
35229            return macLanguages[languageID];
35230
35231        case 3:  // Windows
35232            return windowsLanguages[languageID];
35233    }
35234
35235    return undefined;
35236}
35237
35238var utf16 = 'utf-16';
35239
35240// MacOS script ID → encoding. This table stores the default case,
35241// which can be overridden by macLanguageEncodings.
35242var macScriptEncodings = {
35243    0: 'macintosh',           // smRoman
35244    1: 'x-mac-japanese',      // smJapanese
35245    2: 'x-mac-chinesetrad',   // smTradChinese
35246    3: 'x-mac-korean',        // smKorean
35247    6: 'x-mac-greek',         // smGreek
35248    7: 'x-mac-cyrillic',      // smCyrillic
35249    9: 'x-mac-devanagai',     // smDevanagari
35250    10: 'x-mac-gurmukhi',     // smGurmukhi
35251    11: 'x-mac-gujarati',     // smGujarati
35252    12: 'x-mac-oriya',        // smOriya
35253    13: 'x-mac-bengali',      // smBengali
35254    14: 'x-mac-tamil',        // smTamil
35255    15: 'x-mac-telugu',       // smTelugu
35256    16: 'x-mac-kannada',      // smKannada
35257    17: 'x-mac-malayalam',    // smMalayalam
35258    18: 'x-mac-sinhalese',    // smSinhalese
35259    19: 'x-mac-burmese',      // smBurmese
35260    20: 'x-mac-khmer',        // smKhmer
35261    21: 'x-mac-thai',         // smThai
35262    22: 'x-mac-lao',          // smLao
35263    23: 'x-mac-georgian',     // smGeorgian
35264    24: 'x-mac-armenian',     // smArmenian
35265    25: 'x-mac-chinesesimp',  // smSimpChinese
35266    26: 'x-mac-tibetan',      // smTibetan
35267    27: 'x-mac-mongolian',    // smMongolian
35268    28: 'x-mac-ethiopic',     // smEthiopic
35269    29: 'x-mac-ce',           // smCentralEuroRoman
35270    30: 'x-mac-vietnamese',   // smVietnamese
35271    31: 'x-mac-extarabic'     // smExtArabic
35272};
35273
35274// MacOS language ID → encoding. This table stores the exceptional
35275// cases, which override macScriptEncodings. For writing MacOS naming
35276// tables, we need to emit a MacOS script ID. Therefore, we cannot
35277// merge macScriptEncodings into macLanguageEncodings.
35278//
35279// http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/Readme.txt
35280var macLanguageEncodings = {
35281    15: 'x-mac-icelandic',    // langIcelandic
35282    17: 'x-mac-turkish',      // langTurkish
35283    18: 'x-mac-croatian',     // langCroatian
35284    24: 'x-mac-ce',           // langLithuanian
35285    25: 'x-mac-ce',           // langPolish
35286    26: 'x-mac-ce',           // langHungarian
35287    27: 'x-mac-ce',           // langEstonian
35288    28: 'x-mac-ce',           // langLatvian
35289    30: 'x-mac-icelandic',    // langFaroese
35290    37: 'x-mac-romanian',     // langRomanian
35291    38: 'x-mac-ce',           // langCzech
35292    39: 'x-mac-ce',           // langSlovak
35293    40: 'x-mac-ce',           // langSlovenian
35294    143: 'x-mac-inuit',       // langInuktitut
35295    146: 'x-mac-gaelic'       // langIrishGaelicScript
35296};
35297
35298function getEncoding(platformID, encodingID, languageID) {
35299    switch (platformID) {
35300        case 0:  // Unicode
35301            return utf16;
35302
35303        case 1:  // Apple Macintosh
35304            return macLanguageEncodings[languageID] || macScriptEncodings[encodingID];
35305
35306        case 3:  // Microsoft Windows
35307            if (encodingID === 1 || encodingID === 10) {
35308                return utf16;
35309            }
35310
35311            break;
35312    }
35313
35314    return undefined;
35315}
35316
35317// Parse the naming `name` table.
35318// FIXME: Format 1 additional fields are not supported yet.
35319// ltag is the content of the `ltag' table, such as ['en', 'zh-Hans', 'de-CH-1904'].
35320function parseNameTable(data, start, ltag) {
35321    var name = {};
35322    var p = new parse.Parser(data, start);
35323    var format = p.parseUShort();
35324    var count = p.parseUShort();
35325    var stringOffset = p.offset + p.parseUShort();
35326    for (var i = 0; i < count; i++) {
35327        var platformID = p.parseUShort();
35328        var encodingID = p.parseUShort();
35329        var languageID = p.parseUShort();
35330        var nameID = p.parseUShort();
35331        var property = nameTableNames[nameID] || nameID;
35332        var byteLength = p.parseUShort();
35333        var offset = p.parseUShort();
35334        var language = getLanguageCode(platformID, languageID, ltag);
35335        var encoding = getEncoding(platformID, encodingID, languageID);
35336        if (encoding !== undefined && language !== undefined) {
35337            var text = (void 0);
35338            if (encoding === utf16) {
35339                text = decode.UTF16(data, stringOffset + offset, byteLength);
35340            } else {
35341                text = decode.MACSTRING(data, stringOffset + offset, byteLength, encoding);
35342            }
35343
35344            if (text) {
35345                var translations = name[property];
35346                if (translations === undefined) {
35347                    translations = name[property] = {};
35348                }
35349
35350                translations[language] = text;
35351            }
35352        }
35353    }
35354
35355    var langTagCount = 0;
35356    if (format === 1) {
35357        // FIXME: Also handle Microsoft's 'name' table 1.
35358        langTagCount = p.parseUShort();
35359    }
35360
35361    return name;
35362}
35363
35364// {23: 'foo'} → {'foo': 23}
35365// ['bar', 'baz'] → {'bar': 0, 'baz': 1}
35366function reverseDict(dict) {
35367    var result = {};
35368    for (var key in dict) {
35369        result[dict[key]] = parseInt(key);
35370    }
35371
35372    return result;
35373}
35374
35375function makeNameRecord(platformID, encodingID, languageID, nameID, length, offset) {
35376    return new table.Record('NameRecord', [
35377        {name: 'platformID', type: 'USHORT', value: platformID},
35378        {name: 'encodingID', type: 'USHORT', value: encodingID},
35379        {name: 'languageID', type: 'USHORT', value: languageID},
35380        {name: 'nameID', type: 'USHORT', value: nameID},
35381        {name: 'length', type: 'USHORT', value: length},
35382        {name: 'offset', type: 'USHORT', value: offset}
35383    ]);
35384}
35385
35386// Finds the position of needle in haystack, or -1 if not there.
35387// Like String.indexOf(), but for arrays.
35388function findSubArray(needle, haystack) {
35389    var needleLength = needle.length;
35390    var limit = haystack.length - needleLength + 1;
35391
35392    loop:
35393    for (var pos = 0; pos < limit; pos++) {
35394        for (; pos < limit; pos++) {
35395            for (var k = 0; k < needleLength; k++) {
35396                if (haystack[pos + k] !== needle[k]) {
35397                    continue loop;
35398                }
35399            }
35400
35401            return pos;
35402        }
35403    }
35404
35405    return -1;
35406}
35407
35408function addStringToPool(s, pool) {
35409    var offset = findSubArray(s, pool);
35410    if (offset < 0) {
35411        offset = pool.length;
35412        var i = 0;
35413        var len = s.length;
35414        for (; i < len; ++i) {
35415            pool.push(s[i]);
35416        }
35417
35418    }
35419
35420    return offset;
35421}
35422
35423function makeNameTable(names, ltag) {
35424    var nameID;
35425    var nameIDs = [];
35426
35427    var namesWithNumericKeys = {};
35428    var nameTableIds = reverseDict(nameTableNames);
35429    for (var key in names) {
35430        var id = nameTableIds[key];
35431        if (id === undefined) {
35432            id = key;
35433        }
35434
35435        nameID = parseInt(id);
35436
35437        if (isNaN(nameID)) {
35438            throw new Error('Name table entry "' + key + '" does not exist, see nameTableNames for complete list.');
35439        }
35440
35441        namesWithNumericKeys[nameID] = names[key];
35442        nameIDs.push(nameID);
35443    }
35444
35445    var macLanguageIds = reverseDict(macLanguages);
35446    var windowsLanguageIds = reverseDict(windowsLanguages);
35447
35448    var nameRecords = [];
35449    var stringPool = [];
35450
35451    for (var i = 0; i < nameIDs.length; i++) {
35452        nameID = nameIDs[i];
35453        var translations = namesWithNumericKeys[nameID];
35454        for (var lang in translations) {
35455            var text = translations[lang];
35456
35457            // For MacOS, we try to emit the name in the form that was introduced
35458            // in the initial version of the TrueType spec (in the late 1980s).
35459            // However, this can fail for various reasons: the requested BCP 47
35460            // language code might not have an old-style Mac equivalent;
35461            // we might not have a codec for the needed character encoding;
35462            // or the name might contain characters that cannot be expressed
35463            // in the old-style Macintosh encoding. In case of failure, we emit
35464            // the name in a more modern fashion (Unicode encoding with BCP 47
35465            // language tags) that is recognized by MacOS 10.5, released in 2009.
35466            // If fonts were only read by operating systems, we could simply
35467            // emit all names in the modern form; this would be much easier.
35468            // However, there are many applications and libraries that read
35469            // 'name' tables directly, and these will usually only recognize
35470            // the ancient form (silently skipping the unrecognized names).
35471            var macPlatform = 1;  // Macintosh
35472            var macLanguage = macLanguageIds[lang];
35473            var macScript = macLanguageToScript[macLanguage];
35474            var macEncoding = getEncoding(macPlatform, macScript, macLanguage);
35475            var macName = encode.MACSTRING(text, macEncoding);
35476            if (macName === undefined) {
35477                macPlatform = 0;  // Unicode
35478                macLanguage = ltag.indexOf(lang);
35479                if (macLanguage < 0) {
35480                    macLanguage = ltag.length;
35481                    ltag.push(lang);
35482                }
35483
35484                macScript = 4;  // Unicode 2.0 and later
35485                macName = encode.UTF16(text);
35486            }
35487
35488            var macNameOffset = addStringToPool(macName, stringPool);
35489            nameRecords.push(makeNameRecord(macPlatform, macScript, macLanguage,
35490                                            nameID, macName.length, macNameOffset));
35491
35492            var winLanguage = windowsLanguageIds[lang];
35493            if (winLanguage !== undefined) {
35494                var winName = encode.UTF16(text);
35495                var winNameOffset = addStringToPool(winName, stringPool);
35496                nameRecords.push(makeNameRecord(3, 1, winLanguage,
35497                                                nameID, winName.length, winNameOffset));
35498            }
35499        }
35500    }
35501
35502    nameRecords.sort(function(a, b) {
35503        return ((a.platformID - b.platformID) ||
35504                (a.encodingID - b.encodingID) ||
35505                (a.languageID - b.languageID) ||
35506                (a.nameID - b.nameID));
35507    });
35508
35509    var t = new table.Table('name', [
35510        {name: 'format', type: 'USHORT', value: 0},
35511        {name: 'count', type: 'USHORT', value: nameRecords.length},
35512        {name: 'stringOffset', type: 'USHORT', value: 6 + nameRecords.length * 12}
35513    ]);
35514
35515    for (var r = 0; r < nameRecords.length; r++) {
35516        t.fields.push({name: 'record_' + r, type: 'RECORD', value: nameRecords[r]});
35517    }
35518
35519    t.fields.push({name: 'strings', type: 'LITERAL', value: stringPool});
35520    return t;
35521}
35522
35523var _name = { parse: parseNameTable, make: makeNameTable };
35524
35525// The `OS/2` table contains metrics required in OpenType fonts.
35526// https://www.microsoft.com/typography/OTSPEC/os2.htm
35527
35528var unicodeRanges = [
35529    {begin: 0x0000, end: 0x007F}, // Basic Latin
35530    {begin: 0x0080, end: 0x00FF}, // Latin-1 Supplement
35531    {begin: 0x0100, end: 0x017F}, // Latin Extended-A
35532    {begin: 0x0180, end: 0x024F}, // Latin Extended-B
35533    {begin: 0x0250, end: 0x02AF}, // IPA Extensions
35534    {begin: 0x02B0, end: 0x02FF}, // Spacing Modifier Letters
35535    {begin: 0x0300, end: 0x036F}, // Combining Diacritical Marks
35536    {begin: 0x0370, end: 0x03FF}, // Greek and Coptic
35537    {begin: 0x2C80, end: 0x2CFF}, // Coptic
35538    {begin: 0x0400, end: 0x04FF}, // Cyrillic
35539    {begin: 0x0530, end: 0x058F}, // Armenian
35540    {begin: 0x0590, end: 0x05FF}, // Hebrew
35541    {begin: 0xA500, end: 0xA63F}, // Vai
35542    {begin: 0x0600, end: 0x06FF}, // Arabic
35543    {begin: 0x07C0, end: 0x07FF}, // NKo
35544    {begin: 0x0900, end: 0x097F}, // Devanagari
35545    {begin: 0x0980, end: 0x09FF}, // Bengali
35546    {begin: 0x0A00, end: 0x0A7F}, // Gurmukhi
35547    {begin: 0x0A80, end: 0x0AFF}, // Gujarati
35548    {begin: 0x0B00, end: 0x0B7F}, // Oriya
35549    {begin: 0x0B80, end: 0x0BFF}, // Tamil
35550    {begin: 0x0C00, end: 0x0C7F}, // Telugu
35551    {begin: 0x0C80, end: 0x0CFF}, // Kannada
35552    {begin: 0x0D00, end: 0x0D7F}, // Malayalam
35553    {begin: 0x0E00, end: 0x0E7F}, // Thai
35554    {begin: 0x0E80, end: 0x0EFF}, // Lao
35555    {begin: 0x10A0, end: 0x10FF}, // Georgian
35556    {begin: 0x1B00, end: 0x1B7F}, // Balinese
35557    {begin: 0x1100, end: 0x11FF}, // Hangul Jamo
35558    {begin: 0x1E00, end: 0x1EFF}, // Latin Extended Additional
35559    {begin: 0x1F00, end: 0x1FFF}, // Greek Extended
35560    {begin: 0x2000, end: 0x206F}, // General Punctuation
35561    {begin: 0x2070, end: 0x209F}, // Superscripts And Subscripts
35562    {begin: 0x20A0, end: 0x20CF}, // Currency Symbol
35563    {begin: 0x20D0, end: 0x20FF}, // Combining Diacritical Marks For Symbols
35564    {begin: 0x2100, end: 0x214F}, // Letterlike Symbols
35565    {begin: 0x2150, end: 0x218F}, // Number Forms
35566    {begin: 0x2190, end: 0x21FF}, // Arrows
35567    {begin: 0x2200, end: 0x22FF}, // Mathematical Operators
35568    {begin: 0x2300, end: 0x23FF}, // Miscellaneous Technical
35569    {begin: 0x2400, end: 0x243F}, // Control Pictures
35570    {begin: 0x2440, end: 0x245F}, // Optical Character Recognition
35571    {begin: 0x2460, end: 0x24FF}, // Enclosed Alphanumerics
35572    {begin: 0x2500, end: 0x257F}, // Box Drawing
35573    {begin: 0x2580, end: 0x259F}, // Block Elements
35574    {begin: 0x25A0, end: 0x25FF}, // Geometric Shapes
35575    {begin: 0x2600, end: 0x26FF}, // Miscellaneous Symbols
35576    {begin: 0x2700, end: 0x27BF}, // Dingbats
35577    {begin: 0x3000, end: 0x303F}
35577, // CJK Symbols And Punctuation
35578    {begin: 0x3040, end: 0x309F}, // Hiragana
35579    {begin: 0x30A0, end: 0x30FF}, // Katakana
35580    {begin: 0x3100, end: 0x312F}, // Bopomofo
35581    {begin: 0x3130, end: 0x318F}, // Hangul Compatibility Jamo
35582    {begin: 0xA840, end: 0xA87F}, // Phags-pa
35583    {begin: 0x3200, end: 0x32FF}, // Enclosed CJK Letters And Months
35584    {begin: 0x3300, end: 0x33FF}, // CJK Compatibility
35585    {begin: 0xAC00, end: 0xD7AF}, // Hangul Syllables
35586    {begin: 0xD800, end: 0xDFFF}, // Non-Plane 0 *
35587    {begin: 0x10900, end: 0x1091F}, // Phoenicia
35588    {begin: 0x4E00, end: 0x9FFF}, // CJK Unified Ideographs
35589    {begin: 0xE000, end: 0xF8FF}, // Private Use Area (plane 0)
35590    {begin: 0x31C0, end: 0x31EF}, // CJK Strokes
35591    {begin: 0xFB00, end: 0xFB4F}, // Alphabetic Presentation Forms
35592    {begin: 0xFB50, end: 0xFDFF}, // Arabic Presentation Forms-A
35593    {begin: 0xFE20, end: 0xFE2F}, // Combining Half Marks
35594    {begin: 0xFE10, end: 0xFE1F}, // Vertical Forms
35595    {begin: 0xFE50, end: 0xFE6F}, // Small Form Variants
35596    {begin: 0xFE70, end: 0xFEFF}, // Arabic Presentation Forms-B
35597    {begin: 0xFF00, end: 0xFFEF}, // Halfwidth And Fullwidth Forms
35598    {begin: 0xFFF0, end: 0xFFFF}, // Specials
35599    {begin: 0x0F00, end: 0x0FFF}, // Tibetan
35600    {begin: 0x0700, end: 0x074F}, // Syriac
35601    {begin: 0x0780, end: 0x07BF}, // Thaana
35602    {begin: 0x0D80, end: 0x0DFF}, // Sinhala
35603    {begin: 0x1000, end: 0x109F}, // Myanmar
35604    {begin: 0x1200, end: 0x137F}, // Ethiopic
35605    {begin: 0x13A0, end: 0x13FF}, // Cherokee
35606    {begin: 0x1400, end: 0x167F}, // Unified Canadian Aboriginal Syllabics
35607    {begin: 0x1680, end: 0x169F}, // Ogham
35608    {begin: 0x16A0, end: 0x16FF}, // Runic
35609    {begin: 0x1780, end: 0x17FF}, // Khmer
35610    {begin: 0x1800, end: 0x18AF}, // Mongolian
35611    {begin: 0x2800, end: 0x28FF}, // Braille Patterns
35612    {begin: 0xA000, end: 0xA48F}, // Yi Syllables
35613    {begin: 0x1700, end: 0x171F}, // Tagalog
35614    {begin: 0x10300, end: 0x1032F}, // Old Italic
35615    {begin: 0x10330, end: 0x1034F}, // Gothic
35616    {begin: 0x10400, end: 0x1044F}, // Deseret
35617    {begin: 0x1D000, end: 0x1D0FF}, // Byzantine Musical Symbols
35618    {begin: 0x1D400, end: 0x1D7FF}, // Mathematical Alphanumeric Symbols
35619    {begin: 0xFF000, end: 0xFFFFD}, // Private Use (plane 15)
35620    {begin: 0xFE00, end: 0xFE0F}, // Variation Selectors
35621    {begin: 0xE0000, end: 0xE007F}, // Tags
35622    {begin: 0x1900, end: 0x194F}, // Limbu
35623    {begin: 0x1950, end: 0x197F}, // Tai Le
35624    {begin: 0x1980, end: 0x19DF}, // New Tai Lue
35625    {begin: 0x1A00, end: 0x1A1F}, // Buginese
35626    {begin: 0x2C00, end: 0x2C5F}, // Glagolitic
35627    {begin: 0x2D30, end: 0x2D7F}, // Tifinagh
35628    {begin: 0x4DC0, end: 0x4DFF}, // Yijing Hexagram Symbols
35629    {begin: 0xA800, end: 0xA82F}, // Syloti Nagri
35630    {begin: 0x10000, end: 0x1007F}, // Linear B Syllabary
35631    {begin: 0x10140, end: 0x1018F}, // Ancient Greek Numbers
35632    {begin: 0x10380, end: 0x1039F}, // Ugaritic
35633    {begin: 0x103A0, end: 0x103DF}, // Old Persian
35634    {begin: 0x10450, end: 0x1047F}, // Shavian
35635    {begin: 0x10480, end: 0x104AF}, // Osmanya
35636    {begin: 0x10800, end: 0x1083F}, // Cypriot Syllabary
35637    {begin: 0x10A00, end: 0x10A5F}, // Kharoshthi
35638    {begin: 0x1D300, end: 0x1D35F}, // Tai Xuan Jing Symbols
35639    {begin: 0x12000, end: 0x123FF}, // Cuneiform
35640    {begin: 0x1D360, end: 0x1D37F}, // Counting Rod Numerals
35641    {begin: 0x1B80, end: 0x1BBF}, // Sundanese
35642    {begin: 0x1C00, end: 0x1C4F}, // Lepcha
35643    {begin: 0x1C50, end: 0x1C7F}, // Ol Chiki
35644    {begin: 0xA880, end: 0xA8DF}, // Saurashtra
35645    {begin: 0xA900, end: 0xA92F}, // Kayah Li
35646    {begin: 0xA930, end: 0xA95F}, // Rejang
35647    {begin: 0xAA00, end: 0xAA5F}, // Cham
35648    {begin: 0x10190, end: 0x101CF}, // Ancient Symbols
35649    {begin: 0x101D0, end: 0x101FF}, // Phaistos Disc
35650    {begin: 0x102A0, end: 0x102DF}, // Carian
35651    {begin: 0x1F030, end: 0x1F09F}  // Domino Tiles
35652];
35653
35654function getUnicodeRange(unicode) {
35655    for (var i = 0; i < unicodeRanges.length; i += 1) {
35656        var range = unicodeRanges[i];
35657        if (unicode >= range.begin && unicode < range.end) {
35658            return i;
35659        }
35660    }
35661
35662    return -1;
35663}
35664
35665// Parse the OS/2 and Windows metrics `OS/2` table
35666function parseOS2Table(data, start) {
35667    var os2 = {};
35668    var p = new parse.Parser(data, start);
35669    os2.version = p.parseUShort();
35670    os2.xAvgCharWidth = p.parseShort();
35671    os2.usWeightClass = p.parseUShort();
35672    os2.usWidthClass = p.parseUShort();
35673    os2.fsType = p.parseUShort();
35674    os2.ySubscriptXSize = p.parseShort();
35675    os2.ySubscriptYSize = p.parseShort();
35676    os2.ySubscriptXOffset = p.parseShort();
35677    os2.ySubscriptYOffset = p.parseShort();
35678    os2.ySuperscriptXSize = p.parseShort();
35679    os2.ySuperscriptYSize = p.parseShort();
35680    os2.ySuperscriptXOffset = p.parseShort();
35681    os2.ySuperscriptYOffset = p.parseShort();
35682    os2.yStrikeoutSize = p.parseShort();
35683    os2.yStrikeoutPosition = p.parseShort();
35684    os2.sFamilyClass = p.parseShort();
35685    os2.panose = [];
35686    for (var i = 0; i < 10; i++) {
35687        os2.panose[i] = p.parseByte();
35688    }
35689
35690    os2.ulUnicodeRange1 = p.parseULong();
35691    os2.ulUnicodeRange2 = p.parseULong();
35692    os2.ulUnicodeRange3 = p.parseULong();
35693    os2.ulUnicodeRange4 = p.parseULong();
35694    os2.achVendID = String.fromCharCode(p.parseByte(), p.parseByte(), p.parseByte(), p.parseByte());
35695    os2.fsSelection = p.parseUShort();
35696    os2.usFirstCharIndex = p.parseUShort();
35697    os2.usLastCharIndex = p.parseUShort();
35698    os2.sTypoAscender = p.parseShort();
35699    os2.sTypoDescender = p.parseShort();
35700    os2.sTypoLineGap = p.parseShort();
35701    os2.usWinAscent = p.parseUShort();
35702    os2.usWinDescent = p.parseUShort();
35703    if (os2.version >= 1) {
35704        os2.ulCodePageRange1 = p.parseULong();
35705        os2.ulCodePageRange2 = p.parseULong();
35706    }
35707
35708    if (os2.version >= 2) {
35709        os2.sxHeight = p.parseShort();
35710        os2.sCapHeight = p.parseShort();
35711        os2.usDefaultChar = p.parseUShort();
35712        os2.usBreakChar = p.parseUShort();
35713        os2.usMaxContent = p.parseUShort();
35714    }
35715
35716    return os2;
35717}
35718
35719function makeOS2Table(options) {
35720    return new table.Table('OS/2', [
35721        {name: 'version', type: 'USHORT', value: 0x0003},
35722        {name: 'xAvgCharWidth', type: 'SHORT', value: 0},
35723        {name: 'usWeightClass', type: 'USHORT', value: 0},
35724        {name: 'usWidthClass', type: 'USHORT', value: 0},
35725        {name: 'fsType', type: 'USHORT', value: 0},
35726        {name: 'ySubscriptXSize', type: 'SHORT', value: 650},
35727        {name: 'ySubscriptYSize', type: 'SHORT', value: 699},
35728        {name: 'ySubscriptXOffset', type: 'SHORT', value: 0},
35729        {name: 'ySubscriptYOffset', type: 'SHORT', value: 140},
35730        {name: 'ySuperscriptXSize', type: 'SHORT', value: 650},
35731        {name: 'ySuperscriptYSize', type: 'SHORT', value: 699},
35732        {name: 'ySuperscriptXOffset', type: 'SHORT', value: 0},
35733        {name: 'ySuperscriptYOffset', type: 'SHORT', value: 479},
35734        {name: 'yStrikeoutSize', type: 'SHORT', value: 49},
35735        {name: 'yStrikeoutPosition', type: 'SHORT', value: 258},
35736        {name: 'sFamilyClass', type: 'SHORT', value: 0},
35737        {name: 'bFamilyType', type: 'BYTE', value: 0},
35738        {name: 'bSerifStyle', type: 'BYTE', value: 0},
35739        {name: 'bWeight', type: 'BYTE', value: 0},
35740        {name: 'bProportion', type: 'BYTE', value: 0},
35741        {name: 'bContrast', type: 'BYTE', value: 0},
35742        {name: 'bStrokeVariation', type: 'BYTE', value: 0},
35743        {name: 'bArmStyle', type: 'BYTE', value: 0},
35744        {name: 'bLetterform', type: 'BYTE', value: 0},
35745        {name: 'bMidline', type: 'BYTE', value: 0},
35746        {name: 'bXHeight', type: 'BYTE', value: 0},
35747        {name: 'ulUnicodeRange1', type: 'ULONG', value: 0},
35748        {name: 'ulUnicodeRange2', type: 'ULONG', value: 0},
35749        {name: 'ulUnicodeRange3', type: 'ULONG', value: 0},
35750        {name: 'ulUnicodeRange4', type: 'ULONG', value: 0},
35751        {name: 'achVendID', type: 'CHARARRAY', value: 'XXXX'},
35752        {name: 'fsSelection', type: 'USHORT', value: 0},
35753        {name: 'usFirstCharIndex', type: 'USHORT', value: 0},
35754        {name: 'usLastCharIndex', type: 'USHORT', value: 0},
35755        {name: 'sTypoAscender', type: 'SHORT', value: 0},
35756        {name: 'sTypoDescender', type: 'SHORT', value: 0},
35757        {name: 'sTypoLineGap', type: 'SHORT', value: 0},
35758        {name: 'usWinAscent', type: 'USHORT', value: 0},
35759        {name: 'usWinDescent', type: 'USHORT', value: 0},
35760        {name: 'ulCodePageRange1', type: 'ULONG', value: 0},
35761        {name: 'ulCodePageRange2', type: 'ULONG', value: 0},
35762        {name: 'sxHeight', type: 'SHORT', value: 0},
35763        {name: 'sCapHeight', type: 'SHORT', value: 0},
35764        {name: 'usDefaultChar', type: 'USHORT', value: 0},
vendor: 9,333 bytes, lines 35765-36007
35765        {name: 'usBreakChar', type: 'USHORT', value: 0},
35766        {name: 'usMaxContext', type: 'USHORT', value: 0}
35767    ], options);
35768}
35769
35770var os2 = { parse: parseOS2Table, make: makeOS2Table, unicodeRanges: unicodeRanges, getUnicodeRange: getUnicodeRange };
35771
35772// The `post` table stores additional PostScript information, such as glyph names.
35773// https://www.microsoft.com/typography/OTSPEC/post.htm
35774
35775// Parse the PostScript `post` table
35776function parsePostTable(data, start) {
35777    var post = {};
35778    var p = new parse.Parser(data, start);
35779    post.version = p.parseVersion();
35780    post.italicAngle = p.parseFixed();
35781    post.underlinePosition = p.parseShort();
35782    post.underlineThickness = p.parseShort();
35783    post.isFixedPitch = p.parseULong();
35784    post.minMemType42 = p.parseULong();
35785    post.maxMemType42 = p.parseULong();
35786    post.minMemType1 = p.parseULong();
35787    post.maxMemType1 = p.parseULong();
35788    switch (post.version) {
35789        case 1:
35790            post.names = standardNames.slice();
35791            break;
35792        case 2:
35793            post.numberOfGlyphs = p.parseUShort();
35794            post.glyphNameIndex = new Array(post.numberOfGlyphs);
35795            for (var i = 0; i < post.numberOfGlyphs; i++) {
35796                post.glyphNameIndex[i] = p.parseUShort();
35797            }
35798
35799            post.names = [];
35800            for (var i$1 = 0; i$1 < post.numberOfGlyphs; i$1++) {
35801                if (post.glyphNameIndex[i$1] >= standardNames.length) {
35802                    var nameLength = p.parseChar();
35803                    post.names.push(p.parseString(nameLength));
35804                }
35805            }
35806
35807            break;
35808        case 2.5:
35809            post.numberOfGlyphs = p.parseUShort();
35810            post.offset = new Array(post.numberOfGlyphs);
35811            for (var i$2 = 0; i$2 < post.numberOfGlyphs; i$2++) {
35812                post.offset[i$2] = p.parseChar();
35813            }
35814
35815            break;
35816    }
35817    return post;
35818}
35819
35820function makePostTable() {
35821    return new table.Table('post', [
35822        {name: 'version', type: 'FIXED', value: 0x00030000},
35823        {name: 'italicAngle', type: 'FIXED', value: 0},
35824        {name: 'underlinePosition', type: 'FWORD', value: 0},
35825        {name: 'underlineThickness', type: 'FWORD', value: 0},
35826        {name: 'isFixedPitch', type: 'ULONG', value: 0},
35827        {name: 'minMemType42', type: 'ULONG', value: 0},
35828        {name: 'maxMemType42', type: 'ULONG', value: 0},
35829        {name: 'minMemType1', type: 'ULONG', value: 0},
35830        {name: 'maxMemType1', type: 'ULONG', value: 0}
35831    ]);
35832}
35833
35834var post = { parse: parsePostTable, make: makePostTable };
35835
35836// The `GSUB` table contains ligatures, among other things.
35837// https://www.microsoft.com/typography/OTSPEC/gsub.htm
35838
35839var subtableParsers = new Array(9);         // subtableParsers[0] is unused
35840
35841// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#SS
35842subtableParsers[1] = function parseLookup1() {
35843    var start = this.offset + this.relativeOffset;
35844    var substFormat = this.parseUShort();
35845    if (substFormat === 1) {
35846        return {
35847            substFormat: 1,
35848            coverage: this.parsePointer(Parser.coverage),
35849            deltaGlyphId: this.parseUShort()
35850        };
35851    } else if (substFormat === 2) {
35852        return {
35853            substFormat: 2,
35854            coverage: this.parsePointer(Parser.coverage),
35855            substitute: this.parseOffset16List()
35856        };
35857    }
35858    check.assert(false, '0x' + start.toString(16) + ': lookup type 1 format must be 1 or 2.');
35859};
35860
35861// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#MS
35862subtableParsers[2] = function parseLookup2() {
35863    var substFormat = this.parseUShort();
35864    check.argument(substFormat === 1, 'GSUB Multiple Substitution Subtable identifier-format must be 1');
35865    return {
35866        substFormat: substFormat,
35867        coverage: this.parsePointer(Parser.coverage),
35868        sequences: this.parseListOfLists()
35869    };
35870};
35871
35872// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#AS
35873subtableParsers[3] = function parseLookup3() {
35874    var substFormat = this.parseUShort();
35875    check.argument(substFormat === 1, 'GSUB Alternate Substitution Subtable identifier-format must be 1');
35876    return {
35877        substFormat: substFormat,
35878        coverage: this.parsePointer(Parser.coverage),
35879        alternateSets: this.parseListOfLists()
35880    };
35881};
35882
35883// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#LS
35884subtableParsers[4] = function parseLookup4() {
35885    var substFormat = this.parseUShort();
35886    check.argument(substFormat === 1, 'GSUB ligature table identifier-format must be 1');
35887    return {
35888        substFormat: substFormat,
35889        coverage: this.parsePointer(Parser.coverage),
35890        ligatureSets: this.parseListOfLists(function() {
35891            return {
35892                ligGlyph: this.parseUShort(),
35893                components: this.parseUShortList(this.parseUShort() - 1)
35894            };
35895        })
35896    };
35897};
35898
35899var lookupRecordDesc = {
35900    sequenceIndex: Parser.uShort,
35901    lookupListIndex: Parser.uShort
35902};
35903
35904// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#CSF
35905subtableParsers[5] = function parseLookup5() {
35906    var start = this.offset + this.relativeOffset;
35907    var substFormat = this.parseUShort();
35908
35909    if (substFormat === 1) {
35910        return {
35911            substFormat: substFormat,
35912            coverage: this.parsePointer(Parser.coverage),
35913            ruleSets: this.parseListOfLists(function() {
35914                var glyphCount = this.parseUShort();
35915                var substCount = this.parseUShort();
35916                return {
35917                    input: this.parseUShortList(glyphCount - 1),
35918                    lookupRecords: this.parseRecordList(substCount, lookupRecordDesc)
35919                };
35920            })
35921        };
35922    } else if (substFormat === 2) {
35923        return {
35924            substFormat: substFormat,
35925            coverage: this.parsePointer(Parser.coverage),
35926            classDef: this.parsePointer(Parser.classDef),
35927            classSets: this.parseListOfLists(function() {
35928                var glyphCount = this.parseUShort();
35929                var substCount = this.parseUShort();
35930                return {
35931                    classes: this.parseUShortList(glyphCount - 1),
35932                    lookupRecords: this.parseRecordList(substCount, lookupRecordDesc)
35933                };
35934            })
35935        };
35936    } else if (substFormat === 3) {
35937        var glyphCount = this.parseUShort();
35938        var substCount = this.parseUShort();
35939        return {
35940            substFormat: substFormat,
35941            coverages: this.parseList(glyphCount, Parser.pointer(Parser.coverage)),
35942            lookupRecords: this.parseRecordList(substCount, lookupRecordDesc)
35943        };
35944    }
35945    check.assert(false, '0x' + start.toString(16) + ': lookup type 5 format must be 1, 2 or 3.');
35946};
35947
35948// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#CC
35949subtableParsers[6] = function parseLookup6() {
35950    var start = this.offset + this.relativeOffset;
35951    var substFormat = this.parseUShort();
35952    if (substFormat === 1) {
35953        return {
35954            substFormat: 1,
35955            coverage: this.parsePointer(Parser.coverage),
35956            chainRuleSets: this.parseListOfLists(function() {
35957                return {
35958                    backtrack: this.parseUShortList(),
35959                    input: this.parseUShortList(this.parseShort() - 1),
35960                    lookahead: this.parseUShortList(),
35961                    lookupRecords: this.parseRecordList(lookupRecordDesc)
35962                };
35963            })
35964        };
35965    } else if (substFormat === 2) {
35966        return {
35967            substFormat: 2,
35968            coverage: this.parsePointer(Parser.coverage),
35969            backtrackClassDef: this.parsePointer(Parser.classDef),
35970            inputClassDef: this.parsePointer(Parser.classDef),
35971            lookaheadClassDef: this.parsePointer(Parser.classDef),
35972            chainClassSet: this.parseListOfLists(function() {
35973                return {
35974                    backtrack: this.parseUShortList(),
35975                    input: this.parseUShortList(this.parseShort() - 1),
35976                    lookahead: this.parseUShortList(),
35977                    lookupRecords: this.parseRecordList(lookupRecordDesc)
35978                };
35979            })
35980        };
35981    } else if (substFormat === 3) {
35982        return {
35983            substFormat: 3,
35984            backtrackCoverage: this.parseList(Parser.pointer(Parser.coverage)),
35985            inputCoverage: this.parseList(Parser.pointer(Parser.coverage)),
35986            lookaheadCoverage: this.parseList(Parser.pointer(Parser.coverage)),
35987            lookupRecords: this.parseRecordList(lookupRecordDesc)
35988        };
35989    }
35990    check.assert(false, '0x' + start.toString(16) + ': lookup type 6 format must be 1, 2 or 3.');
35991};
35992
35993// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#ES
35994subtableParsers[7] = function parseLookup7() {
35995    // Extension Substitution subtable
35996    var substFormat = this.parseUShort();
35997    check.argument(substFormat === 1, 'GSUB Extension Substitution subtable identifier-format must be 1');
35998    var extensionLookupType = this.parseUShort();
35999    var extensionParser = new Parser(this.data, this.offset + this.parseULong());
36000    return {
36001        substFormat: 1,
36002        lookupType: extensionLookupType,
36003        extension: subtableParsers[extensionLookupType].call(extensionParser)
36004    };
36005};
36006
36007// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#RCCS
36008subtableParsers[8] = function parseLookup8() {
36009    var substFormat = this.parseUShort();
36010    check.argument(substFormat === 1, 'GSUB Reverse Chaining Contextual Single Substitution Subtable identifier-format must be 1');
36011    return {
36012        substFormat: substFormat,
36013        coverage: this.parsePointer(Parser.coverage),
36014        backtrackCoverage: this.parseList(Parser.pointer(Parser.coverage)),
36015        lookaheadCoverage: this.parseList(Parser.pointer(Parser.coverage)),
36016        substitutes: this.parseUShortList()
36017    };
36018};
36019
36020// https://www.microsoft.com/typography/OTSPEC/gsub.htm
36021function parseGsubTable(data, start) {
36022    start = start || 0;
36023    var p = new Parser(data, start);
36024    var tableVersion = p.parseVersion();
36025    check.argument(tableVersion === 1, 'Unsupported GSUB table version.');
36026    return {
36027        version: tableVersion,
36028        scripts: p.parseScriptList(),
36029        features: p.parseFeatureList(),
36030        lookups: p.parseLookupList(subtableParsers)
36031    };
36032}
36033
36034// GSUB Writing //////////////////////////////////////////////
36035var subtableMakers = new Array(9);
36036
36037subtableMakers[1] = function makeLookup1(subtable) {
36038    if (subtable.substFormat === 1) {
36039        return new table.Table('substitutionTable', [
36040            {name: 'substFormat', type: 'USHORT', value: 1},
36041            {name: 'coverage', type: 'TABLE', value: new table.Coverage(subtable.coverage)},
36042            {name: 'deltaGlyphID', type: 'USHORT', value: subtable.deltaGlyphId}
36043        ]);
36044    } else {
36045        return new table.Table('substitutionTable', [
36046            {name: 'substFormat', type: 'USHORT', value: 2},
36047            {name: 'coverage', type: 'TABLE', value: new table.Coverage(subtable.coverage)}
36048        ].concat(table.ushortList('substitute', subtable.substitute)));
36049    }
36050    check.fail('Lookup type 1 substFormat must be 1 or 2.');
36051};
36052
36053subtableMakers[3] = function makeLookup3(subtable) {
36054    check.assert(subtable.substFormat === 1, 'Lookup type 3 substFormat must be 1.');
36055    return new table.Table('substitutionTable', [
36056        {name: 'substFormat', type: 'USHORT', value: 1},
36057        {name: 'coverage', type: 'TABLE', value: new table.Coverage(subtable.coverage)}
36058    ].concat(table.tableList('altSet', subtable.alternateSets, function(alternateSet) {
36059        return new table.Table('alternateSetTable', table.ushortList('alternate', alternateSet));
36060    })));
36061};
36062
36063subtableMakers[4] = function makeLookup4(subtable) {
36064    check.assert(subtable.substFormat === 1, 'Lookup type 4 substFormat must be 1.');
36065    return new table.Table('substitutionTable', [
36066        {name: 'substFormat', type: 'USHORT', value: 1},
36067        {name: 'coverage', type: 'TABLE', value: new table.Coverage(subtable.coverage)}
36068    ].concat(table.tableList('ligSet', subtable.ligatureSets, function(ligatureSet) {
36069        return new table.Table('ligatureSetTable', table.tableList('ligature', ligatureSet, function(ligature) {
36070            return new table.Table('ligatureTable',
36071                [{name: 'ligGlyph', type: 'USHORT', value: ligature.ligGlyph}]
36072                .concat(table.ushortList('component', ligature.components, ligature.components.length + 1))
36073            );
36074        }));
36075    })));
36076};
36077
36078function makeGsubTable(gsub) {
36079    return new table.Table('GSUB', [
36080        {name: 'version', type: 'ULONG', value: 0x10000},
36081        {name: 'scripts', type: 'TABLE', value: new table.ScriptList(gsub.scripts)},
36082        {name: 'features', type: 'TABLE', value: new table.FeatureList(gsub.features)},
36083        {name: 'lookups', type: 'TABLE', value: new table.LookupList(gsub.lookups, subtableMakers)}
36084    ]);
36085}
36086
36087var gsub = { parse: parseGsubTable, make: makeGsubTable };
36088
36089// The `GPOS` table contains kerning pairs, among other things.
36090// https://www.microsoft.com/typography/OTSPEC/gpos.htm
36091
36092// Parse the metadata `meta` table.
36093// https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6meta.html
36094function parseMetaTable(data, start) {
36095    var p = new parse.Parser(data, start);
36096    var tableVersion = p.parseULong();
36097    check.argument(tableVersion === 1, 'Unsupported META table version.');
36098    p.parseULong(); // flags - currently unused and set to 0
36099    p.parseULong(); // tableOffset
36100    var numDataMaps = p.parseULong();
36101
36102    var tags = {};
36103    for (var i = 0; i < numDataMaps; i++) {
36104        var tag = p.parseTag();
36105        var dataOffset = p.parseULong();
36106        var dataLength = p.parseULong();
36107        var text = decode.UTF8(data, start + dataOffset, dataLength);
36108
36109        tags[tag] = text;
36110    }
36111    return tags;
36112}
36113
36114function makeMetaTable(tags) {
36115    var numTags = Object.keys(tags).length;
36116    var stringPool = '';
36117    var stringPoolOffset = 16 + numTags * 12;
36118
36119    var result = new table.Table('meta', [
36120        {name: 'version', type: 'ULONG', value: 1},
36121        {name: 'flags', type: 'ULONG', value: 0},
36122        {name: 'offset', type: 'ULONG', value: stringPoolOffset},
36123        {name: 'numTags', type: 'ULONG', value: numTags}
36124    ]);
36125
36126    for (var tag in tags) {
36127        var pos = stringPool.length;
36128        stringPool += tags[tag];
36129
36130        result.fields.push({name: 'tag ' + tag, type: 'TAG', value: tag});
36131        result.fields.push({name: 'offset ' + tag, type: 'ULONG', value: stringPoolOffset + pos});
36132        result.fields.push({name: 'length ' + tag, type: 'ULONG', value: tags[tag].length});
36133    }
36134
36135    result.fields.push({name: 'stringPool', type: 'CHARARRAY', value: stringPool});
36136
36137    return result;
36138}
36139
36140var meta = { parse: parseMetaTable, make: makeMetaTable };
36141
36142// The `sfnt` wrapper provides organization for the tables in the font.
36143// It is the top-level data structure in a font.
36144// https://www.microsoft.com/typography/OTSPEC/otff.htm
36145// Recommendations for creating OpenType Fonts:
36146// http://www.microsoft.com/typography/otspec140/recom.htm
36147
36148function log2(v) {
36149    return Math.log(v) / Math.log(2) | 0;
36150}
36151
36152function computeCheckSum(bytes) {
36153    while (bytes.length % 4 !== 0) {
36154        bytes.push(0);
36155    }
36156
36157    var sum = 0;
36158    for (var i = 0; i < bytes.length; i += 4) {
36159        sum += (bytes[i] << 24) +
36160            (bytes[i + 1] << 16) +
36161            (bytes[i + 2] << 8) +
36162            (bytes[i + 3]);
36163    }
36164
36165    sum %= Math.pow(2, 32);
36166    return sum;
36167}
36168
36169function makeTableRecord(tag, checkSum, offset, length) {
36170    return new table.Record('Table Record', [
36171        {name: 'tag', type: 'TAG', value: tag !== undefined ? tag : ''},
36172        {name: 'checkSum', type: 'ULONG', value: checkSum !== undefined ? checkSum : 0},
36173        {name: 'offset', type: 'ULONG', value: offset !== undefined ? offset : 0},
36174        {name: 'length', type: 'ULONG', value: length !== undefined ? length : 0}
36175    ]);
36176}
36177
36178function makeSfntTable(tables) {
36179    var sfnt = new table.Table('sfnt', [
36180        {name: 'version', type: 'TAG', value: 'OTTO'},
36181        {name: 'numTables', type: 'USHORT', value: 0},
36182        {name: 'searchRange', type: 'USHORT', value: 0},
36183        {name: 'entrySelector', type: 'USHORT', value: 0},
36184        {name: 'rangeShift', type: 'USHORT', value: 0}
36185    ]);
36186    sfnt.tables = tables;
36187    sfnt.numTables = tables.length;
36188    var highestPowerOf2 = Math.pow(2, log2(sfnt.numTables));
36189    sfnt.searchRange = 16 * highestPowerOf2;
36190    sfnt.entrySelector = log2(highestPowerOf2);
36191    sfnt.rangeShift = sfnt.numTables * 16 - sfnt.searchRange;
36192
36193    var recordFields = [];
36194    var tableFields = [];
36195
36196    var offset = sfnt.sizeOf() + (makeTableRecord().sizeOf() * sfnt.numTables);
36197    while (offset % 4 !== 0) {
36198        offset += 1;
36199        tableFields.push({name: 'padding', type: 'BYTE', value: 0});
36200    }
36201
36202    for (var i = 0; i < tables.length; i += 1) {
36203        var t = tables[i];
36204        check.argument(t.tableName.length === 4, 'Table name' + t.tableName + ' is invalid.');
36205        var tableLength = t.sizeOf();
36206        var tableRecord = makeTableRecord(t.tableName, computeCheckSum(t.encode()), offset, tableLength);
36207        recordFields.push({name: tableRecord.tag + ' Table Record', type: 'RECORD', value: tableRecord});
36208        tableFields.push({name: t.tableName + ' table', type: 'RECORD', value: t});
36209        offset += tableLength;
36210        check.argument(!isNaN(offset), 'Something went wrong calculating the offset.');
36211        while (offset % 4 !== 0) {
36212            offset += 1;
36213            tableFields.push({name: 'padding', type: 'BYTE', value: 0});
36214        }
36215    }
36216
36217    // Table records need to be sorted alphabetically.
36218    recordFields.sort(function(r1, r2) {
36219        if (r1.value.tag > r2.value.tag) {
36220            return 1;
36221        } else {
36222            return -1;
36223        }
36224    });
36225
36226    sfnt.fields = sfnt.fields.concat(recordFields);
36227    sfnt.fields = sfnt.fields.concat(tableFields);
36228    return sfnt;
36229}
36230
36231// Get the metrics for a character. If the string has more than one character
36232// this function returns metrics for the first available character.
36233// You can provide optional fallback metrics if no characters are available.
36234function metricsForChar(font, chars, notFoundMetrics) {
36235    for (var i = 0; i < chars.length; i += 1) {
36236        var glyphIndex = font.charToGlyphIndex(chars[i]);
36237        if (glyphIndex > 0) {
36238            var glyph = font.glyphs.get(glyphIndex);
36239            return glyph.getMetrics();
36240        }
36241    }
36242
36243    return notFoundMetrics;
36244}
36245
36246function average(vs) {
36247    var sum = 0;
36248    for (var i = 0; i < vs.length; i += 1) {
36249        sum += vs[i];
36250    }
36251
36252    return sum / vs.length;
36253}
36254
36255// Convert the font object to a SFNT data structure.
36256// This structure contains all the necessary tables and metadata to create a binary OTF file.
36257function fontToSfntTable(font) {
36258    var xMins = [];
36259    var yMins = [];
36260    var xMaxs = [];
36261    var yMaxs = [];
36262    var advanceWidths = [];
36263    var leftSideBearings = [];
36264    var rightSideBearings = [];
36265    var firstCharIndex;
36266    var lastCharIndex = 0;
36267    var ulUnicodeRange1 = 0;
36268    var ulUnicodeRange2 = 0;
36269    var ulUnicodeRange3 = 0;
36270    var ulUnicodeRange4 = 0;
36271
36272    for (var i = 0; i < font.glyphs.length; i += 1) {
36273        var glyph = font.glyphs.get(i);
36274        var unicode = glyph.unicode | 0;
36275
36276        if (isNaN(glyph.advanceWidth)) {
36277            throw new Error('Glyph ' + glyph.name + ' (' + i + '): advanceWidth is not a number.');
36278        }
36279
36280        if (firstCharIndex > unicode || firstCharIndex === undefined) {
36281            // ignore .notdef char
36282            if (unicode > 0) {
36283                firstCharIndex = unicode;
36284            }
36285        }
36286
36287        if (lastCharIndex < unicode) {
36288            lastCharIndex = unicode;
36289        }
36290
36291        var position = os2.getUnicodeRange(unicode);
36292        if (position < 32) {
36293            ulUnicodeRange1 |= 1 << position;
36294        } else if (position < 64) {
36295            ulUnicodeRange2 |= 1 << position - 32;
36296        } else if (position < 96) {
36297            ulUnicodeRange3 |= 1 << position - 64;
36298        } else if (position < 123) {
36299            ulUnicodeRange4 |= 1 << position - 96;
36300        } else {
36301            throw new Error('Unicode ranges bits > 123 are reserved for internal usage');
36302        }
36303        // Skip non-important characters.
36304        if (glyph.name === '.notdef') { continue; }
36305        var metrics = glyph.getMetrics();
36306        xMins.push(metrics.xMin);
36307        yMins.push(metrics.yMin);
36308        xMaxs.push(metrics.xMax);
36309        yMaxs.push(metrics.yMax);
36310        leftSideBearings.push(metrics.leftSideBearing);
36311        rightSideBearings.push(metrics.rightSideBearing);
36312        advanceWidths.push(glyph.advanceWidth);
36313    }
36314
36315    var globals = {
36316        xMin: Math.min.apply(null, xMins),
36317        yMin: Math.min.apply(null, yMins),
36318        xMax: Math.max.apply(null, xMaxs),
36319        yMax: Math.max.apply(null, yMaxs),
36320        advanceWidthMax: Math.max.apply(null, advanceWidths),
36321        advanceWidthAvg: average(advanceWidths),
36322        minLeftSideBearing: Math.min.apply(null, leftSideBearings),
36323        maxLeftSideBearing: Math.max.apply(null, leftSideBearings),
36324        minRightSideBearing: Math.min.apply(null, rightSideBearings)
36325    };
36326    globals.ascender = font.ascender;
36327    globals.descender = font.descender;
36328
36329    var headTable = head.make({
36330        flags: 3, // 00000011 (baseline for font at y=0; left sidebearing point at x=0)
36331        unitsPerEm: font.unitsPerEm,
36332        xMin: globals.xMin,
36333        yMin: globals.yMin,
36334        xMax: globals.xMax,
36335        yMax: globals.yMax,
36336        lowestRecPPEM: 3,
36337        createdTimestamp: font.createdTimestamp
36338    });
36339
36340    var hheaTable = hhea.make({
36341        ascender: globals.ascender,
36342        descender: globals.descender,
36343        advanceWidthMax: globals.advanceWidthMax,
36344        minLeftSideBearing: globals.minLeftSideBearing,
36345        minRightSideBearing: globals.minRightSideBearing,
36346        xMaxExtent: globals.maxLeftSideBearing + (globals.xMax - globals.xMin),
36347        numberOfHMetrics: font.glyphs.length
36348    });
36349
36350    var maxpTable = maxp.make(font.glyphs.length);
36351
36352    var os2Table = os2.make({
36353        xAvgCharWidth: Math.round(globals.advanceWidthAvg),
36354        usWeightClass: font.tables.os2.usWeightClass,
36355        usWidthClass: font.tables.os2.usWidthClass,
36356        usFirstCharIndex: firstCharIndex,
36357        usLastCharIndex: lastCharIndex,
36358        ulUnicodeRange1: ulUnicodeRange1,
36359        ulUnicodeRange2: ulUnicodeRange2,
36360        ulUnicodeRange3: ulUnicodeRange3,
36361        ulUnicodeRange4: ulUnicodeRange4,
36362        fsSelection: font.tables.os2.fsSelection, // REGULAR
36363        // See http://typophile.com/node/13081 for more info on vertical metrics.
36364        // We get metrics for typical characters (such as "x" for xHeight).
36365        // We provide some fallback characters if characters are unavailable: their
36366        // ordering was chosen experimentally.
36367        sTypoAscender: globals.ascender,
36368        sTypoDescender: globals.descender,
36369        sTypoLineGap: 0,
36370        usWinAscent: globals.yMax,
36371        usWinDescent: Math.abs(globals.yMin),
36372        ulCodePageRange1: 1, // FIXME: hard-code Latin 1 support for now
36373        sxHeight: metricsForChar(font, 'xyvw', {yMax: Math.round(globals.ascender / 2)}).yMax,
36374        sCapHeight: metricsForChar(font, 'HIKLEFJMNTZBDPRAGOQSUVWXY', globals).yMax,
36375        usDefaultChar: font.hasChar(' ') ? 32 : 0, // Use space as the default character, if available.
36376        usBreakChar: font.hasChar(' ') ? 32 : 0 // Use space as the break character, if available.
36377    });
36378
36379    var hmtxTable = hmtx.make(font.glyphs);
36380    var cmapTable = cmap.make(font.glyphs);
36381
36382    var englishFamilyName = font.getEnglishName('fontFamily');
36383    var englishStyleName = font.getEnglishName('fontSubfamily');
36384    var englishFullName = englishFamilyName + ' ' + englishStyleName;
36385    var postScriptName = font.getEnglishName('postScriptName');
36386    if (!postScriptName) {
36387        postScriptName = englishFamilyName.replace(/\s/g, '') + '-' + englishStyleName;
36388    }
36389
36390    var names = {};
36391    for (var n in font.names) {
36392        names[n] = font.names[n];
36393    }
36394
36395    if (!names.uniqueID) {
36396        names.uniqueID = {en: font.getEnglishName('manufacturer') + ':' + englishFullName};
36397    }
36398
36399    if (!names.postScriptName) {
36400        names.postScriptName = {en: postScriptName};
36401    }
36402
36403    if (!names.preferredFamily) {
36404        names.preferredFamily = font.names.fontFamily;
36405    }
36406
36407    if (!names.preferredSubfamily) {
36408        names.preferredSubfamily = font.names.fontSubfamily;
36409    }
36410
36411    var languageTags = [];
36412    var nameTable = _name.make(names, languageTags);
36413    var ltagTable = (languageTags.length > 0 ? ltag.make(languageTags) : undefined);
36414
36415    var postTable = post.make();
36416    var cffTable = cff.make(font.glyphs, {
36417        version: font.getEnglishName('version'),
36418        fullName: englishFullName,
36419        familyName: englishFamilyName,
36420        weightName: englishStyleName,
36421        postScriptName: postScriptName,
36422        unitsPerEm: font.unitsPerEm,
36423        fontBBox: [0, globals.yMin, globals.ascender, globals.advanceWidthMax]
36424    });
36425
36426    var metaTable = (font.metas && Object.keys(font.metas).length > 0) ? meta.make(font.metas) : undefined;
36427
36428    // The order does not matter because makeSfntTable() will sort them.
36429    var tables = [headTable, hheaTable, maxpTable, os2Table, nameTable, cmapTable, postTable, cffTable, hmtxTable];
36430    if (ltagTable) {
36431        tables.push(ltagTable);
36432    }
36433    // Optional tables
36434    if (font.tables.gsub) {
36435        tables.push(gsub.make(font.tables.gsub));
36436    }
36437    if (metaTable) {
36438        tables.push(metaTable);
36439    }
36440
36441    var sfntTable = makeSfntTable(tables);
36442
36443    // Compute the font's checkSum and store it in head.checkSumAdjustment.
36444    var bytes = sfntTable.encode();
36445    var checkSum = computeCheckSum(bytes);
36446    var tableFields = sfntTable.fields;
36447    var checkSumAdjusted = false;
36448    for (var i$1 = 0; i$1 < tableFields.length; i$1 += 1) {
36449        if (tableFields[i$1].name === 'head table') {
36450            tableFields[i$1].value.checkSumAdjustment = 0xB1B0AFBA - checkSum;
36451            checkSumAdjusted = true;
36452            break;
36453        }
36454    }
36455
36456    if (!checkSumAdjusted) {
36457        throw new Error('Could not find head table with checkSum to adjust.');
36458    }
36459
36460    return sfntTable;
36461}
36462
36463var sfnt = { make: makeSfntTable, fontToTable: fontToSfntTable, computeCheckSum: computeCheckSum };
36464
36465// The Layout object is the prototype of Substitution objects, and provides
36466// utility methods to manipulate common layout tables (GPOS, GSUB, GDEF...)
36467
36468function searchTag(arr, tag) {
36469    /* jshint bitwise: false */
36470    var imin = 0;
36471    var imax = arr.length - 1;
36472    while (imin <= imax) {
36473        var imid = (imin + imax) >>> 1;
36474        var val = arr[imid].tag;
36475        if (val === tag) {
36476            return imid;
36477        } else if (val < tag) {
36478            imin = imid + 1;
36479        } else { imax = imid - 1; }
36480    }
36481    // Not found: return -1-insertion point
36482    return -imin - 1;
36483}
36484
36485function binSearch(arr, value) {
36486    /* jshint bitwise: false */
36487    var imin = 0;
36488    var imax = arr.length - 1;
36489    while (imin <= imax) {
36490        var imid = (imin + imax) >>> 1;
36491        var val = arr[imid];
36492        if (val === value) {
36493            return imid;
36494        } else if (val < value) {
36495            imin = imid + 1;
36496        } else { imax = imid - 1; }
36497    }
36498    // Not found: return -1-insertion point
36499    return -imin - 1;
36500}
36501
36502/**
vendor: 18,362 bytes, lines 36503-37005
36503 * @exports opentype.Layout
36504 * @class
36505 */
36506function Layout(font, tableName) {
36507    this.font = font;
36508    this.tableName = tableName;
36509}
36510
36511Layout.prototype = {
36512
36513    /**
36514     * Binary search an object by "tag" property
36515     * @instance
36516     * @function searchTag
36517     * @memberof opentype.Layout
36518     * @param  {Array} arr
36519     * @param  {string} tag
36520     * @return {number}
36521     */
36522    searchTag: searchTag,
36523
36524    /**
36525     * Binary search in a list of numbers
36526     * @instance
36527     * @function binSearch
36528     * @memberof opentype.Layout
36529     * @param  {Array} arr
36530     * @param  {number} value
36531     * @return {number}
36532     */
36533    binSearch: binSearch,
36534
36535    /**
36536     * Get or create the Layout table (GSUB, GPOS etc).
36537     * @param  {boolean} create - Whether to create a new one.
36538     * @return {Object} The GSUB or GPOS table.
36539     */
36540    getTable: function(create) {
36541        var layout = this.font.tables[this.tableName];
36542        if (!layout && create) {
36543            layout = this.font.tables[this.tableName] = this.createDefaultTable();
36544        }
36545        return layout;
36546    },
36547
36548    /**
36549     * Returns all scripts in the substitution table.
36550     * @instance
36551     * @return {Array}
36552     */
36553    getScriptNames: function() {
36554        var layout = this.getTable();
36555        if (!layout) { return []; }
36556        return layout.scripts.map(function(script) {
36557            return script.tag;
36558        });
36559    },
36560
36561    /**
36562     * Returns the best bet for a script name.
36563     * Returns 'DFLT' if it exists.
36564     * If not, returns 'latn' if it exists.
36565     * If neither exist, returns undefined.
36566     */
36567    getDefaultScriptName: function() {
36568        var layout = this.getTable();
36569        if (!layout) { return; }
36570        var hasLatn = false;
36571        for (var i = 0; i < layout.scripts.length; i++) {
36572            var name = layout.scripts[i].tag;
36573            if (name === 'DFLT') { return name; }
36574            if (name === 'latn') { hasLatn = true; }
36575        }
36576        if (hasLatn) { return 'latn'; }
36577    },
36578
36579    /**
36580     * Returns all LangSysRecords in the given script.
36581     * @instance
36582     * @param {string} [script='DFLT']
36583     * @param {boolean} create - forces the creation of this script table if it doesn't exist.
36584     * @return {Object} An object with tag and script properties.
36585     */
36586    getScriptTable: function(script, create) {
36587        var layout = this.getTable(create);
36588        if (layout) {
36589            script = script || 'DFLT';
36590            var scripts = layout.scripts;
36591            var pos = searchTag(layout.scripts, script);
36592            if (pos >= 0) {
36593                return scripts[pos].script;
36594            } else if (create) {
36595                var scr = {
36596                    tag: script,
36597                    script: {
36598                        defaultLangSys: {reserved: 0, reqFeatureIndex: 0xffff, featureIndexes: []},
36599                        langSysRecords: []
36600                    }
36601                };
36602                scripts.splice(-1 - pos, 0, scr);
36603                return scr.script;
36604            }
36605        }
36606    },
36607
36608    /**
36609     * Returns a language system table
36610     * @instance
36611     * @param {string} [script='DFLT']
36612     * @param {string} [language='dlft']
36613     * @param {boolean} create - forces the creation of this langSysTable if it doesn't exist.
36614     * @return {Object}
36615     */
36616    getLangSysTable: function(script, language, create) {
36617        var scriptTable = this.getScriptTable(script, create);
36618        if (scriptTable) {
36619            if (!language || language === 'dflt' || language === 'DFLT') {
36620                return scriptTable.defaultLangSys;
36621            }
36622            var pos = searchTag(scriptTable.langSysRecords, language);
36623            if (pos >= 0) {
36624                return scriptTable.langSysRecords[pos].langSys;
36625            } else if (create) {
36626                var langSysRecord = {
36627                    tag: language,
36628                    langSys: {reserved: 0, reqFeatureIndex: 0xffff, featureIndexes: []}
36629                };
36630                scriptTable.langSysRecords.splice(-1 - pos, 0, langSysRecord);
36631                return langSysRecord.langSys;
36632            }
36633        }
36634    },
36635
36636    /**
36637     * Get a specific feature table.
36638     * @instance
36639     * @param {string} [script='DFLT']
36640     * @param {string} [language='dlft']
36641     * @param {string} feature - One of the codes listed at https://www.microsoft.com/typography/OTSPEC/featurelist.htm
36642     * @param {boolean} create - forces the creation of the feature table if it doesn't exist.
36643     * @return {Object}
36644     */
36645    getFeatureTable: function(script, language, feature, create) {
36646        var langSysTable = this.getLangSysTable(script, language, create);
36647        if (langSysTable) {
36648            var featureRecord;
36649            var featIndexes = langSysTable.featureIndexes;
36650            var allFeatures = this.font.tables[this.tableName].features;
36651            // The FeatureIndex array of indices is in arbitrary order,
36652            // even if allFeatures is sorted alphabetically by feature tag.
36653            for (var i = 0; i < featIndexes.length; i++) {
36654                featureRecord = allFeatures[featIndexes[i]];
36655                if (featureRecord.tag === feature) {
36656                    return featureRecord.feature;
36657                }
36658            }
36659            if (create) {
36660                var index = allFeatures.length;
36661                // Automatic ordering of features would require to shift feature indexes in the script list.
36662                check.assert(index === 0 || feature >= allFeatures[index - 1].tag, 'Features must be added in alphabetical order.');
36663                featureRecord = {
36664                    tag: feature,
36665                    feature: { params: 0, lookupListIndexes: [] }
36666                };
36667                allFeatures.push(featureRecord);
36668                featIndexes.push(index);
36669                return featureRecord.feature;
36670            }
36671        }
36672    },
36673
36674    /**
36675     * Get the lookup tables of a given type for a script/language/feature.
36676     * @instance
36677     * @param {string} [script='DFLT']
36678     * @param {string} [language='dlft']
36679     * @param {string} feature - 4-letter feature code
36680     * @param {number} lookupType - 1 to 8
36681     * @param {boolean} create - forces the creation of the lookup table if it doesn't exist, with no subtables.
36682     * @return {Object[]}
36683     */
36684    getLookupTables: function(script, language, feature, lookupType, create) {
36685        var featureTable = this.getFeatureTable(script, language, feature, create);
36686        var tables = [];
36687        if (featureTable) {
36688            var lookupTable;
36689            var lookupListIndexes = featureTable.lookupListIndexes;
36690            var allLookups = this.font.tables[this.tableName].lookups;
36691            // lookupListIndexes are in no particular order, so use naive search.
36692            for (var i = 0; i < lookupListIndexes.length; i++) {
36693                lookupTable = allLookups[lookupListIndexes[i]];
36694                if (lookupTable.lookupType === lookupType) {
36695                    tables.push(lookupTable);
36696                }
36697            }
36698            if (tables.length === 0 && create) {
36699                lookupTable = {
36700                    lookupType: lookupType,
36701                    lookupFlag: 0,
36702                    subtables: [],
36703                    markFilteringSet: undefined
36704                };
36705                var index = allLookups.length;
36706                allLookups.push(lookupTable);
36707                lookupListIndexes.push(index);
36708                return [lookupTable];
36709            }
36710        }
36711        return tables;
36712    },
36713
36714    /**
36715     * Returns the list of glyph indexes of a coverage table.
36716     * Format 1: the list is stored raw
36717     * Format 2: compact list as range records.
36718     * @instance
36719     * @param  {Object} coverageTable
36720     * @return {Array}
36721     */
36722    expandCoverage: function(coverageTable) {
36723        if (coverageTable.format === 1) {
36724            return coverageTable.glyphs;
36725        } else {
36726            var glyphs = [];
36727            var ranges = coverageTable.ranges;
36728            for (var i = 0; i < ranges.length; i++) {
36729                var range = ranges[i];
36730                var start = range.start;
36731                var end = range.end;
36732                for (var j = start; j <= end; j++) {
36733                    glyphs.push(j);
36734                }
36735            }
36736            return glyphs;
36737        }
36738    }
36739
36740};
36741
36742// The Substitution object provides utility methods to manipulate
36743// the GSUB substitution table.
36744
36745/**
36746 * @exports opentype.Substitution
36747 * @class
36748 * @extends opentype.Layout
36749 * @param {opentype.Font}
36750 * @constructor
36751 */
36752function Substitution(font) {
36753    Layout.call(this, font, 'gsub');
36754}
36755
36756// Check if 2 arrays of primitives are equal.
36757function arraysEqual(ar1, ar2) {
36758    var n = ar1.length;
36759    if (n !== ar2.length) { return false; }
36760    for (var i = 0; i < n; i++) {
36761        if (ar1[i] !== ar2[i]) { return false; }
36762    }
36763    return true;
36764}
36765
36766// Find the first subtable of a lookup table in a particular format.
36767function getSubstFormat(lookupTable, format, defaultSubtable) {
36768    var subtables = lookupTable.subtables;
36769    for (var i = 0; i < subtables.length; i++) {
36770        var subtable = subtables[i];
36771        if (subtable.substFormat === format) {
36772            return subtable;
36773        }
36774    }
36775    if (defaultSubtable) {
36776        subtables.push(defaultSubtable);
36777        return defaultSubtable;
36778    }
36779    return undefined;
36780}
36781
36782Substitution.prototype = Layout.prototype;
36783
36784/**
36785 * Create a default GSUB table.
36786 * @return {Object} gsub - The GSUB table.
36787 */
36788Substitution.prototype.createDefaultTable = function() {
36789    // Generate a default empty GSUB table with just a DFLT script and dflt lang sys.
36790    return {
36791        version: 1,
36792        scripts: [{
36793            tag: 'DFLT',
36794            script: {
36795                defaultLangSys: { reserved: 0, reqFeatureIndex: 0xffff, featureIndexes: [] },
36796                langSysRecords: []
36797            }
36798        }],
36799        features: [],
36800        lookups: []
36801    };
36802};
36803
36804/**
36805 * List all single substitutions (lookup type 1) for a given script, language, and feature.
36806 * @param {string} [script='DFLT']
36807 * @param {string} [language='dflt']
36808 * @param {string} feature - 4-character feature name ('aalt', 'salt', 'ss01'...)
36809 * @return {Array} substitutions - The list of substitutions.
36810 */
36811Substitution.prototype.getSingle = function(feature, script, language) {
36812    var this$1 = this;
36813
36814    var substitutions = [];
36815    var lookupTables = this.getLookupTables(script, language, feature, 1);
36816    for (var idx = 0; idx < lookupTables.length; idx++) {
36817        var subtables = lookupTables[idx].subtables;
36818        for (var i = 0; i < subtables.length; i++) {
36819            var subtable = subtables[i];
36820            var glyphs = this$1.expandCoverage(subtable.coverage);
36821            var j = (void 0);
36822            if (subtable.substFormat === 1) {
36823                var delta = subtable.deltaGlyphId;
36824                for (j = 0; j < glyphs.length; j++) {
36825                    var glyph = glyphs[j];
36826                    substitutions.push({ sub: glyph, by: glyph + delta });
36827                }
36828            } else {
36829                var substitute = subtable.substitute;
36830                for (j = 0; j < glyphs.length; j++) {
36831                    substitutions.push({ sub: glyphs[j], by: substitute[j] });
36832                }
36833            }
36834        }
36835    }
36836    return substitutions;
36837};
36838
36839/**
36840 * List all alternates (lookup type 3) for a given script, language, and feature.
36841 * @param {string} [script='DFLT']
36842 * @param {string} [language='dflt']
36843 * @param {string} feature - 4-character feature name ('aalt', 'salt'...)
36844 * @return {Array} alternates - The list of alternates
36845 */
36846Substitution.prototype.getAlternates = function(feature, script, language) {
36847    var this$1 = this;
36848
36849    var alternates = [];
36850    var lookupTables = this.getLookupTables(script, language, feature, 3);
36851    for (var idx = 0; idx < lookupTables.length; idx++) {
36852        var subtables = lookupTables[idx].subtables;
36853        for (var i = 0; i < subtables.length; i++) {
36854            var subtable = subtables[i];
36855            var glyphs = this$1.expandCoverage(subtable.coverage);
36856            var alternateSets = subtable.alternateSets;
36857            for (var j = 0; j < glyphs.length; j++) {
36858                alternates.push({ sub: glyphs[j], by: alternateSets[j] });
36859            }
36860        }
36861    }
36862    return alternates;
36863};
36864
36865/**
36866 * List all ligatures (lookup type 4) for a given script, language, and feature.
36867 * The result is an array of ligature objects like { sub: [ids], by: id }
36868 * @param {string} feature - 4-letter feature name ('liga', 'rlig', 'dlig'...)
36869 * @param {string} [script='DFLT']
36870 * @param {string} [language='dflt']
36871 * @return {Array} ligatures - The list of ligatures.
36872 */
36873Substitution.prototype.getLigatures = function(feature, script, language) {
36874    var this$1 = this;
36875
36876    var ligatures = [];
36877    var lookupTables = this.getLookupTables(script, language, feature, 4);
36878    for (var idx = 0; idx < lookupTables.length; idx++) {
36879        var subtables = lookupTables[idx].subtables;
36880        for (var i = 0; i < subtables.length; i++) {
36881            var subtable = subtables[i];
36882            var glyphs = this$1.expandCoverage(subtable.coverage);
36883            var ligatureSets = subtable.ligatureSets;
36884            for (var j = 0; j < glyphs.length; j++) {
36885                var startGlyph = glyphs[j];
36886                var ligSet = ligatureSets[j];
36887                for (var k = 0; k < ligSet.length; k++) {
36888                    var lig = ligSet[k];
36889                    ligatures.push({
36890                        sub: [startGlyph].concat(lig.components),
36891                        by: lig.ligGlyph
36892                    });
36893                }
36894            }
36895        }
36896    }
36897    return ligatures;
36898};
36899
36900/**
36901 * Add or modify a single substitution (lookup type 1)
36902 * Format 2, more flexible, is always used.
36903 * @param {string} feature - 4-letter feature name ('liga', 'rlig', 'dlig'...)
36904 * @param {Object} substitution - { sub: id, delta: number } for format 1 or { sub: id, by: id } for format 2.
36905 * @param {string} [script='DFLT']
36906 * @param {string} [language='dflt']
36907 */
36908Substitution.prototype.addSingle = function(feature, substitution, script, language) {
36909    var lookupTable = this.getLookupTables(script, language, feature, 1, true)[0];
36910    var subtable = getSubstFormat(lookupTable, 2, {                // lookup type 1 subtable, format 2, coverage format 1
36911        substFormat: 2,
36912        coverage: {format: 1, glyphs: []},
36913        substitute: []
36914    });
36915    check.assert(subtable.coverage.format === 1, 'Ligature: unable to modify coverage table format ' + subtable.coverage.format);
36916    var coverageGlyph = substitution.sub;
36917    var pos = this.binSearch(subtable.coverage.glyphs, coverageGlyph);
36918    if (pos < 0) {
36919        pos = -1 - pos;
36920        subtable.coverage.glyphs.splice(pos, 0, coverageGlyph);
36921        subtable.substitute.splice(pos, 0, 0);
36922    }
36923    subtable.substitute[pos] = substitution.by;
36924};
36925
36926/**
36927 * Add or modify an alternate substitution (lookup type 1)
36928 * @param {string} feature - 4-letter feature name ('liga', 'rlig', 'dlig'...)
36929 * @param {Object} substitution - { sub: id, by: [ids] }
36930 * @param {string} [script='DFLT']
36931 * @param {string} [language='dflt']
36932 */
36933Substitution.prototype.addAlternate = function(feature, substitution, script, language) {
36934    var lookupTable = this.getLookupTables(script, language, feature, 3, true)[0];
36935    var subtable = getSubstFormat(lookupTable, 1, {                // lookup type 3 subtable, format 1, coverage format 1
36936        substFormat: 1,
36937        coverage: {format: 1, glyphs: []},
36938        alternateSets: []
36939    });
36940    check.assert(subtable.coverage.format === 1, 'Ligature: unable to modify coverage table format ' + subtable.coverage.format);
36941    var coverageGlyph = substitution.sub;
36942    var pos = this.binSearch(subtable.coverage.glyphs, coverageGlyph);
36943    if (pos < 0) {
36944        pos = -1 - pos;
36945        subtable.coverage.glyphs.splice(pos, 0, coverageGlyph);
36946        subtable.alternateSets.splice(pos, 0, 0);
36947    }
36948    subtable.alternateSets[pos] = substitution.by;
36949};
36950
36951/**
36952 * Add a ligature (lookup type 4)
36953 * Ligatures with more components must be stored ahead of those with fewer components in order to be found
36954 * @param {string} feature - 4-letter feature name ('liga', 'rlig', 'dlig'...)
36955 * @param {Object} ligature - { sub: [ids], by: id }
36956 * @param {string} [script='DFLT']
36957 * @param {string} [language='dflt']
36958 */
36959Substitution.prototype.addLigature = function(feature, ligature, script, language) {
36960    var lookupTable = this.getLookupTables(script, language, feature, 4, true)[0];
36961    var subtable = lookupTable.subtables[0];
36962    if (!subtable) {
36963        subtable = {                // lookup type 4 subtable, format 1, coverage format 1
36964            substFormat: 1,
36965            coverage: { format: 1, glyphs: [] },
36966            ligatureSets: []
36967        };
36968        lookupTable.subtables[0] = subtable;
36969    }
36970    check.assert(subtable.coverage.format === 1, 'Ligature: unable to modify coverage table format ' + subtable.coverage.format);
36971    var coverageGlyph = ligature.sub[0];
36972    var ligComponents = ligature.sub.slice(1);
36973    var ligatureTable = {
36974        ligGlyph: ligature.by,
36975        components: ligComponents
36976    };
36977    var pos = this.binSearch(subtable.coverage.glyphs, coverageGlyph);
36978    if (pos >= 0) {
36979        // ligatureSet already exists
36980        var ligatureSet = subtable.ligatureSets[pos];
36981        for (var i = 0; i < ligatureSet.length; i++) {
36982            // If ligature already exists, return.
36983            if (arraysEqual(ligatureSet[i].components, ligComponents)) {
36984                return;
36985            }
36986        }
36987        // ligature does not exist: add it.
36988        ligatureSet.push(ligatureTable);
36989    } else {
36990        // Create a new ligatureSet and add coverage for the first glyph.
36991        pos = -1 - pos;
36992        subtable.coverage.glyphs.splice(pos, 0, coverageGlyph);
36993        subtable.ligatureSets.splice(pos, 0, [ligatureTable]);
36994    }
36995};
36996
36997/**
36998 * List all feature data for a given script and language.
36999 * @param {string} feature - 4-letter feature name
37000 * @param {string} [script='DFLT']
37001 * @param {string} [language='dflt']
37002 * @return {Array} substitutions - The list of substitutions.
37003 */
37004Substitution.prototype.getFeature = function(feature, script, language) {
37005    if (/ss\d\d/.test(feature)) {               // ss01 - ss20
37006        return this.getSingle(feature, script, language);
37007    }
37008    switch (feature) {
37009        case 'aalt':
37010        case 'salt':
37011            return this.getSingle(feature, script, language)
37012                    .concat(this.getAlternates(feature, script, language));
37013        case 'dlig':
37014        case 'liga':
37015        case 'rlig': return this.getLigatures(feature, script, language);
37016    }
37017    return undefined;
37018};
37019
37020/**
37021 * Add a substitution to a feature for a given script and language.
37022 * @param {string} feature - 4-letter feature name
37023 * @param {Object} sub - the substitution to add (an object like { sub: id or [ids], by: id or [ids] })
37024 * @param {string} [script='DFLT']
37025 * @param {string} [language='dflt']
37026 */
37027Substitution.prototype.add = function(feature, sub, script, language) {
37028    if (/ss\d\d/.test(feature)) {               // ss01 - ss20
37029        return this.addSingle(feature, sub, script, language);
37030    }
37031    switch (feature) {
37032        case 'aalt':
37033        case 'salt':
37034            if (typeof sub.by === 'number') {
37035                return this.addSingle(feature, sub, script, language);
37036            }
37037            return this.addAlternate(feature, sub, script, language);
37038        case 'dlig':
37039        case 'liga':
37040        case 'rlig':
37041            return this.addLigature(feature, sub, script, language);
37042    }
37043    return undefined;
37044};
37045
37046function isBrowser() {
37047    return typeof window !== 'undefined';
37048}
37049
37050function nodeBufferToArrayBuffer(buffer) {
37051    var ab = new ArrayBuffer(buffer.length);
37052    var view = new Uint8Array(ab);
37053    for (var i = 0; i < buffer.length; ++i) {
37054        view[i] = buffer[i];
37055    }
37056
37057    return ab;
37058}
37059
37060function arrayBufferToNodeBuffer(ab) {
37061    var buffer = new Buffer(ab.byteLength);
37062    var view = new Uint8Array(ab);
37063    for (var i = 0; i < buffer.length; ++i) {
37064        buffer[i] = view[i];
37065    }
37066
37067    return buffer;
37068}
37069
37070function checkArgument(expression, message) {
37071    if (!expression) {
37072        throw message;
37073    }
37074}
37075
37076/* A TrueType font hinting interpreter.
37077*
37078* (c) 2017 Axel Kittenberger
37079*
37080* This interpreter has been implemented according to this documentation:
37081* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM05/Chap5.html
37082*
37083* According to the documentation F24DOT6 values are used for pixels.
37084* That means calculation is 1/64 pixel accurate and uses integer operations.
37085* However, Javascript has floating point operations by default and only
37086* those are available. One could make a case to simulate the 1/64 accuracy
37087* exactly by truncating after every division operation
37088* (for example with << 0) to get pixel exactly results as other TrueType
37089* implementations. It may make sense since some fonts are pixel optimized
37090* by hand using DELTAP instructions. The current implementation doesn't
37091* and rather uses full floating point precision.
37092*
37093* xScale, yScale and rotation is currently ignored.
37094*
37095* A few non-trivial instructions are missing as I didn't encounter yet
37096* a font that used them to test a possible implementation.
37097*
37098* Some fonts seem to use undocumented features regarding the twilight zone.
37099* Only some of them are implemented as they were encountered.
37100*
37101* The exports.DEBUG statements are removed on the minified distribution file.
37102*/
37103var instructionTable;
37104var exec;
37105var execGlyph;
37106var execComponent;
37107
37108/*
37109* Creates a hinting object.
37110*
37111* There ought to be exactly one
37112* for each truetype font that is used for hinting.
37113*/
37114function Hinting(font) {
37115    // the font this hinting object is for
37116    this.font = font;
37117
37118    // cached states
37119    this._fpgmState  =
37120    this._prepState  =
37121        undefined;
37122
37123    // errorState
37124    // 0 ... all okay
37125    // 1 ... had an error in a glyf,
37126    //       continue working but stop spamming
37127    //       the console
37128    // 2 ... error at prep, stop hinting at this ppem
37129    // 3 ... error at fpeg, stop hinting for this font at all
37130    this._errorState = 0;
37131}
37132
37133/*
37134* Not rounding.
37135*/
37136function roundOff(v) {
37137    return v;
37138}
37139
37140/*
37141* Rounding to grid.
37142*/
37143function roundToGrid(v) {
37144    //Rounding in TT is supposed to "symmetrical around zero"
37145    return Math.sign(v) * Math.round(Math.abs(v));
37146}
37147
37148/*
37149* Rounding to double grid.
37150*/
37151function roundToDoubleGrid(v) {
37152    return Math.sign(v) * Math.round(Math.abs(v * 2)) / 2;
37153}
37154
37155/*
37156* Rounding to half grid.
37157*/
37158function roundToHalfGrid(v) {
37159    return Math.sign(v) * (Math.round(Math.abs(v) + 0.5) - 0.5);
37160}
37161
37162/*
37163* Rounding to up to grid.
37164*/
37165function roundUpToGrid(v) {
37166    return Math.sign(v) * Math.ceil(Math.abs(v));
37167}
37168
37169/*
37170* Rounding to down to grid.
37171*/
37172function roundDownToGrid(v) {
37173    return Math.sign(v) * Math.floor(Math.abs(v));
37174}
37175
37176/*
37177* Super rounding.
37178*/
vendor: 56,961 bytes, lines 37179-39631
37179var roundSuper = function (v) {
37180    var period = this.srPeriod;
37181    var phase = this.srPhase;
37182    var threshold = this.srThreshold;
37183    var sign = 1;
37184
37185    if (v < 0) {
37186        v = -v;
37187        sign = -1;
37188    }
37189
37190    v += threshold - phase;
37191
37192    v = Math.trunc(v / period) * period;
37193
37194    v += phase;
37195
37196    // according to http://xgridfit.sourceforge.net/round.html
37197    if (sign > 0 && v < 0) { return phase; }
37198    if (sign < 0 && v > 0) { return -phase; }
37199
37200    return v * sign;
37201};
37202
37203/*
37204* Unit vector of x-axis.
37205*/
37206var xUnitVector = {
37207    x: 1,
37208
37209    y: 0,
37210
37211    axis: 'x',
37212
37213    // Gets the projected distance between two points.
37214    // o1/o2 ... if true, respective original position is used.
37215    distance: function (p1, p2, o1, o2) {
37216        return (o1 ? p1.xo : p1.x) - (o2 ? p2.xo : p2.x);
37217    },
37218
37219    // Moves point p so the moved position has the same relative
37220    // position to the moved positions of rp1 and rp2 than the
37221    // original positions had.
37222    //
37223    // See APPENDIX on INTERPOLATE at the bottom of this file.
37224    interpolate: function (p, rp1, rp2, pv) {
37225        var do1;
37226        var do2;
37227        var doa1;
37228        var doa2;
37229        var dm1;
37230        var dm2;
37231        var dt;
37232
37233        if (!pv || pv === this) {
37234            do1 = p.xo - rp1.xo;
37235            do2 = p.xo - rp2.xo;
37236            dm1 = rp1.x - rp1.xo;
37237            dm2 = rp2.x - rp2.xo;
37238            doa1 = Math.abs(do1);
37239            doa2 = Math.abs(do2);
37240            dt = doa1 + doa2;
37241
37242            if (dt === 0) {
37243                p.x = p.xo + (dm1 + dm2) / 2;
37244                return;
37245            }
37246
37247            p.x = p.xo + (dm1 * doa2 + dm2 * doa1) / dt;
37248            return;
37249        }
37250
37251        do1 = pv.distance(p, rp1, true, true);
37252        do2 = pv.distance(p, rp2, true, true);
37253        dm1 = pv.distance(rp1, rp1, false, true);
37254        dm2 = pv.distance(rp2, rp2, false, true);
37255        doa1 = Math.abs(do1);
37256        doa2 = Math.abs(do2);
37257        dt = doa1 + doa2;
37258
37259        if (dt === 0) {
37260            xUnitVector.setRelative(p, p, (dm1 + dm2) / 2, pv, true);
37261            return;
37262        }
37263
37264        xUnitVector.setRelative(p, p, (dm1 * doa2 + dm2 * doa1) / dt, pv, true);
37265    },
37266
37267    // Slope of line normal to this
37268    normalSlope: Number.NEGATIVE_INFINITY,
37269
37270    // Sets the point 'p' relative to point 'rp'
37271    // by the distance 'd'.
37272    //
37273    // See APPENDIX on SETRELATIVE at the bottom of this file.
37274    //
37275    // p   ... point to set
37276    // rp  ... reference point
37277    // d   ... distance on projection vector
37278    // pv  ... projection vector (undefined = this)
37279    // org ... if true, uses the original position of rp as reference.
37280    setRelative: function (p, rp, d, pv, org) {
37281        if (!pv || pv === this) {
37282            p.x = (org ? rp.xo : rp.x) + d;
37283            return;
37284        }
37285
37286        var rpx = org ? rp.xo : rp.x;
37287        var rpy = org ? rp.yo : rp.y;
37288        var rpdx = rpx + d * pv.x;
37289        var rpdy = rpy + d * pv.y;
37290
37291        p.x = rpdx + (p.y - rpdy) / pv.normalSlope;
37292    },
37293
37294    // Slope of vector line.
37295    slope: 0,
37296
37297    // Touches the point p.
37298    touch: function (p) {
37299        p.xTouched = true;
37300    },
37301
37302    // Tests if a point p is touched.
37303    touched: function (p) {
37304        return p.xTouched;
37305    },
37306
37307    // Untouches the point p.
37308    untouch: function (p) {
37309        p.xTouched = false;
37310    }
37311};
37312
37313/*
37314* Unit vector of y-axis.
37315*/
37316var yUnitVector = {
37317    x: 0,
37318
37319    y: 1,
37320
37321    axis: 'y',
37322
37323    // Gets the projected distance between two points.
37324    // o1/o2 ... if true, respective original position is used.
37325    distance: function (p1, p2, o1, o2) {
37326        return (o1 ? p1.yo : p1.y) - (o2 ? p2.yo : p2.y);
37327    },
37328
37329    // Moves point p so the moved position has the same relative
37330    // position to the moved positions of rp1 and rp2 than the
37331    // original positions had.
37332    //
37333    // See APPENDIX on INTERPOLATE at the bottom of this file.
37334    interpolate: function (p, rp1, rp2, pv) {
37335        var do1;
37336        var do2;
37337        var doa1;
37338        var doa2;
37339        var dm1;
37340        var dm2;
37341        var dt;
37342
37343        if (!pv || pv === this) {
37344            do1 = p.yo - rp1.yo;
37345            do2 = p.yo - rp2.yo;
37346            dm1 = rp1.y - rp1.yo;
37347            dm2 = rp2.y - rp2.yo;
37348            doa1 = Math.abs(do1);
37349            doa2 = Math.abs(do2);
37350            dt = doa1 + doa2;
37351
37352            if (dt === 0) {
37353                p.y = p.yo + (dm1 + dm2) / 2;
37354                return;
37355            }
37356
37357            p.y = p.yo + (dm1 * doa2 + dm2 * doa1) / dt;
37358            return;
37359        }
37360
37361        do1 = pv.distance(p, rp1, true, true);
37362        do2 = pv.distance(p, rp2, true, true);
37363        dm1 = pv.distance(rp1, rp1, false, true);
37364        dm2 = pv.distance(rp2, rp2, false, true);
37365        doa1 = Math.abs(do1);
37366        doa2 = Math.abs(do2);
37367        dt = doa1 + doa2;
37368
37369        if (dt === 0) {
37370            yUnitVector.setRelative(p, p, (dm1 + dm2) / 2, pv, true);
37371            return;
37372        }
37373
37374        yUnitVector.setRelative(p, p, (dm1 * doa2 + dm2 * doa1) / dt, pv, true);
37375    },
37376
37377    // Slope of line normal to this.
37378    normalSlope: 0,
37379
37380    // Sets the point 'p' relative to point 'rp'
37381    // by the distance 'd'
37382    //
37383    // See APPENDIX on SETRELATIVE at the bottom of this file.
37384    //
37385    // p   ... point to set
37386    // rp  ... reference point
37387    // d   ... distance on projection vector
37388    // pv  ... projection vector (undefined = this)
37389    // org ... if true, uses the original position of rp as reference.
37390    setRelative: function (p, rp, d, pv, org) {
37391        if (!pv || pv === this) {
37392            p.y = (org ? rp.yo : rp.y) + d;
37393            return;
37394        }
37395
37396        var rpx = org ? rp.xo : rp.x;
37397        var rpy = org ? rp.yo : rp.y;
37398        var rpdx = rpx + d * pv.x;
37399        var rpdy = rpy + d * pv.y;
37400
37401        p.y = rpdy + pv.normalSlope * (p.x - rpdx);
37402    },
37403
37404    // Slope of vector line.
37405    slope: Number.POSITIVE_INFINITY,
37406
37407    // Touches the point p.
37408    touch: function (p) {
37409        p.yTouched = true;
37410    },
37411
37412    // Tests if a point p is touched.
37413    touched: function (p) {
37414        return p.yTouched;
37415    },
37416
37417    // Untouches the point p.
37418    untouch: function (p) {
37419        p.yTouched = false;
37420    }
37421};
37422
37423Object.freeze(xUnitVector);
37424Object.freeze(yUnitVector);
37425
37426/*
37427* Creates a unit vector that is not x- or y-axis.
37428*/
37429function UnitVector(x, y) {
37430    this.x = x;
37431    this.y = y;
37432    this.axis = undefined;
37433    this.slope = y / x;
37434    this.normalSlope = -x / y;
37435    Object.freeze(this);
37436}
37437
37438/*
37439* Gets the projected distance between two points.
37440* o1/o2 ... if true, respective original position is used.
37441*/
37442UnitVector.prototype.distance = function(p1, p2, o1, o2) {
37443    return (
37444        this.x * xUnitVector.distance(p1, p2, o1, o2) +
37445        this.y * yUnitVector.distance(p1, p2, o1, o2)
37446    );
37447};
37448
37449/*
37450* Moves point p so the moved position has the same relative
37451* position to the moved positions of rp1 and rp2 than the
37452* original positions had.
37453*
37454* See APPENDIX on INTERPOLATE at the bottom of this file.
37455*/
37456UnitVector.prototype.interpolate = function(p, rp1, rp2, pv) {
37457    var dm1;
37458    var dm2;
37459    var do1;
37460    var do2;
37461    var doa1;
37462    var doa2;
37463    var dt;
37464
37465    do1 = pv.distance(p, rp1, true, true);
37466    do2 = pv.distance(p, rp2, true, true);
37467    dm1 = pv.distance(rp1, rp1, false, true);
37468    dm2 = pv.distance(rp2, rp2, false, true);
37469    doa1 = Math.abs(do1);
37470    doa2 = Math.abs(do2);
37471    dt = doa1 + doa2;
37472
37473    if (dt === 0) {
37474        this.setRelative(p, p, (dm1 + dm2) / 2, pv, true);
37475        return;
37476    }
37477
37478    this.setRelative(p, p, (dm1 * doa2 + dm2 * doa1) / dt, pv, true);
37479};
37480
37481/*
37482* Sets the point 'p' relative to point 'rp'
37483* by the distance 'd'
37484*
37485* See APPENDIX on SETRELATIVE at the bottom of this file.
37486*
37487* p   ...  point to set
37488* rp  ... reference point
37489* d   ... distance on projection vector
37490* pv  ... projection vector (undefined = this)
37491* org ... if true, uses the original position of rp as reference.
37492*/
37493UnitVector.prototype.setRelative = function(p, rp, d, pv, org) {
37494    pv = pv || this;
37495
37496    var rpx = org ? rp.xo : rp.x;
37497    var rpy = org ? rp.yo : rp.y;
37498    var rpdx = rpx + d * pv.x;
37499    var rpdy = rpy + d * pv.y;
37500
37501    var pvns = pv.normalSlope;
37502    var fvs = this.slope;
37503
37504    var px = p.x;
37505    var py = p.y;
37506
37507    p.x = (fvs * px - pvns * rpdx + rpdy - py) / (fvs - pvns);
37508    p.y = fvs * (p.x - px) + py;
37509};
37510
37511/*
37512* Touches the point p.
37513*/
37514UnitVector.prototype.touch = function(p) {
37515    p.xTouched = true;
37516    p.yTouched = true;
37517};
37518
37519/*
37520* Returns a unit vector with x/y coordinates.
37521*/
37522function getUnitVector(x, y) {
37523    var d = Math.sqrt(x * x + y * y);
37524
37525    x /= d;
37526    y /= d;
37527
37528    if (x === 1 && y === 0) { return xUnitVector; }
37529    else if (x === 0 && y === 1) { return yUnitVector; }
37530    else { return new UnitVector(x, y); }
37531}
37532
37533/*
37534* Creates a point in the hinting engine.
37535*/
37536function HPoint(
37537    x,
37538    y,
37539    lastPointOfContour,
37540    onCurve
37541) {
37542    this.x = this.xo = Math.round(x * 64) / 64; // hinted x value and original x-value
37543    this.y = this.yo = Math.round(y * 64) / 64; // hinted y value and original y-value
37544
37545    this.lastPointOfContour = lastPointOfContour;
37546    this.onCurve = onCurve;
37547    this.prevPointOnContour = undefined;
37548    this.nextPointOnContour = undefined;
37549    this.xTouched = false;
37550    this.yTouched = false;
37551
37552    Object.preventExtensions(this);
37553}
37554
37555/*
37556* Returns the next touched point on the contour.
37557*
37558* v  ... unit vector to test touch axis.
37559*/
37560HPoint.prototype.nextTouched = function(v) {
37561    var p = this.nextPointOnContour;
37562
37563    while (!v.touched(p) && p !== this) { p = p.nextPointOnContour; }
37564
37565    return p;
37566};
37567
37568/*
37569* Returns the previous touched point on the contour
37570*
37571* v  ... unit vector to test touch axis.
37572*/
37573HPoint.prototype.prevTouched = function(v) {
37574    var p = this.prevPointOnContour;
37575
37576    while (!v.touched(p) && p !== this) { p = p.prevPointOnContour; }
37577
37578    return p;
37579};
37580
37581/*
37582* The zero point.
37583*/
37584var HPZero = Object.freeze(new HPoint(0, 0));
37585
37586/*
37587* The default state of the interpreter.
37588*
37589* Note: Freezing the defaultState and then deriving from it
37590* makes the V8 Javascript engine going awkward,
37591* so this is avoided, albeit the defaultState shouldn't
37592* ever change.
37593*/
37594var defaultState = {
37595    cvCutIn: 17 / 16,    // control value cut in
37596    deltaBase: 9,
37597    deltaShift: 0.125,
37598    loop: 1,             // loops some instructions
37599    minDis: 1,           // minimum distance
37600    autoFlip: true
37601};
37602
37603/*
37604* The current state of the interpreter.
37605*
37606* env  ... 'fpgm' or 'prep' or 'glyf'
37607* prog ... the program
37608*/
37609function State(env, prog) {
37610    this.env = env;
37611    this.stack = [];
37612    this.prog = prog;
37613
37614    switch (env) {
37615        case 'glyf' :
37616            this.zp0 = this.zp1 = this.zp2 = 1;
37617            this.rp0 = this.rp1 = this.rp2 = 0;
37618            /* fall through */
37619        case 'prep' :
37620            this.fv = this.pv = this.dpv = xUnitVector;
37621            this.round = roundToGrid;
37622    }
37623}
37624
37625/*
37626* Executes a glyph program.
37627*
37628* This does the hinting for each glyph.
37629*
37630* Returns an array of moved points.
37631*
37632* glyph: the glyph to hint
37633* ppem: the size the glyph is rendered for
37634*/
37635Hinting.prototype.exec = function(glyph, ppem) {
37636    if (typeof ppem !== 'number') {
37637        throw new Error('Point size is not a number!');
37638    }
37639
37640    // Received a fatal error, don't do any hinting anymore.
37641    if (this._errorState > 2) { return; }
37642
37643    var font = this.font;
37644    var prepState = this._prepState;
37645
37646    if (!prepState || prepState.ppem !== ppem) {
37647        var fpgmState = this._fpgmState;
37648
37649        if (!fpgmState) {
37650            // Executes the fpgm state.
37651            // This is used by fonts to define functions.
37652            State.prototype = defaultState;
37653
37654            fpgmState =
37655            this._fpgmState =
37656                new State('fpgm', font.tables.fpgm);
37657
37658            fpgmState.funcs = [ ];
37659            fpgmState.font = font;
37660
37661            if (exports.DEBUG) {
37662                console.log('---EXEC FPGM---');
37663                fpgmState.step = -1;
37664            }
37665
37666            try {
37667                exec(fpgmState);
37668            } catch (e) {
37669                console.log('Hinting error in FPGM:' + e);
37670                this._errorState = 3;
37671                return;
37672            }
37673        }
37674
37675        // Executes the prep program for this ppem setting.
37676        // This is used by fonts to set cvt values
37677        // depending on to be rendered font size.
37678
37679        State.prototype = fpgmState;
37680        prepState =
37681        this._prepState =
37682            new State('prep', font.tables.prep);
37683
37684        prepState.ppem = ppem;
37685
37686        // Creates a copy of the cvt table
37687        // and scales it to the current ppem setting.
37688        var oCvt = font.tables.cvt;
37689        if (oCvt) {
37690            var cvt = prepState.cvt = new Array(oCvt.length);
37691            var scale = ppem / font.unitsPerEm;
37692            for (var c = 0; c < oCvt.length; c++) {
37693                cvt[c] = oCvt[c] * scale;
37694            }
37695        } else {
37696            prepState.cvt = [];
37697        }
37698
37699        if (exports.DEBUG) {
37700            console.log('---EXEC PREP---');
37701            prepState.step = -1;
37702        }
37703
37704        try {
37705            exec(prepState);
37706        } catch (e) {
37707            if (this._errorState < 2) {
37708                console.log('Hinting error in PREP:' + e);
37709            }
37710            this._errorState = 2;
37711        }
37712    }
37713
37714    if (this._errorState > 1) { return; }
37715
37716    try {
37717        return execGlyph(glyph, prepState);
37718    } catch (e) {
37719        if (this._errorState < 1) {
37720            console.log('Hinting error:' + e);
37721            console.log('Note: further hinting errors are silenced');
37722        }
37723        this._errorState = 1;
37724        return undefined;
37725    }
37726};
37727
37728/*
37729* Executes the hinting program for a glyph.
37730*/
37731execGlyph = function(glyph, prepState) {
37732    // original point positions
37733    var xScale = prepState.ppem / prepState.font.unitsPerEm;
37734    var yScale = xScale;
37735    var components = glyph.components;
37736    var contours;
37737    var gZone;
37738    var state;
37739
37740    State.prototype = prepState;
37741    if (!components) {
37742        state = new State('glyf', glyph.instructions);
37743        if (exports.DEBUG) {
37744            console.log('---EXEC GLYPH---');
37745            state.step = -1;
37746        }
37747        execComponent(glyph, state, xScale, yScale);
37748        gZone = state.gZone;
37749    } else {
37750        var font = prepState.font;
37751        gZone = [];
37752        contours = [];
37753        for (var i = 0; i < components.length; i++) {
37754            var c = components[i];
37755            var cg = font.glyphs.get(c.glyphIndex);
37756
37757            state = new State('glyf', cg.instructions);
37758
37759            if (exports.DEBUG) {
37760                console.log('---EXEC COMP ' + i + '---');
37761                state.step = -1;
37762            }
37763
37764            execComponent(cg, state, xScale, yScale);
37765            // appends the computed points to the result array
37766            // post processes the component points
37767            var dx = Math.round(c.dx * xScale);
37768            var dy = Math.round(c.dy * yScale);
37769            var gz = state.gZone;
37770            var cc = state.contours;
37771            for (var pi = 0; pi < gz.length; pi++) {
37772                var p = gz[pi];
37773                p.xTouched = p.yTouched = false;
37774                p.xo = p.x = p.x + dx;
37775                p.yo = p.y = p.y + dy;
37776            }
37777
37778            var gLen = gZone.length;
37779            gZone.push.apply(gZone, gz);
37780            for (var j = 0; j < cc.length; j++) {
37781                contours.push(cc[j] + gLen);
37782            }
37783        }
37784
37785        if (glyph.instructions && !state.inhibitGridFit) {
37786            // the composite has instructions on its own
37787            state = new State('glyf', glyph.instructions);
37788
37789            state.gZone = state.z0 = state.z1 = state.z2 = gZone;
37790
37791            state.contours = contours;
37792
37793            // note: HPZero cannot be used here, since
37794            //       the point might be modified
37795            gZone.push(
37796                new HPoint(0, 0),
37797                new HPoint(Math.round(glyph.advanceWidth * xScale), 0)
37798            );
37799
37800            if (exports.DEBUG) {
37801                console.log('---EXEC COMPOSITE---');
37802                state.step = -1;
37803            }
37804
37805            exec(state);
37806
37807            gZone.length -= 2;
37808        }
37809    }
37810
37811    return gZone;
37812};
37813
37814/*
37815* Executes the hinting program for a component of a multi-component glyph
37816* or of the glyph itself by a non-component glyph.
37817*/
37818execComponent = function(glyph, state, xScale, yScale)
37819{
37820    var points = glyph.points || [];
37821    var pLen = points.length;
37822    var gZone = state.gZone = state.z0 = state.z1 = state.z2 = [];
37823    var contours = state.contours = [];
37824
37825    // Scales the original points and
37826    // makes copies for the hinted points.
37827    var cp; // current point
37828    for (var i = 0; i < pLen; i++) {
37829        cp = points[i];
37830
37831        gZone[i] = new HPoint(
37832            cp.x * xScale,
37833            cp.y * yScale,
37834            cp.lastPointOfContour,
37835            cp.onCurve
37836        );
37837    }
37838
37839    // Chain links the contours.
37840    var sp; // start point
37841    var np; // next point
37842
37843    for (var i$1 = 0; i$1 < pLen; i$1++) {
37844        cp = gZone[i$1];
37845
37846        if (!sp) {
37847            sp = cp;
37848            contours.push(i$1);
37849        }
37850
37851        if (cp.lastPointOfContour) {
37852            cp.nextPointOnContour = sp;
37853            sp.prevPointOnContour = cp;
37854            sp = undefined;
37855        } else {
37856            np = gZone[i$1 + 1];
37857            cp.nextPointOnContour = np;
37858            np.prevPointOnContour = cp;
37859        }
37860    }
37861
37862    if (state.inhibitGridFit) { return; }
37863
37864    gZone.push(
37865        new HPoint(0, 0),
37866        new HPoint(Math.round(glyph.advanceWidth * xScale), 0)
37867    );
37868
37869    exec(state);
37870
37871    // Removes the extra points.
37872    gZone.length -= 2;
37873
37874    if (exports.DEBUG) {
37875        console.log('FINISHED GLYPH', state.stack);
37876        for (var i$2 = 0; i$2 < pLen; i$2++) {
37877            console.log(i$2, gZone[i$2].x, gZone[i$2].y);
37878        }
37879    }
37880};
37881
37882/*
37883* Executes the program loaded in state.
37884*/
37885exec = function(state) {
37886    var prog = state.prog;
37887
37888    if (!prog) { return; }
37889
37890    var pLen = prog.length;
37891    var ins;
37892
37893    for (state.ip = 0; state.ip < pLen; state.ip++) {
37894        if (exports.DEBUG) { state.step++; }
37895        ins = instructionTable[prog[state.ip]];
37896
37897        if (!ins) {
37898            throw new Error(
37899                'unknown instruction: 0x' +
37900                Number(prog[state.ip]).toString(16)
37901            );
37902        }
37903
37904        ins(state);
37905
37906        // very extensive debugging for each step
37907        /*
37908        if (exports.DEBUG) {
37909            var da;
37910            if (state.gZone) {
37911                da = [];
37912                for (let i = 0; i < state.gZone.length; i++)
37913                {
37914                    da.push(i + ' ' +
37915                        state.gZone[i].x * 64 + ' ' +
37916                        state.gZone[i].y * 64 + ' ' +
37917                        (state.gZone[i].xTouched ? 'x' : '') +
37918                        (state.gZone[i].yTouched ? 'y' : '')
37919                    );
37920                }
37921                console.log('GZ', da);
37922            }
37923
37924            if (state.tZone) {
37925                da = [];
37926                for (let i = 0; i < state.tZone.length; i++) {
37927                    da.push(i + ' ' +
37928                        state.tZone[i].x * 64 + ' ' +
37929                        state.tZone[i].y * 64 + ' ' +
37930                        (state.tZone[i].xTouched ? 'x' : '') +
37931                        (state.tZone[i].yTouched ? 'y' : '')
37932                    );
37933                }
37934                console.log('TZ', da);
37935            }
37936
37937            if (state.stack.length > 10) {
37938                console.log(
37939                    state.stack.length,
37940                    '...', state.stack.slice(state.stack.length - 10)
37941                );
37942            } else {
37943                console.log(state.stack.length, state.stack);
37944            }
37945        }
37946        */
37947    }
37948};
37949
37950/*
37951* Initializes the twilight zone.
37952*
37953* This is only done if a SZPx instruction
37954* refers to the twilight zone.
37955*/
37956function initTZone(state)
37957{
37958    var tZone = state.tZone = new Array(state.gZone.length);
37959
37960    // no idea if this is actually correct...
37961    for (var i = 0; i < tZone.length; i++)
37962    {
37963        tZone[i] = new HPoint(0, 0);
37964    }
37965}
37966
37967/*
37968* Skips the instruction pointer ahead over an IF/ELSE block.
37969* handleElse .. if true breaks on matching ELSE
37970*/
37971function skip(state, handleElse)
37972{
37973    var prog = state.prog;
37974    var ip = state.ip;
37975    var nesting = 1;
37976    var ins;
37977
37978    do {
37979        ins = prog[++ip];
37980        if (ins === 0x58) // IF
37981            { nesting++; }
37982        else if (ins === 0x59) // EIF
37983            { nesting--; }
37984        else if (ins === 0x40) // NPUSHB
37985            { ip += prog[ip + 1] + 1; }
37986        else if (ins === 0x41) // NPUSHW
37987            { ip += 2 * prog[ip + 1] + 1; }
37988        else if (ins >= 0xB0 && ins <= 0xB7) // PUSHB
37989            { ip += ins - 0xB0 + 1; }
37990        else if (ins >= 0xB8 && ins <= 0xBF) // PUSHW
37991            { ip += (ins - 0xB8 + 1) * 2; }
37992        else if (handleElse && nesting === 1 && ins === 0x1B) // ELSE
37993            { break; }
37994    } while (nesting > 0);
37995
37996    state.ip = ip;
37997}
37998
37999/*----------------------------------------------------------*
38000*          And then a lot of instructions...                *
38001*----------------------------------------------------------*/
38002
38003// SVTCA[a] Set freedom and projection Vectors To Coordinate Axis
38004// 0x00-0x01
38005function SVTCA(v, state) {
38006    if (exports.DEBUG) { console.log(state.step, 'SVTCA[' + v.axis + ']'); }
38007
38008    state.fv = state.pv = state.dpv = v;
38009}
38010
38011// SPVTCA[a] Set Projection Vector to Coordinate Axis
38012// 0x02-0x03
38013function SPVTCA(v, state) {
38014    if (exports.DEBUG) { console.log(state.step, 'SPVTCA[' + v.axis + ']'); }
38015
38016    state.pv = state.dpv = v;
38017}
38018
38019// SFVTCA[a] Set Freedom Vector to Coordinate Axis
38020// 0x04-0x05
38021function SFVTCA(v, state) {
38022    if (exports.DEBUG) { console.log(state.step, 'SFVTCA[' + v.axis + ']'); }
38023
38024    state.fv = v;
38025}
38026
38027// SPVTL[a] Set Projection Vector To Line
38028// 0x06-0x07
38029function SPVTL(a, state) {
38030    var stack = state.stack;
38031    var p2i = stack.pop();
38032    var p1i = stack.pop();
38033    var p2 = state.z2[p2i];
38034    var p1 = state.z1[p1i];
38035
38036    if (exports.DEBUG) { console.log('SPVTL[' + a + ']', p2i, p1i); }
38037
38038    var dx;
38039    var dy;
38040
38041    if (!a) {
38042        dx = p1.x - p2.x;
38043        dy = p1.y - p2.y;
38044    } else {
38045        dx = p2.y - p1.y;
38046        dy = p1.x - p2.x;
38047    }
38048
38049    state.pv = state.dpv = getUnitVector(dx, dy);
38050}
38051
38052// SFVTL[a] Set Freedom Vector To Line
38053// 0x08-0x09
38054function SFVTL(a, state) {
38055    var stack = state.stack;
38056    var p2i = stack.pop();
38057    var p1i = stack.pop();
38058    var p2 = state.z2[p2i];
38059    var p1 = state.z1[p1i];
38060
38061    if (exports.DEBUG) { console.log('SFVTL[' + a + ']', p2i, p1i); }
38062
38063    var dx;
38064    var dy;
38065
38066    if (!a) {
38067        dx = p1.x - p2.x;
38068        dy = p1.y - p2.y;
38069    } else {
38070        dx = p2.y - p1.y;
38071        dy = p1.x - p2.x;
38072    }
38073
38074    state.fv = getUnitVector(dx, dy);
38075}
38076
38077// SPVFS[] Set Projection Vector From Stack
38078// 0x0A
38079function SPVFS(state) {
38080    var stack = state.stack;
38081    var y = stack.pop();
38082    var x = stack.pop();
38083
38084    if (exports.DEBUG) { console.log(state.step, 'SPVFS[]', y, x); }
38085
38086    state.pv = state.dpv = getUnitVector(x, y);
38087}
38088
38089// SFVFS[] Set Freedom Vector From Stack
38090// 0x0B
38091function SFVFS(state) {
38092    var stack = state.stack;
38093    var y = stack.pop();
38094    var x = stack.pop();
38095
38096    if (exports.DEBUG) { console.log(state.step, 'SPVFS[]', y, x); }
38097
38098    state.fv = getUnitVector(x, y);
38099}
38100
38101// GPV[] Get Projection Vector
38102// 0x0C
38103function GPV(state) {
38104    var stack = state.stack;
38105    var pv = state.pv;
38106
38107    if (exports.DEBUG) { console.log(state.step, 'GPV[]'); }
38108
38109    stack.push(pv.x * 0x4000);
38110    stack.push(pv.y * 0x4000);
38111}
38112
38113// GFV[] Get Freedom Vector
38114// 0x0C
38115function GFV(state) {
38116    var stack = state.stack;
38117    var fv = state.fv;
38118
38119    if (exports.DEBUG) { console.log(state.step, 'GFV[]'); }
38120
38121    stack.push(fv.x * 0x4000);
38122    stack.push(fv.y * 0x4000);
38123}
38124
38125// SFVTPV[] Set Freedom Vector To Projection Vector
38126// 0x0E
38127function SFVTPV(state) {
38128    state.fv = state.pv;
38129
38130    if (exports.DEBUG) { console.log(state.step, 'SFVTPV[]'); }
38131}
38132
38133// ISECT[] moves point p to the InterSECTion of two lines
38134// 0x0F
38135function ISECT(state)
38136{
38137    var stack = state.stack;
38138    var pa0i = stack.pop();
38139    var pa1i = stack.pop();
38140    var pb0i = stack.pop();
38141    var pb1i = stack.pop();
38142    var pi = stack.pop();
38143    var z0 = state.z0;
38144    var z1 = state.z1;
38145    var pa0 = z0[pa0i];
38146    var pa1 = z0[pa1i];
38147    var pb0 = z1[pb0i];
38148    var pb1 = z1[pb1i];
38149    var p = state.z2[pi];
38150
38151    if (exports.DEBUG) { console.log('ISECT[], ', pa0i, pa1i, pb0i, pb1i, pi); }
38152
38153    // math from
38154    // en.wikipedia.org/wiki/Line%E2%80%93line_intersection#Given_two_points_on_each_line
38155
38156    var x1 = pa0.x;
38157    var y1 = pa0.y;
38158    var x2 = pa1.x;
38159    var y2 = pa1.y;
38160    var x3 = pb0.x;
38161    var y3 = pb0.y;
38162    var x4 = pb1.x;
38163    var y4 = pb1.y;
38164
38165    var div = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
38166    var f1 = x1 * y2 - y1 * x2;
38167    var f2 = x3 * y4 - y3 * x4;
38168
38169    p.x = (f1 * (x3 - x4) - f2 * (x1 - x2)) / div;
38170    p.y = (f1 * (y3 - y4) - f2 * (y1 - y2)) / div;
38171}
38172
38173// SRP0[] Set Reference Point 0
38174// 0x10
38175function SRP0(state) {
38176    state.rp0 = state.stack.pop();
38177
38178    if (exports.DEBUG) { console.log(state.step, 'SRP0[]', state.rp0); }
38179}
38180
38181// SRP1[] Set Reference Point 1
38182// 0x11
38183function SRP1(state) {
38184    state.rp1 = state.stack.pop();
38185
38186    if (exports.DEBUG) { console.log(state.step, 'SRP1[]', state.rp1); }
38187}
38188
38189// SRP1[] Set Reference Point 2
38190// 0x12
38191function SRP2(state) {
38192    state.rp2 = state.stack.pop();
38193
38194    if (exports.DEBUG) { console.log(state.step, 'SRP2[]', state.rp2); }
38195}
38196
38197// SZP0[] Set Zone Pointer 0
38198// 0x13
38199function SZP0(state) {
38200    var n = state.stack.pop();
38201
38202    if (exports.DEBUG) { console.log(state.step, 'SZP0[]', n); }
38203
38204    state.zp0 = n;
38205
38206    switch (n) {
38207        case 0:
38208            if (!state.tZone) { initTZone(state); }
38209            state.z0 = state.tZone;
38210            break;
38211        case 1 :
38212            state.z0 = state.gZone;
38213            break;
38214        default :
38215            throw new Error('Invalid zone pointer');
38216    }
38217}
38218
38219// SZP1[] Set Zone Pointer 1
38220// 0x14
38221function SZP1(state) {
38222    var n = state.stack.pop();
38223
38224    if (exports.DEBUG) { console.log(state.step, 'SZP1[]', n); }
38225
38226    state.zp1 = n;
38227
38228    switch (n) {
38229        case 0:
38230            if (!state.tZone) { initTZone(state); }
38231            state.z1 = state.tZone;
38232            break;
38233        case 1 :
38234            state.z1 = state.gZone;
38235            break;
38236        default :
38237            throw new Error('Invalid zone pointer');
38238    }
38239}
38240
38241// SZP2[] Set Zone Pointer 2
38242// 0x15
38243function SZP2(state) {
38244    var n = state.stack.pop();
38245
38246    if (exports.DEBUG) { console.log(state.step, 'SZP2[]', n); }
38247
38248    state.zp2 = n;
38249
38250    switch (n) {
38251        case 0:
38252            if (!state.tZone) { initTZone(state); }
38253            state.z2 = state.tZone;
38254            break;
38255        case 1 :
38256            state.z2 = state.gZone;
38257            break;
38258        default :
38259            throw new Error('Invalid zone pointer');
38260    }
38261}
38262
38263// SZPS[] Set Zone PointerS
38264// 0x16
38265function SZPS(state) {
38266    var n = state.stack.pop();
38267
38268    if (exports.DEBUG) { console.log(state.step, 'SZPS[]', n); }
38269
38270    state.zp0 = state.zp1 = state.zp2 = n;
38271
38272    switch (n) {
38273        case 0:
38274            if (!state.tZone) { initTZone(state); }
38275            state.z0 = state.z1 = state.z2 = state.tZone;
38276            break;
38277        case 1 :
38278            state.z0 = state.z1 = state.z2 = state.gZone;
38279            break;
38280        default :
38281            throw new Error('Invalid zone pointer');
38282    }
38283}
38284
38285// SLOOP[] Set LOOP variable
38286// 0x17
38287function SLOOP(state) {
38288    state.loop = state.stack.pop();
38289
38290    if (exports.DEBUG) { console.log(state.step, 'SLOOP[]', state.loop); }
38291}
38292
38293// RTG[] Round To Grid
38294// 0x18
38295function RTG(state) {
38296    if (exports.DEBUG) { console.log(state.step, 'RTG[]'); }
38297
38298    state.round = roundToGrid;
38299}
38300
38301// RTHG[] Round To Half Grid
38302// 0x19
38303function RTHG(state) {
38304    if (exports.DEBUG) { console.log(state.step, 'RTHG[]'); }
38305
38306    state.round = roundToHalfGrid;
38307}
38308
38309// SMD[] Set Minimum Distance
38310// 0x1A
38311function SMD(state) {
38312    var d = state.stack.pop();
38313
38314    if (exports.DEBUG) { console.log(state.step, 'SMD[]', d); }
38315
38316    state.minDis = d / 0x40;
38317}
38318
38319// ELSE[] ELSE clause
38320// 0x1B
38321function ELSE(state) {
38322    // This instruction has been reached by executing a then branch
38323    // so it just skips ahead until matching EIF.
38324    //
38325    // In case the IF was negative the IF[] instruction already
38326    // skipped forward over the ELSE[]
38327
38328    if (exports.DEBUG) { console.log(state.step, 'ELSE[]'); }
38329
38330    skip(state, false);
38331}
38332
38333// JMPR[] JuMP Relative
38334// 0x1C
38335function JMPR(state) {
38336    var o = state.stack.pop();
38337
38338    if (exports.DEBUG) { console.log(state.step, 'JMPR[]', o); }
38339
38340    // A jump by 1 would do nothing.
38341    state.ip += o - 1;
38342}
38343
38344// SCVTCI[] Set Control Value Table Cut-In
38345// 0x1D
38346function SCVTCI(state) {
38347    var n = state.stack.pop();
38348
38349    if (exports.DEBUG) { console.log(state.step, 'SCVTCI[]', n); }
38350
38351    state.cvCutIn = n / 0x40;
38352}
38353
38354// DUP[] DUPlicate top stack element
38355// 0x20
38356function DUP(state) {
38357    var stack = state.stack;
38358
38359    if (exports.DEBUG) { console.log(state.step, 'DUP[]'); }
38360
38361    stack.push(stack[stack.length - 1]);
38362}
38363
38364// POP[] POP top stack element
38365// 0x21
38366function POP(state) {
38367    if (exports.DEBUG) { console.log(state.step, 'POP[]'); }
38368
38369    state.stack.pop();
38370}
38371
38372// CLEAR[] CLEAR the stack
38373// 0x22
38374function CLEAR(state) {
38375    if (exports.DEBUG) { console.log(state.step, 'CLEAR[]'); }
38376
38377    state.stack.length = 0;
38378}
38379
38380// SWAP[] SWAP the top two elements on the stack
38381// 0x23
38382function SWAP(state) {
38383    var stack = state.stack;
38384
38385    var a = stack.pop();
38386    var b = stack.pop();
38387
38388    if (exports.DEBUG) { console.log(state.step, 'SWAP[]'); }
38389
38390    stack.push(a);
38391    stack.push(b);
38392}
38393
38394// DEPTH[] DEPTH of the stack
38395// 0x24
38396function DEPTH(state) {
38397    var stack = state.stack;
38398
38399    if (exports.DEBUG) { console.log(state.step, 'DEPTH[]'); }
38400
38401    stack.push(stack.length);
38402}
38403
38404// LOOPCALL[] LOOPCALL function
38405// 0x2A
38406function LOOPCALL(state) {
38407    var stack = state.stack;
38408    var fn = stack.pop();
38409    var c = stack.pop();
38410
38411    if (exports.DEBUG) { console.log(state.step, 'LOOPCALL[]', fn, c); }
38412
38413    // saves callers program
38414    var cip = state.ip;
38415    var cprog = state.prog;
38416
38417    state.prog = state.funcs[fn];
38418
38419    // executes the function
38420    for (var i = 0; i < c; i++) {
38421        exec(state);
38422
38423        if (exports.DEBUG) { console.log(
38424            ++state.step,
38425            i + 1 < c ? 'next loopcall' : 'done loopcall',
38426            i
38427        ); }
38428    }
38429
38430    // restores the callers program
38431    state.ip = cip;
38432    state.prog = cprog;
38433}
38434
38435// CALL[] CALL function
38436// 0x2B
38437function CALL(state) {
38438    var fn = state.stack.pop();
38439
38440    if (exports.DEBUG) { console.log(state.step, 'CALL[]', fn); }
38441
38442    // saves callers program
38443    var cip = state.ip;
38444    var cprog = state.prog;
38445
38446    state.prog = state.funcs[fn];
38447
38448    // executes the function
38449    exec(state);
38450
38451    // restores the callers program
38452    state.ip = cip;
38453    state.prog = cprog;
38454
38455    if (exports.DEBUG) { console.log(++state.step, 'returning from', fn); }
38456}
38457
38458// CINDEX[] Copy the INDEXed element to the top of the stack
38459// 0x25
38460function CINDEX(state) {
38461    var stack = state.stack;
38462    var k = stack.pop();
38463
38464    if (exports.DEBUG) { console.log(state.step, 'CINDEX[]', k); }
38465
38466    // In case of k == 1, it copies the last element after popping
38467    // thus stack.length - k.
38468    stack.push(stack[stack.length - k]);
38469}
38470
38471// MINDEX[] Move the INDEXed element to the top of the stack
38472// 0x26
38473function MINDEX(state) {
38474    var stack = state.stack;
38475    var k = stack.pop();
38476
38477    if (exports.DEBUG) { console.log(state.step, 'MINDEX[]', k); }
38478
38479    stack.push(stack.splice(stack.length - k, 1)[0]);
38480}
38481
38482// FDEF[] Function DEFinition
38483// 0x2C
38484function FDEF(state) {
38485    if (state.env !== 'fpgm') { throw new Error('FDEF not allowed here'); }
38486    var stack = state.stack;
38487    var prog = state.prog;
38488    var ip = state.ip;
38489
38490    var fn = stack.pop();
38491    var ipBegin = ip;
38492
38493    if (exports.DEBUG) { console.log(state.step, 'FDEF[]', fn); }
38494
38495    while (prog[++ip] !== 0x2D){  }
38496
38497    state.ip = ip;
38498    state.funcs[fn] = prog.slice(ipBegin + 1, ip);
38499}
38500
38501// MDAP[a] Move Direct Absolute Point
38502// 0x2E-0x2F
38503function MDAP(round, state) {
38504    var pi = state.stack.pop();
38505    var p = state.z0[pi];
38506    var fv = state.fv;
38507    var pv = state.pv;
38508
38509    if (exports.DEBUG) { console.log(state.step, 'MDAP[' + round + ']', pi); }
38510
38511    var d = pv.distance(p, HPZero);
38512
38513    if (round) { d = state.round(d); }
38514
38515    fv.setRelative(p, HPZero, d, pv);
38516    fv.touch(p);
38517
38518    state.rp0 = state.rp1 = pi;
38519}
38520
38521// IUP[a] Interpolate Untouched Points through the outline
38522// 0x30
38523function IUP(v, state) {
38524    var z2 = state.z2;
38525    var pLen = z2.length - 2;
38526    var cp;
38527    var pp;
38528    var np;
38529
38530    if (exports.DEBUG) { console.log(state.step, 'IUP[' + v.axis + ']'); }
38531
38532    for (var i = 0; i < pLen; i++) {
38533        cp = z2[i]; // current point
38534
38535        // if this point has been touched go on
38536        if (v.touched(cp)) { continue; }
38537
38538        pp = cp.prevTouched(v);
38539
38540        // no point on the contour has been touched?
38541        if (pp === cp) { continue; }
38542
38543        np = cp.nextTouched(v);
38544
38545        if (pp === np) {
38546            // only one point on the contour has been touched
38547            // so simply moves the point like that
38548
38549            v.setRelative(cp, cp, v.distance(pp, pp, false, true), v, true);
38550        }
38551
38552        v.interpolate(cp, pp, np, v);
38553    }
38554}
38555
38556// SHP[] SHift Point using reference point
38557// 0x32-0x33
38558function SHP(a, state) {
38559    var stack = state.stack;
38560    var rpi = a ? state.rp1 : state.rp2;
38561    var rp = (a ? state.z0 : state.z1)[rpi];
38562    var fv = state.fv;
38563    var pv = state.pv;
38564    var loop = state.loop;
38565    var z2 = state.z2;
38566
38567    while (loop--)
38568    {
38569        var pi = stack.pop();
38570        var p = z2[pi];
38571
38572        var d = pv.distance(rp, rp, false, true);
38573        fv.setRelative(p, p, d, pv);
38574        fv.touch(p);
38575
38576        if (exports.DEBUG) {
38577            console.log(
38578                state.step,
38579                (state.loop > 1 ?
38580                   'loop ' + (state.loop - loop) + ': ' :
38581                   ''
38582                ) +
38583                'SHP[' + (a ? 'rp1' : 'rp2') + ']', pi
38584            );
38585        }
38586    }
38587
38588    state.loop = 1;
38589}
38590
38591// SHC[] SHift Contour using reference point
38592// 0x36-0x37
38593function SHC(a, state) {
38594    var stack = state.stack;
38595    var rpi = a ? state.rp1 : state.rp2;
38596    var rp = (a ? state.z0 : state.z1)[rpi];
38597    var fv = state.fv;
38598    var pv = state.pv;
38599    var ci = stack.pop();
38600    var sp = state.z2[state.contours[ci]];
38601    var p = sp;
38602
38603    if (exports.DEBUG) { console.log(state.step, 'SHC[' + a + ']', ci); }
38604
38605    var d = pv.distance(rp, rp, false, true);
38606
38607    do {
38608        if (p !== rp) { fv.setRelative(p, p, d, pv); }
38609        p = p.nextPointOnContour;
38610    } while (p !== sp);
38611}
38612
38613// SHZ[] SHift Zone using reference point
38614// 0x36-0x37
38615function SHZ(a, state) {
38616    var stack = state.stack;
38617    var rpi = a ? state.rp1 : state.rp2;
38618    var rp = (a ? state.z0 : state.z1)[rpi];
38619    var fv = state.fv;
38620    var pv = state.pv;
38621
38622    var e = stack.pop();
38623
38624    if (exports.DEBUG) { console.log(state.step, 'SHZ[' + a + ']', e); }
38625
38626    var z;
38627    switch (e) {
38628        case 0 : z = state.tZone; break;
38629        case 1 : z = state.gZone; break;
38630        default : throw new Error('Invalid zone');
38631    }
38632
38633    var p;
38634    var d = pv.distance(rp, rp, false, true);
38635    var pLen = z.length - 2;
38636    for (var i = 0; i < pLen; i++)
38637    {
38638        p = z[i];
38639        if (p !== rp) { fv.setRelative(p, p, d, pv); }
38640    }
38641}
38642
38643// SHPIX[] SHift point by a PIXel amount
38644// 0x38
38645function SHPIX(state) {
38646    var stack = state.stack;
38647    var loop = state.loop;
38648    var fv = state.fv;
38649    var d = stack.pop() / 0x40;
38650    var z2 = state.z2;
38651
38652    while (loop--) {
38653        var pi = stack.pop();
38654        var p = z2[pi];
38655
38656        if (exports.DEBUG) {
38657            console.log(
38658                state.step,
38659                (state.loop > 1 ? 'loop ' + (state.loop - loop) + ': ' : '') +
38660                'SHPIX[]', pi, d
38661            );
38662        }
38663
38664        fv.setRelative(p, p, d);
38665        fv.touch(p);
38666    }
38667
38668    state.loop = 1;
38669}
38670
38671// IP[] Interpolate Point
38672// 0x39
38673function IP(state) {
38674    var stack = state.stack;
38675    var rp1i = state.rp1;
38676    var rp2i = state.rp2;
38677    var loop = state.loop;
38678    var rp1 = state.z0[rp1i];
38679    var rp2 = state.z1[rp2i];
38680    var fv = state.fv;
38681    var pv = state.dpv;
38682    var z2 = state.z2;
38683
38684    while (loop--) {
38685        var pi = stack.pop();
38686        var p = z2[pi];
38687
38688        if (exports.DEBUG) {
38689            console.log(
38690                state.step,
38691                (state.loop > 1 ? 'loop ' + (state.loop - loop) + ': ' : '') +
38692                'IP[]', pi, rp1i, '<->', rp2i
38693            );
38694        }
38695
38696        fv.interpolate(p, rp1, rp2, pv);
38697
38698        fv.touch(p);
38699    }
38700
38701    state.loop = 1;
38702}
38703
38704// MSIRP[a] Move Stack Indirect Relative Point
38705// 0x3A-0x3B
38706function MSIRP(a, state) {
38707    var stack = state.stack;
38708    var d = stack.pop() / 64;
38709    var pi = stack.pop();
38710    var p = state.z1[pi];
38711    var rp0 = state.z0[state.rp0];
38712    var fv = state.fv;
38713    var pv = state.pv;
38714
38715    fv.setRelative(p, rp0, d, pv);
38716    fv.touch(p);
38717
38718    if (exports.DEBUG) { console.log(state.step, 'MSIRP[' + a + ']', d, pi); }
38719
38720    state.rp1 = state.rp0;
38721    state.rp2 = pi;
38722    if (a) { state.rp0 = pi; }
38723}
38724
38725// ALIGNRP[] Align to reference point.
38726// 0x3C
38727function ALIGNRP(state) {
38728    var stack = state.stack;
38729    var rp0i = state.rp0;
38730    var rp0 = state.z0[rp0i];
38731    var loop = state.loop;
38732    var fv = state.fv;
38733    var pv = state.pv;
38734    var z1 = state.z1;
38735
38736    while (loop--) {
38737        var pi = stack.pop();
38738        var p = z1[pi];
38739
38740        if (exports.DEBUG) {
38741            console.log(
38742                state.step,
38743                (state.loop > 1 ? 'loop ' + (state.loop - loop) + ': ' : '') +
38744                'ALIGNRP[]', pi
38745            );
38746        }
38747
38748        fv.setRelative(p, rp0, 0, pv);
38749        fv.touch(p);
38750    }
38751
38752    state.loop = 1;
38753}
38754
38755// RTG[] Round To Double Grid
38756// 0x3D
38757function RTDG(state) {
38758    if (exports.DEBUG) { console.log(state.step, 'RTDG[]'); }
38759
38760    state.round = roundToDoubleGrid;
38761}
38762
38763// MIAP[a] Move Indirect Absolute Point
38764// 0x3E-0x3F
38765function MIAP(round, state) {
38766    var stack = state.stack;
38767    var n = stack.pop();
38768    var pi = stack.pop();
38769    var p = state.z0[pi];
38770    var fv = state.fv;
38771    var pv = state.pv;
38772    var cv = state.cvt[n];
38773
38774    // TODO cvtcutin should be considered here
38775    if (round) { cv = state.round(cv); }
38776
38777    if (exports.DEBUG) {
38778        console.log(
38779            state.step,
38780            'MIAP[' + round + ']',
38781            n, '(', cv, ')', pi
38782        );
38783    }
38784
38785    fv.setRelative(p, HPZero, cv, pv);
38786
38787    if (state.zp0 === 0) {
38788        p.xo = p.x;
38789        p.yo = p.y;
38790    }
38791
38792    fv.touch(p);
38793
38794    state.rp0 = state.rp1 = pi;
38795}
38796
38797// NPUSB[] PUSH N Bytes
38798// 0x40
38799function NPUSHB(state) {
38800    var prog = state.prog;
38801    var ip = state.ip;
38802    var stack = state.stack;
38803
38804    var n = prog[++ip];
38805
38806    if (exports.DEBUG) { console.log(state.step, 'NPUSHB[]', n); }
38807
38808    for (var i = 0; i < n; i++) { stack.push(prog[++ip]); }
38809
38810    state.ip = ip;
38811}
38812
38813// NPUSHW[] PUSH N Words
38814// 0x41
38815function NPUSHW(state) {
38816    var ip = state.ip;
38817    var prog = state.prog;
38818    var stack = state.stack;
38819    var n = prog[++ip];
38820
38821    if (exports.DEBUG) { console.log(state.step, 'NPUSHW[]', n); }
38822
38823    for (var i = 0; i < n; i++) {
38824        var w = (prog[++ip] << 8) | prog[++ip];
38825        if (w & 0x8000) { w = -((w ^ 0xffff) + 1); }
38826        stack.push(w);
38827    }
38828
38829    state.ip = ip;
38830}
38831
38832// WS[] Write Store
38833// 0x42
38834function WS(state) {
38835    var stack = state.stack;
38836    var store = state.store;
38837
38838    if (!store) { store = state.store = []; }
38839
38840    var v = stack.pop();
38841    var l = stack.pop();
38842
38843    if (exports.DEBUG) { console.log(state.step, 'WS', v, l); }
38844
38845    store[l] = v;
38846}
38847
38848// RS[] Read Store
38849// 0x43
38850function RS(state) {
38851    var stack = state.stack;
38852    var store = state.store;
38853
38854    var l = stack.pop();
38855
38856    if (exports.DEBUG) { console.log(state.step, 'RS', l); }
38857
38858    var v = (store && store[l]) || 0;
38859
38860    stack.push(v);
38861}
38862
38863// WCVTP[] Write Control Value Table in Pixel units
38864// 0x44
38865function WCVTP(state) {
38866    var stack = state.stack;
38867
38868    var v = stack.pop();
38869    var l = stack.pop();
38870
38871    if (exports.DEBUG) { console.log(state.step, 'WCVTP', v, l); }
38872
38873    state.cvt[l] = v / 0x40;
38874}
38875
38876// RCVT[] Read Control Value Table entry
38877// 0x45
38878function RCVT(state) {
38879    var stack = state.stack;
38880    var cvte = stack.pop();
38881
38882    if (exports.DEBUG) { console.log(state.step, 'RCVT', cvte); }
38883
38884    stack.push(state.cvt[cvte] * 0x40);
38885}
38886
38887// GC[] Get Coordinate projected onto the projection vector
38888// 0x46-0x47
38889function GC(a, state) {
38890    var stack = state.stack;
38891    var pi = stack.pop();
38892    var p = state.z2[pi];
38893
38894    if (exports.DEBUG) { console.log(state.step, 'GC[' + a + ']', pi); }
38895
38896    stack.push(state.dpv.distance(p, HPZero, a, false) * 0x40);
38897}
38898
38899// MD[a] Measure Distance
38900// 0x49-0x4A
38901function MD(a, state) {
38902    var stack = state.stack;
38903    var pi2 = stack.pop();
38904    var pi1 = stack.pop();
38905    var p2 = state.z1[pi2];
38906    var p1 = state.z0[pi1];
38907    var d = state.dpv.distance(p1, p2, a, a);
38908
38909    if (exports.DEBUG) { console.log(state.step, 'MD[' + a + ']', pi2, pi1, '->', d); }
38910
38911    state.stack.push(Math.round(d * 64));
38912}
38913
38914// MPPEM[] Measure Pixels Per EM
38915// 0x4B
38916function MPPEM(state) {
38917    if (exports.DEBUG) { console.log(state.step, 'MPPEM[]'); }
38918    state.stack.push(state.ppem);
38919}
38920
38921// FLIPON[] set the auto FLIP Boolean to ON
38922// 0x4D
38923function FLIPON(state) {
38924    if (exports.DEBUG) { console.log(state.step, 'FLIPON[]'); }
38925    state.autoFlip = true;
38926}
38927
38928// LT[] Less Than
38929// 0x50
38930function LT(state) {
38931    var stack = state.stack;
38932    var e2 = stack.pop();
38933    var e1 = stack.pop();
38934
38935    if (exports.DEBUG) { console.log(state.step, 'LT[]', e2, e1); }
38936
38937    stack.push(e1 < e2 ? 1 : 0);
38938}
38939
38940// LTEQ[] Less Than or EQual
38941// 0x53
38942function LTEQ(state) {
38943    var stack = state.stack;
38944    var e2 = stack.pop();
38945    var e1 = stack.pop();
38946
38947    if (exports.DEBUG) { console.log(state.step, 'LTEQ[]', e2, e1); }
38948
38949    stack.push(e1 <= e2 ? 1 : 0);
38950}
38951
38952// GTEQ[] Greater Than
38953// 0x52
38954function GT(state) {
38955    var stack = state.stack;
38956    var e2 = stack.pop();
38957    var e1 = stack.pop();
38958
38959    if (exports.DEBUG) { console.log(state.step, 'GT[]', e2, e1); }
38960
38961    stack.push(e1 > e2 ? 1 : 0);
38962}
38963
38964// GTEQ[] Greater Than or EQual
38965// 0x53
38966function GTEQ(state) {
38967    var stack = state.stack;
38968    var e2 = stack.pop();
38969    var e1 = stack.pop();
38970
38971    if (exports.DEBUG) { console.log(state.step, 'GTEQ[]', e2, e1); }
38972
38973    stack.push(e1 >= e2 ? 1 : 0);
38974}
38975
38976// EQ[] EQual
38977// 0x54
38978function EQ(state) {
38979    var stack = state.stack;
38980    var e2 = stack.pop();
38981    var e1 = stack.pop();
38982
38983    if (exports.DEBUG) { console.log(state.step, 'EQ[]', e2, e1); }
38984
38985    stack.push(e2 === e1 ? 1 : 0);
38986}
38987
38988// NEQ[] Not EQual
38989// 0x55
38990function NEQ(state) {
38991    var stack = state.stack;
38992    var e2 = stack.pop();
38993    var e1 = stack.pop();
38994
38995    if (exports.DEBUG) { console.log(state.step, 'NEQ[]', e2, e1); }
38996
38997    stack.push(e2 !== e1 ? 1 : 0);
38998}
38999
39000// ODD[] ODD
39001// 0x56
39002function ODD(state) {
39003    var stack = state.stack;
39004    var n = stack.pop();
39005
39006    if (exports.DEBUG) { console.log(state.step, 'ODD[]', n); }
39007
39008    stack.push(Math.trunc(n) % 2 ? 1 : 0);
39009}
39010
39011// EVEN[] EVEN
39012// 0x57
39013function EVEN(state) {
39014    var stack = state.stack;
39015    var n = stack.pop();
39016
39017    if (exports.DEBUG) { console.log(state.step, 'EVEN[]', n); }
39018
39019    stack.push(Math.trunc(n) % 2 ? 0 : 1);
39020}
39021
39022// IF[] IF test
39023// 0x58
39024function IF(state) {
39025    var test = state.stack.pop();
39026    var ins;
39027
39028    if (exports.DEBUG) { console.log(state.step, 'IF[]', test); }
39029
39030    // if test is true it just continues
39031    // if not the ip is skipped until matching ELSE or EIF
39032    if (!test) {
39033        skip(state, true);
39034
39035        if (exports.DEBUG) { console.log(state.step, ins === 0x1B ? 'ELSE[]' : 'EIF[]'); }
39036    }
39037}
39038
39039// EIF[] End IF
39040// 0x59
39041function EIF(state) {
39042    // this can be reached normally when
39043    // executing an else branch.
39044    // -> just ignore it
39045
39046    if (exports.DEBUG) { console.log(state.step, 'EIF[]'); }
39047}
39048
39049// AND[] logical AND
39050// 0x5A
39051function AND(state) {
39052    var stack = state.stack;
39053    var e2 = stack.pop();
39054    var e1 = stack.pop();
39055
39056    if (exports.DEBUG) { console.log(state.step, 'AND[]', e2, e1); }
39057
39058    stack.push(e2 && e1 ? 1 : 0);
39059}
39060
39061// OR[] logical OR
39062// 0x5B
39063function OR(state) {
39064    var stack = state.stack;
39065    var e2 = stack.pop();
39066    var e1 = stack.pop();
39067
39068    if (exports.DEBUG) { console.log(state.step, 'OR[]', e2, e1); }
39069
39070    stack.push(e2 || e1 ? 1 : 0);
39071}
39072
39073// NOT[] logical NOT
39074// 0x5C
39075function NOT(state) {
39076    var stack = state.stack;
39077    var e = stack.pop();
39078
39079    if (exports.DEBUG) { console.log(state.step, 'NOT[]', e); }
39080
39081    stack.push(e ? 0 : 1);
39082}
39083
39084// DELTAP1[] DELTA exception P1
39085// DELTAP2[] DELTA exception P2
39086// DELTAP3[] DELTA exception P3
39087// 0x5D, 0x71, 0x72
39088function DELTAP123(b, state) {
39089    var stack = state.stack;
39090    var n = stack.pop();
39091    var fv = state.fv;
39092    var pv = state.pv;
39093    var ppem = state.ppem;
39094    var base = state.deltaBase + (b - 1) * 16;
39095    var ds = state.deltaShift;
39096    var z0 = state.z0;
39097
39098    if (exports.DEBUG) { console.log(state.step, 'DELTAP[' + b + ']', n, stack); }
39099
39100    for (var i = 0; i < n; i++)
39101    {
39102        var pi = stack.pop();
39103        var arg = stack.pop();
39104        var appem = base + ((arg & 0xF0) >> 4);
39105        if (appem !== ppem) { continue; }
39106
39107        var mag = (arg & 0x0F) - 8;
39108        if (mag >= 0) { mag++; }
39109        if (exports.DEBUG) { console.log(state.step, 'DELTAPFIX', pi, 'by', mag * ds); }
39110
39111        var p = z0[pi];
39112        fv.setRelative(p, p, mag * ds, pv);
39113    }
39114}
39115
39116// SDB[] Set Delta Base in the graphics state
39117// 0x5E
39118function SDB(state) {
39119    var stack = state.stack;
39120    var n = stack.pop();
39121
39122    if (exports.DEBUG) { console.log(state.step, 'SDB[]', n); }
39123
39124    state.deltaBase = n;
39125}
39126
39127// SDS[] Set Delta Shift in the graphics state
39128// 0x5F
39129function SDS(state) {
39130    var stack = state.stack;
39131    var n = stack.pop();
39132
39133    if (exports.DEBUG) { console.log(state.step, 'SDS[]', n); }
39134
39135    state.deltaShift = Math.pow(0.5, n);
39136}
39137
39138// ADD[] ADD
39139// 0x60
39140function ADD(state) {
39141    var stack = state.stack;
39142    var n2 = stack.pop();
39143    var n1 = stack.pop();
39144
39145    if (exports.DEBUG) { console.log(state.step, 'ADD[]', n2, n1); }
39146
39147    stack.push(n1 + n2);
39148}
39149
39150// SUB[] SUB
39151// 0x61
39152function SUB(state) {
39153    var stack = state.stack;
39154    var n2 = stack.pop();
39155    var n1 = stack.pop();
39156
39157    if (exports.DEBUG) { console.log(state.step, 'SUB[]', n2, n1); }
39158
39159    stack.push(n1 - n2);
39160}
39161
39162// DIV[] DIV
39163// 0x62
39164function DIV(state) {
39165    var stack = state.stack;
39166    var n2 = stack.pop();
39167    var n1 = stack.pop();
39168
39169    if (exports.DEBUG) { console.log(state.step, 'DIV[]', n2, n1); }
39170
39171    stack.push(n1 * 64 / n2);
39172}
39173
39174// MUL[] MUL
39175// 0x63
39176function MUL(state) {
39177    var stack = state.stack;
39178    var n2 = stack.pop();
39179    var n1 = stack.pop();
39180
39181    if (exports.DEBUG) { console.log(state.step, 'MUL[]', n2, n1); }
39182
39183    stack.push(n1 * n2 / 64);
39184}
39185
39186// ABS[] ABSolute value
39187// 0x64
39188function ABS(state) {
39189    var stack = state.stack;
39190    var n = stack.pop();
39191
39192    if (exports.DEBUG) { console.log(state.step, 'ABS[]', n); }
39193
39194    stack.push(Math.abs(n));
39195}
39196
39197// NEG[] NEGate
39198// 0x65
39199function NEG(state) {
39200    var stack = state.stack;
39201    var n = stack.pop();
39202
39203    if (exports.DEBUG) { console.log(state.step, 'NEG[]', n); }
39204
39205    stack.push(-n);
39206}
39207
39208// FLOOR[] FLOOR
39209// 0x66
39210function FLOOR(state) {
39211    var stack = state.stack;
39212    var n = stack.pop();
39213
39214    if (exports.DEBUG) { console.log(state.step, 'FLOOR[]', n); }
39215
39216    stack.push(Math.floor(n / 0x40) * 0x40);
39217}
39218
39219// CEILING[] CEILING
39220// 0x67
39221function CEILING(state) {
39222    var stack = state.stack;
39223    var n = stack.pop();
39224
39225    if (exports.DEBUG) { console.log(state.step, 'CEILING[]', n); }
39226
39227    stack.push(Math.ceil(n / 0x40) * 0x40);
39228}
39229
39230// ROUND[ab] ROUND value
39231// 0x68-0x6B
39232function ROUND(dt, state) {
39233    var stack = state.stack;
39234    var n = stack.pop();
39235
39236    if (exports.DEBUG) { console.log(state.step, 'ROUND[]'); }
39237
39238    stack.push(state.round(n / 0x40) * 0x40);
39239}
39240
39241// WCVTF[] Write Control Value Table in Funits
39242// 0x70
39243function WCVTF(state) {
39244    var stack = state.stack;
39245    var v = stack.pop();
39246    var l = stack.pop();
39247
39248    if (exports.DEBUG) { console.log(state.step, 'WCVTF[]', v, l); }
39249
39250    state.cvt[l] = v * state.ppem / state.font.unitsPerEm;
39251}
39252
39253// DELTAC1[] DELTA exception C1
39254// DELTAC2[] DELTA exception C2
39255// DELTAC3[] DELTA exception C3
39256// 0x73, 0x74, 0x75
39257function DELTAC123(b, state) {
39258    var stack = state.stack;
39259    var n = stack.pop();
39260    var ppem = state.ppem;
39261    var base = state.deltaBase + (b - 1) * 16;
39262    var ds = state.deltaShift;
39263
39264    if (exports.DEBUG) { console.log(state.step, 'DELTAC[' + b + ']', n, stack); }
39265
39266    for (var i = 0; i < n; i++) {
39267        var c = stack.pop();
39268        var arg = stack.pop();
39269        var appem = base + ((arg & 0xF0) >> 4);
39270        if (appem !== ppem) { continue; }
39271
39272        var mag = (arg & 0x0F) - 8;
39273        if (mag >= 0) { mag++; }
39274
39275        var delta = mag * ds;
39276
39277        if (exports.DEBUG) { console.log(state.step, 'DELTACFIX', c, 'by', delta); }
39278
39279        state.cvt[c] += delta;
39280    }
39281}
39282
39283// SROUND[] Super ROUND
39284// 0x76
39285function SROUND(state) {
39286    var n = state.stack.pop();
39287
39288    if (exports.DEBUG) { console.log(state.step, 'SROUND[]', n); }
39289
39290    state.round = roundSuper;
39291
39292    var period;
39293
39294    switch (n & 0xC0) {
39295        case 0x00:
39296            period = 0.5;
39297            break;
39298        case 0x40:
39299            period = 1;
39300            break;
39301        case 0x80:
39302            period = 2;
39303            break;
39304        default:
39305            throw new Error('invalid SROUND value');
39306    }
39307
39308    state.srPeriod = period;
39309
39310    switch (n & 0x30) {
39311        case 0x00:
39312            state.srPhase = 0;
39313            break;
39314        case 0x10:
39315            state.srPhase = 0.25 * period;
39316            break;
39317        case 0x20:
39318            state.srPhase = 0.5  * period;
39319            break;
39320        case 0x30:
39321            state.srPhase = 0.75 * period;
39322            break;
39323        default: throw new Error('invalid SROUND value');
39324    }
39325
39326    n &= 0x0F;
39327
39328    if (n === 0) { state.srThreshold = 0; }
39329    else { state.srThreshold = (n / 8 - 0.5) * period; }
39330}
39331
39332// S45ROUND[] Super ROUND 45 degrees
39333// 0x77
39334function S45ROUND(state) {
39335    var n = state.stack.pop();
39336
39337    if (exports.DEBUG) { console.log(state.step, 'S45ROUND[]', n); }
39338
39339    state.round = roundSuper;
39340
39341    var period;
39342
39343    switch (n & 0xC0) {
39344        case 0x00:
39345            period = Math.sqrt(2) / 2;
39346            break;
39347        case 0x40:
39348            period = Math.sqrt(2);
39349            break;
39350        case 0x80:
39351            period = 2 * Math.sqrt(2);
39352            break;
39353        default:
39354            throw new Error('invalid S45ROUND value');
39355    }
39356
39357    state.srPeriod = period;
39358
39359    switch (n & 0x30) {
39360        case 0x00:
39361            state.srPhase = 0;
39362            break;
39363        case 0x10:
39364            state.srPhase = 0.25 * period;
39365            break;
39366        case 0x20:
39367            state.srPhase = 0.5  * period;
39368            break;
39369        case 0x30:
39370            state.srPhase = 0.75 * period;
39371            break;
39372        default:
39373            throw new Error('invalid S45ROUND value');
39374    }
39375
39376    n &= 0x0F;
39377
39378    if (n === 0) { state.srThreshold = 0; }
39379    else { state.srThreshold = (n / 8 - 0.5) * period; }
39380}
39381
39382// ROFF[] Round Off
39383// 0x7A
39384function ROFF(state) {
39385    if (exports.DEBUG) { console.log(state.step, 'ROFF[]'); }
39386
39387    state.round = roundOff;
39388}
39389
39390// RUTG[] Round Up To Grid
39391// 0x7C
39392function RUTG(state) {
39393    if (exports.DEBUG) { console.log(state.step, 'RUTG[]'); }
39394
39395    state.round = roundUpToGrid;
39396}
39397
39398// RDTG[] Round Down To Grid
39399// 0x7D
39400function RDTG(state) {
39401    if (exports.DEBUG) { console.log(state.step, 'RDTG[]'); }
39402
39403    state.round = roundDownToGrid;
39404}
39405
39406// SCANCTRL[] SCAN conversion ConTRoL
39407// 0x85
39408function SCANCTRL(state) {
39409    var n = state.stack.pop();
39410
39411    // ignored by opentype.js
39412
39413    if (exports.DEBUG) { console.log(state.step, 'SCANCTRL[]', n); }
39414}
39415
39416// SDPVTL[a] Set Dual Projection Vector To Line
39417// 0x86-0x87
39418function SDPVTL(a, state) {
39419    var stack = state.stack;
39420    var p2i = stack.pop();
39421    var p1i = stack.pop();
39422    var p2 = state.z2[p2i];
39423    var p1 = state.z1[p1i];
39424
39425    if (exports.DEBUG) { console.log('SDPVTL[' + a + ']', p2i, p1i); }
39426
39427    var dx;
39428    var dy;
39429
39430    if (!a) {
39431        dx = p1.x - p2.x;
39432        dy = p1.y - p2.y;
39433    } else {
39434        dx = p2.y - p1.y;
39435        dy = p1.x - p2.x;
39436    }
39437
39438    state.dpv = getUnitVector(dx, dy);
39439}
39440
39441// GETINFO[] GET INFOrmation
39442// 0x88
39443function GETINFO(state) {
39444    var stack = state.stack;
39445    var sel = stack.pop();
39446    var r = 0;
39447
39448    if (exports.DEBUG) { console.log(state.step, 'GETINFO[]', sel); }
39449
39450    // v35 as in no subpixel hinting
39451    if (sel & 0x01) { r = 35; }
39452
39453    // TODO rotation and stretch currently not supported
39454    // and thus those GETINFO are always 0.
39455
39456    // opentype.js is always gray scaling
39457    if (sel & 0x20) { r |= 0x1000; }
39458
39459    stack.push(r);
39460}
39461
39462// ROLL[] ROLL the top three stack elements
39463// 0x8A
39464function ROLL(state) {
39465    var stack = state.stack;
39466    var a = stack.pop();
39467    var b = stack.pop();
39468    var c = stack.pop();
39469
39470    if (exports.DEBUG) { console.log(state.step, 'ROLL[]'); }
39471
39472    stack.push(b);
39473    stack.push(a);
39474    stack.push(c);
39475}
39476
39477// MAX[] MAXimum of top two stack elements
39478// 0x8B
39479function MAX(state) {
39480    var stack = state.stack;
39481    var e2 = stack.pop();
39482    var e1 = stack.pop();
39483
39484    if (exports.DEBUG) { console.log(state.step, 'MAX[]', e2, e1); }
39485
39486    stack.push(Math.max(e1, e2));
39487}
39488
39489// MIN[] MINimum of top two stack elements
39490// 0x8C
39491function MIN(state) {
39492    var stack = state.stack;
39493    var e2 = stack.pop();
39494    var e1 = stack.pop();
39495
39496    if (exports.DEBUG) { console.log(state.step, 'MIN[]', e2, e1); }
39497
39498    stack.push(Math.min(e1, e2));
39499}
39500
39501// SCANTYPE[] SCANTYPE
39502// 0x8D
39503function SCANTYPE(state) {
39504    var n = state.stack.pop();
39505    // ignored by opentype.js
39506    if (exports.DEBUG) { console.log(state.step, 'SCANTYPE[]', n); }
39507}
39508
39509// INSTCTRL[] INSTCTRL
39510// 0x8D
39511function INSTCTRL(state) {
39512    var s = state.stack.pop();
39513    var v = state.stack.pop();
39514
39515    if (exports.DEBUG) { console.log(state.step, 'INSTCTRL[]', s, v); }
39516
39517    switch (s) {
39518        case 1 : state.inhibitGridFit = !!v; return;
39519        case 2 : state.ignoreCvt = !!v; return;
39520        default: throw new Error('invalid INSTCTRL[] selector');
39521    }
39522}
39523
39524// PUSHB[abc] PUSH Bytes
39525// 0xB0-0xB7
39526function PUSHB(n, state) {
39527    var stack = state.stack;
39528    var prog = state.prog;
39529    var ip = state.ip;
39530
39531    if (exports.DEBUG) { console.log(state.step, 'PUSHB[' + n + ']'); }
39532
39533    for (var i = 0; i < n; i++) { stack.push(prog[++ip]); }
39534
39535    state.ip = ip;
39536}
39537
39538// PUSHW[abc] PUSH Words
39539// 0xB8-0xBF
39540function PUSHW(n, state) {
39541    var ip = state.ip;
39542    var prog = state.prog;
39543    var stack = state.stack;
39544
39545    if (exports.DEBUG) { console.log(state.ip, 'PUSHW[' + n + ']'); }
39546
39547    for (var i = 0; i < n; i++) {
39548        var w = (prog[++ip] << 8) | prog[++ip];
39549        if (w & 0x8000) { w = -((w ^ 0xffff) + 1); }
39550        stack.push(w);
39551    }
39552
39553    state.ip = ip;
39554}
39555
39556// MDRP[abcde] Move Direct Relative Point
39557// 0xD0-0xEF
39558// (if indirect is 0)
39559//
39560// and
39561//
39562// MIRP[abcde] Move Indirect Relative Point
39563// 0xE0-0xFF
39564// (if indirect is 1)
39565
39566function MDRP_MIRP(indirect, setRp0, keepD, ro, dt, state) {
39567    var stack = state.stack;
39568    var cvte = indirect && stack.pop();
39569    var pi = stack.pop();
39570    var rp0i = state.rp0;
39571    var rp = state.z0[rp0i];
39572    var p = state.z1[pi];
39573
39574    var md = state.minDis;
39575    var fv = state.fv;
39576    var pv = state.dpv;
39577    var od; // original distance
39578    var d; // moving distance
39579    var sign; // sign of distance
39580    var cv;
39581
39582    d = od = pv.distance(p, rp, true, true);
39583    sign = d >= 0 ? 1 : -1; // Math.sign would be 0 in case of 0
39584
39585    // TODO consider autoFlip
39586    d = Math.abs(d);
39587
39588    if (indirect) {
39589        cv = state.cvt[cvte];
39590
39591        if (ro && Math.abs(d - cv) < state.cvCutIn) { d = cv; }
39592    }
39593
39594    if (keepD && d < md) { d = md; }
39595
39596    if (ro) { d = state.round(d); }
39597
39598    fv.setRelative(p, rp, sign * d, pv);
39599    fv.touch(p);
39600
39601    if (exports.DEBUG) {
39602        console.log(
39603            state.step,
39604            (indirect ? 'MIRP[' : 'MDRP[') +
39605            (setRp0 ? 'M' : 'm') +
39606            (keepD ? '>' : '_') +
39607            (ro ? 'R' : '_') +
39608            (dt === 0 ? 'Gr' : (dt === 1 ? 'Bl' : (dt === 2 ? 'Wh' : ''))) +
39609            ']',
39610            indirect ?
39611                cvte + '(' + state.cvt[cvte] + ',' +  cv + ')' :
39612                '',
39613            pi,
39614            '(d =', od, '->', sign * d, ')'
39615        );
39616    }
39617
39618    state.rp1 = state.rp0;
39619    state.rp2 = pi;
39620    if (setRp0) { state.rp0 = pi; }
39621}
39622
39623/*
39624* The instruction table.
39625*/
39626instructionTable = [
39627    /* 0x00 */ SVTCA.bind(undefined, yUnitVector),
39628    /* 0x01 */ SVTCA.bind(undefined, xUnitVector),
39629    /* 0x02 */ SPVTCA.bind(undefined, yUnitVector),
39630    /* 0x03 */ SPVTCA.bind(undefined, xUnitVector),
39631    /* 0x04 */ SFVTCA.bind(undefined, yUnitVec
39631tor),
39632    /* 0x05 */ SFVTCA.bind(undefined, xUnitVector),
39633    /* 0x06 */ SPVTL.bind(undefined, 0),
39634    /* 0x07 */ SPVTL.bind(undefined, 1),
39635    /* 0x08 */ SFVTL.bind(undefined, 0),
39636    /* 0x09 */ SFVTL.bind(undefined, 1),
39637    /* 0x0A */ SPVFS,
39638    /* 0x0B */ SFVFS,
39639    /* 0x0C */ GPV,
39640    /* 0x0D */ GFV,
39641    /* 0x0E */ SFVTPV,
39642    /* 0x0F */ ISECT,
39643    /* 0x10 */ SRP0,
39644    /* 0x11 */ SRP1,
39645    /* 0x12 */ SRP2,
39646    /* 0x13 */ SZP0,
39647    /* 0x14 */ SZP1,
39648    /* 0x15 */ SZP2,
39649    /* 0x16 */ SZPS,
39650    /* 0x17 */ SLOOP,
39651    /* 0x18 */ RTG,
39652    /* 0x19 */ RTHG,
39653    /* 0x1A */ SMD,
39654    /* 0x1B */ ELSE,
39655    /* 0x1C */ JMPR,
39656    /* 0x1D */ SCVTCI,
39657    /* 0x1E */ undefined,   // TODO SSWCI
39658    /* 0x1F */ undefined,   // TODO SSW
39659    /* 0x20 */ DUP,
39660    /* 0x21 */ POP,
39661    /* 0x22 */ CLEAR,
39662    /* 0x23 */ SWAP,
39663    /* 0x24 */ DEPTH,
39664    /* 0x25 */ CINDEX,
39665    /* 0x26 */ MINDEX,
39666    /* 0x27 */ undefined,   // TODO ALIGNPTS
39667    /* 0x28 */ undefined,
39668    /* 0x29 */ undefined,   // TODO UTP
39669    /* 0x2A */ LOOPCALL,
39670    /* 0x2B */ CALL,
39671    /* 0x2C */ FDEF,
39672    /* 0x2D */ undefined,   // ENDF (eaten by FDEF)
39673    /* 0x2E */ MDAP.bind(undefined, 0),
39674    /* 0x2F */ MDAP.bind(undefined, 1),
39675    /* 0x30 */ IUP.bind(undefined, yUnitVector),
39676    /* 0x31 */ IUP.bind(undefined, xUnitVector),
39677    /* 0x32 */ SHP.bind(undefined, 0),
39678    /* 0x33 */ SHP.bind(undefined, 1),
39679    /* 0x34 */ SHC.bind(undefined, 0),
39680    /* 0x35 */ SHC.bind(undefined, 1),
39681    /* 0x36 */ SHZ.bind(undefined, 0),
39682    /* 0x37 */ SHZ.bind(undefined, 1),
39683    /* 0x38 */ SHPIX,
39684    /* 0x39 */ IP,
39685    /* 0x3A */ MSIRP.bind(undefined, 0),
39686    /* 0x3B */ MSIRP.bind(undefined, 1),
39687    /* 0x3C */ ALIGNRP,
39688    /* 0x3D */ RTDG,
39689    /* 0x3E */ MIAP.bind(undefined, 0),
39690    /* 0x3F */ MIAP.bind(undefined, 1),
39691    /* 0x40 */ NPUSHB,
39692    /* 0x41 */ NPUSHW,
39693    /* 0x42 */ WS,
39694    /* 0x43 */ RS,
39695    /* 0x44 */ WCVTP,
39696    /* 0x45 */ RCVT,
39697    /* 0x46 */ GC.bind(undefined, 0),
39698    /* 0x47 */ GC.bind(undefined, 1),
39699    /* 0x48 */ undefined,   // TODO SCFS
39700    /* 0x49 */ MD.bind(undefined, 0),
39701    /* 0x4A */ MD.bind(undefined, 1),
39702    /* 0x4B */ MPPEM,
39703    /* 0x4C */ undefined,   // TODO MPS
39704    /* 0x4D */ FLIPON,
39705    /* 0x4E */ undefined,   // TODO FLIPOFF
39706    /* 0x4F */ undefined,   // TODO DEBUG
39707    /* 0x50 */ LT,
39708    /* 0x51 */ LTEQ,
39709    /* 0x52 */ GT,
39710    /* 0x53 */ GTEQ,
39711    /* 0x54 */ EQ,
39712    /* 0x55 */ NEQ,
39713    /* 0x56 */ ODD,
39714    /* 0x57 */ EVEN,
39715    /* 0x58 */ IF,
39716    /* 0x59 */ EIF,
39717    /* 0x5A */ AND,
39718    /* 0x5B */ OR,
39719    /* 0x5C */ NOT,
39720    /* 0x5D */ DELTAP123.bind(undefined, 1),
39721    /* 0x5E */ SDB,
39722    /* 0x5F */ SDS,
39723    /* 0x60 */ ADD,
39724    /* 0x61 */ SUB,
39725    /* 0x62 */ DIV,
39726    /* 0x63 */ MUL,
39727    /* 0x64 */ ABS,
39728    /* 0x65 */ NEG,
39729    /* 0x66 */ FLOOR,
39730    /* 0x67 */ CEILING,
39731    /* 0x68 */ ROUND.bind(undefined, 0),
39732    /* 0x69 */ ROUND.bind(undefined, 1),
39733    /* 0x6A */ ROUND.bind(undefined, 2),
39734    /* 0x6B */ ROUND.bind(undefined, 3),
39735    /* 0x6C */ undefined,   // TODO NROUND[ab]
39736    /* 0x6D */ undefined,   // TODO NROUND[ab]
39737    /* 0x6E */ undefined,   // TODO NROUND[ab]
39738    /* 0x6F */ undefined,   // TODO NROUND[ab]
39739    /* 0x70 */ WCVTF,
39740    /* 0x71 */ DELTAP123.bind(undefined, 2),
39741    /* 0x72 */ DELTAP123.bind(undefined, 3),
39742    /* 0x73 */ DELTAC123.bind(undefined, 1),
39743    /* 0x74 */ DELTAC123.bind(undefined, 2),
39744    /* 0x75 */ DELTAC123.bind(undefined, 3),
39745    /* 0x76 */ SROUND,
39746    /* 0x77 */ S45ROUND,
39747    /* 0x78 */ undefined,   // TODO JROT[]
39748    /* 0x79 */ undefined,   // TODO JROF[]
39749    /* 0x7A */ ROFF,
39750    /* 0x7B */ undefined,
39751    /* 0x7C */ RUTG,
39752    /* 0x7D */ RDTG,
39753    /* 0x7E */ POP, // actually SANGW, supposed to do only a pop though
39754    /* 0x7F */ POP, // actually AA, supposed to do only a pop though
39755    /* 0x80 */ undefined,   // TODO FLIPPT
39756    /* 0x81 */ undefined,   // TODO FLIPRGON
39757    /* 0x82 */ undefined,   // TODO FLIPRGOFF
39758    /* 0x83 */ undefined,
39759    /* 0x84 */ undefined,
39760    /* 0x85 */ SCANCTRL,
39761    /* 0x86 */ SDPVTL.bind(undefined, 0),
39762    /* 0x87 */ SDPVTL.bind(undefined, 1),
39763    /* 0x88 */ GETINFO,
39764    /* 0x89 */ undefined,   // TODO IDEF
39765    /* 0x8A */ ROLL,
39766    /* 0x8B */ MAX,
39767    /* 0x8C */ MIN,
39768    /* 0x8D */ SCANTYPE,
39769    /* 0x8E */ INSTCTRL,
39770    /* 0x8F */ undefined,
39771    /* 0x90 */ undefined,
39772    /* 0x91 */ undefined,
39773    /* 0x92 */ undefined,
39774    /* 0x93 */ undefined,
39775    /* 0x94 */ undefined,
39776    /* 0x95 */ undefined,
39777    /* 0x96 */ undefined,
39778    /* 0x97 */ undefined,
39779    /* 0x98 */ undefined,
39780    /* 0x99 */ undefined,
39781    /* 0x9A */ undefined,
39782    /* 0x9B */ undefined,
39783    /* 0x9C */ undefined,
39784    /* 0x9D */ undefined,
39785    /* 0x9E */ undefined,
39786    /* 0x9F */ undefined,
39787    /* 0xA0 */ undefined,
39788    /* 0xA1 */ undefined,
39789    /* 0xA2 */ undefined,
39790    /* 0xA3 */ undefined,
39791    /* 0xA4 */ undefined,
39792    /* 0xA5 */ undefined,
39793    /* 0xA6 */ undefined,
39794    /* 0xA7 */ undefined,
39795    /* 0xA8 */ undefined,
39796    /* 0xA9 */ undefined,
39797    /* 0xAA */ undefined,
39798    /* 0xAB */ undefined,
39799    /* 0xAC */ undefined,
39800    /* 0xAD */ undefined,
39801    /* 0xAE */ undefined,
39802    /* 0xAF */ undefined,
39803    /* 0xB0 */ PUSHB.bind(undefined, 1),
39804    /* 0xB1 */ PUSHB.bind(undefined, 2),
39805    /* 0xB2 */ PUSHB.bind(undefined, 3),
39806    /* 0xB3 */ PUSHB.bind(undefined, 4),
39807    /* 0xB4 */ PUSHB.bind(undefined, 5),
39808    /* 0xB5 */ PUSHB.bind(undefined, 6),
39809    /* 0xB6 */ PUSHB.bind(undefined, 7),
39810    /* 0xB7 */ PUSHB.bind(undefined, 8),
39811    /* 0xB8 */ PUSHW.bind(undefined, 1),
39812    /* 0xB9 */ PUSHW.bind(undefined, 2),
39813    /* 0xBA */ PUSHW.bind(undefined, 3),
39814    /* 0xBB */ PUSHW.bind(undefined, 4),
39815    /* 0xBC */ PUSHW.bind(undefined, 5),
39816    /* 0xBD */ PUSHW.bind(undefined, 6),
39817    /* 0xBE */ PUSHW.bind(undefined, 7),
39818    /* 0xBF */ PUSHW.bind(undefined, 8),
39819    /* 0xC0 */ MDRP_MIRP.bind(undefined, 0, 0, 0, 0, 0),
39820    /* 0xC1 */ MDRP_MIRP.bind(undefined, 0, 0, 0, 0, 1),
39821    /* 0xC2 */ MDRP_MIRP.bind(undefined, 0, 0, 0, 0, 2),
39822    /* 0xC3 */ MDRP_MIRP.bind(undefined, 0, 0, 0, 0, 3),
39823    /* 0xC4 */ MDRP_MIRP.bind(undefined, 0, 0, 0, 1, 0),
39824    /* 0xC5 */ MDRP_MIRP.bind(undefined, 0, 0, 0, 1, 1),
39825    /* 0xC6 */ MDRP_MIRP.bind(undefined, 0, 0, 0, 1, 2),
39826    /* 0xC7 */ MDRP_MIRP.bind(undefined, 0, 0, 0, 1, 3),
39827    /* 0xC8 */ MDRP_MIRP.bind(undefined, 0, 0, 1, 0, 0),
39828    /* 0xC9 */ MDRP_MIRP.bind(undefined, 0, 0, 1, 0, 1),
39829    /* 0xCA */ MDRP_MIRP.bind(undefined, 0, 0, 1, 0, 2),
39830    /* 0xCB */ MDRP_MIRP.bind(undefined, 0, 0, 1, 0, 3),
39831    /* 0xCC */ MDRP_MIRP.bind(undefined, 0, 0, 1, 1, 0),
39832    /* 0xCD */ MDRP_MIRP.bind(undefined, 0, 0, 1, 1, 1),
39833    /* 0xCE */ MDRP_MIRP.bind(undefined, 0, 0, 1, 1, 2),
39834    /* 0xCF */ MDRP_MIRP.bind(undefined, 0, 0, 1, 1, 3),
39835    /* 0xD0 */ MDRP_MIRP.bind(undefined, 0, 1, 0, 0, 0),
39836    /* 0xD1 */ MDRP_MIRP.bind(undefined, 0, 1, 0, 0, 1),
39837    /* 0xD2 */ MDRP_MIRP.bind(undefined, 0, 1, 0, 0, 2),
39838    /* 0xD3 */ MDRP_MIRP.bind(undefined, 0, 1, 0, 0, 3),
39839    /* 0xD4 */ MDRP_MIRP.bind(undefined, 0, 1, 0, 1, 0),
39840    /* 0xD5 */ MDRP_MIRP.bind(undefined, 0, 1, 0, 1, 1),
39841    /* 0xD6 */ MDRP_MIRP.bind(undefined, 0, 1, 0, 1, 2),
39842    /* 0xD7 */ MDRP_MIRP.bind(undefined, 0, 1, 0, 1, 3),
39843    /* 0xD8 */ MDRP_MIRP.bind(undefined, 0, 1, 1, 0, 0),
39844    /* 0xD9 */ MDRP_MIRP.bind(undefined, 0, 1, 1, 0, 1),
39845    /* 0xDA */ MDRP_MIRP.bind(undefined, 0, 1, 1, 0, 2),
39846    /* 0xDB */ MDRP_MIRP.bind(undefined, 0, 1, 1, 0, 3),
39847    /* 0xDC */ MDRP_MIRP.bind(undefined, 0, 1, 1, 1, 0),
39848    /* 0xDD */ MDRP_MIRP.bind(undefined, 0, 1, 1, 1, 1),
39849    /* 0xDE */ MDRP_MIRP.bind(undefined, 0, 1, 1, 1, 2),
39850    /* 0xDF */ MDRP_MIRP.bind(undefined, 0, 1, 1, 1, 3),
39851    /* 0xE0 */ MDRP_MIRP.bind(undefined, 1, 0, 0, 0, 0),
39852    /* 0xE1 */ MDRP_MIRP.bind(undefined, 1, 0, 0, 0, 1),
39853    /* 0xE2 */ MDRP_MIRP.bind(undefined, 1, 0, 0, 0, 2),
39854    /* 0xE3 */ MDRP_MIRP.bind(undefined, 1, 0, 0, 0, 3),
39855    /* 0xE4 */ MDRP_MIRP.bind(undefined, 1, 0, 0, 1, 0),
39856    /* 0xE5 */ MDRP_MIRP.bind(undefined, 1, 0, 0, 1, 1),
39857    /* 0xE6 */ MDRP_MIRP.bind(undefined, 1, 0, 0, 1, 2),
39858    /* 0xE7 */ MDRP_MIRP.bind(undefined, 1, 0, 0, 1, 3),
39859    /* 0xE8 */ MDRP_MIRP.bind(undefined, 1, 0, 1, 0, 0),
39860    /* 0xE9 */ MDRP_MIRP.bind(undefined, 1, 0, 1, 0, 1),
39861    /* 0xEA */ MDRP_MIRP.bind(undefined, 1, 0, 1, 0, 2),
39862    /* 0xEB */ MDRP_MIRP.bind(undefined, 1, 0, 1, 0, 3),
39863    /* 0xEC */ MDRP_MIRP.bind(undefined, 1, 0, 1, 1, 0),
39864    /* 0xED */ MDRP_MIRP.bind(undefined, 1, 0, 1, 1, 1),
39865    /* 0xEE */ MDRP_MIRP.bind(undefined, 1, 0, 1, 1, 2),
39866    /* 0xEF */ MDRP_MIRP.bind(undefined, 1, 0, 1, 1, 3),
39867    /* 0xF0 */ MDRP_MIRP.bind(undefined, 1, 1, 0, 0, 0),
39868    /* 0xF1 */ MDRP_MIRP.bind(undefined, 1, 1, 0, 0, 1),
39869    /* 0xF2 */ MDRP_MIRP.bind(undefined, 1, 1, 0, 0, 2),
39870    /* 0xF3 */ MDRP_MIRP.bind(undefined, 1, 1, 0, 0, 3),
39871    /* 0xF4 */ MDRP_MIRP.bind(undefined, 1, 1, 0, 1, 0),
39872    /* 0xF5 */ MDRP_MIRP.bind(undefined, 1, 1, 0, 1, 1),
39873    /* 0xF6 */ MDRP_MIRP.bind(undefined, 1, 1, 0, 1, 2),
39874    /* 0xF7 */ MDRP_MIRP.bind(undefined, 1, 1, 0, 1, 3),
39875    /* 0xF8 */ MDRP_MIRP.bind(undefined, 1, 1, 1, 0, 0),
39876    /* 0xF9 */ MDRP_MIRP.bind(undefined, 1, 1, 1, 0, 1),
39877    /* 0xFA */ MDRP_MIRP.bind(undefined, 1, 1, 1, 0, 2),
39878    /* 0xFB */ MDRP_MIRP.bind(undefined, 1, 1, 1, 0, 3),
39879    /* 0xFC */ MDRP_MIRP.bind(undefined, 1, 1, 1, 1, 0),
39880    /* 0xFD */ MDRP_MIRP.bind(undefined, 1, 1, 1, 1, 1),
39881    /* 0xFE */ MDRP_MIRP.bind(undefined, 1, 1, 1, 1, 2),
39882    /* 0xFF */ MDRP_MIRP.bind(undefined, 1, 1, 1, 1, 3)
39883];
39884
39885
39886
39887/*****************************
39888  Mathematical Considerations
39889******************************
39890
39891fv ... refers to freedom vector
39892pv ... refers to projection vector
39893rp ... refers to reference point
39894p  ... refers to to point being operated on
39895d  ... refers to distance
39896
39897SETRELATIVE:
39898============
39899
39900case freedom vector == x-axis:
39901------------------------------
39902
39903                        (pv)
39904                     .-'
39905              rpd .-'
39906               .-*
39907          d .-'90°'
39908         .-'       '
39909      .-'           '
39910   *-'               ' b
39911  rp                  '
39912                       '
39913                        '
39914            p *----------*-------------- (fv)
39915                          pm
39916
39917  rpdx = rpx + d * pv.x
39918  rpdy = rpy + d * pv.y
39919
39920  equation of line b
39921
39922   y - rpdy = pvns * (x- rpdx)
39923
39924   y = p.y
39925
39926   x = rpdx + ( p.y - rpdy ) / pvns
39927
39928
39929case freedom vector == y-axis:
39930------------------------------
39931
39932    * pm
39933    |\
39934    | \
39935    |  \
39936    |   \
39937    |    \
39938    |     \
39939    |      \
39940    |       \
39941    |        \
39942    |         \ b
39943    |          \
39944    |           \
39945    |            \    .-' (pv)
39946    |         90° \.-'
39947    |           .-'* rpd
39948    |        .-'
39949    *     *-'  d
39950    p     rp
39951
39952  rpdx = rpx + d * pv.x
39953  rpdy = rpy + d * pv.y
39954
39955  equation of line b:
39956           pvns ... normal slope to pv
39957
39958   y - rpdy = pvns * (x - rpdx)
39959
39960   x = p.x
39961
39962   y = rpdy +  pvns * (p.x - rpdx)
39963
39964
39965
39966generic case:
39967-------------
39968
39969
39970                              .'(fv)
39971                            .'
39972                          .* pm
39973                        .' !
39974                      .'    .
39975                    .'      !
39976                  .'         . b
39977                .'           !
39978               *              .
39979              p               !
39980                         90°   .    ... (pv)
39981                           ...-*-'''
39982                  ...---'''    rpd
39983         ...---'''   d
39984   *--'''
39985  rp
39986
39987    rpdx = rpx + d * pv.x
39988    rpdy = rpy + d * pv.y
39989
39990 equation of line b:
39991    pvns... normal slope to pv
39992
39993    y - rpdy = pvns * (x - rpdx)
39994
39995 equation of freedom vector line:
39996    fvs ... slope of freedom vector (=fy/fx)
39997
39998    y - py = fvs * (x - px)
39999
40000
40001  on pm both equations are true for same x/y
40002
40003    y - rpdy = pvns * (x - rpdx)
40004
40005    y - py = fvs * (x - px)
40006
40007  form to y and set equal:
40008
40009    pvns * (x - rpdx) + rpdy = fvs * (x - px) + py
40010
40011  expand:
40012
40013    pvns * x - pvns * rpdx + rpdy = fvs * x - fvs * px + py
40014
40015  switch:
40016
40017    fvs * x - fvs * px + py = pvns * x - pvns * rpdx + rpdy
40018
40019  solve for x:
40020
40021    fvs * x - pvns * x = fvs * px - pvns * rpdx - py + rpdy
40022
40023
40024
40025          fvs * px - pvns * rpdx + rpdy - py
40026    x =  -----------------------------------
40027                 fvs - pvns
40028
40029  and:
40030
40031    y = fvs * (x - px) + py
40032
40033
40034
40035INTERPOLATE:
40036============
40037
40038Examples of point interpolation.
40039
40040The weight of the movement of the reference point gets bigger
40041the further the other reference point is away, thus the safest
40042option (that is avoiding 0/0 divisions) is to weight the
40043original distance of the other point by the sum of both distances.
40044
40045If the sum of both distances is 0, then move the point by the
40046arithmetic average of the movement of both reference points.
40047
40048
40049
40050
40051           (+6)
40052    rp1o *---->*rp1
40053         .     .                          (+12)
40054         .     .                  rp2o *---------->* rp2
40055         .     .                       .           .
40056         .     .                       .           .
40057         .    10          20           .           .
40058         |.........|...................|           .
40059               .   .                               .
40060               .   . (+8)                          .
40061                po *------>*p                      .
40062               .           .                       .
40063               .    12     .          24           .
40064               |...........|.......................|
40065                                  36
40066
40067
40068-------
40069
40070
40071
40072           (+10)
40073    rp1o *-------->*rp1
40074         .         .                      (-10)
40075         .         .              rp2 *<---------* rpo2
40076         .         .                   .         .
40077         .         .                   .         .
40078         .    10   .          30       .         .
40079         |.........|.............................|
40080                   .                   .
40081                   . (+5)              .
40082                po *--->* p            .
40083                   .    .              .
40084                   .    .   20         .
40085                   |....|..............|
40086                     5        15
40087
40088
40089-------
40090
40091
40092           (+10)
40093    rp1o *-------->*rp1
40094         .         .
40095         .         .
40096    rp2o *-------->*rp2
40097
40098
40099                               (+10)
40100                          po *-------->* p
40101
40102-------
40103
40104
40105           (+10)
40106    rp1o *-------->*rp1
40107         .         .
40108         .         .(+30)
40109    rp2o *---------------------------->*rp2
40110
40111
40112                                        (+25)
40113                          po *----------------------->* p
40114
40115
40116
40117vim: set ts=4 sw=4 expandtab:
40118*****/
40119
40120// The Font object
40121
40122/**
40123 * @typedef FontOptions
40124 * @type Object
40125 * @property {Boolean} empty - whether to create a new empty font
40126 * @property {string} familyName
40127 * @property {string} styleName
40128 * @property {string=} fullName
40129 * @property {string=} postScriptName
40130 * @property {string=} designer
40131 * @property {string=} designerURL
40132 * @property {string=} manufacturer
40133 * @property {string=} manufacturerURL
40134 * @property {string=} license
40135 * @property {string=} licenseURL
40136 * @property {string=} version
40137 * @property {string=} description
40138 * @property {string=} copyright
40139 * @property {string=} trademark
40140 * @property {Number} unitsPerEm
40141 * @property {Number} ascender
40142 * @property {Number} descender
40143 * @property {Number} createdTimestamp
40144 * @property {string=} weightClass
40145 * @property {string=} widthClass
40146 * @property {string=} fsSelection
40147 */
40148
40149/**
40150 * A Font represents a loaded OpenType font file.
40151 * It contains a set of glyphs and methods to draw text on a drawing context,
40152 * or to get a path representing the text.
40153 * @exports opentype.Font
40154 * @class
40155 * @param {FontOptions}
40156 * @constructor
40157 */
40158function Font(options) {
40159    options = options || {};
40160
40161    if (!options.empty) {
40162        // Check that we've provided the minimum set of names.
40163        checkArgument(options.familyName, 'When creating a new Font object, familyName is required.');
40164        checkArgument(options.styleName, 'When creating a new Font object, styleName is required.');
40165        checkArgument(options.unitsPerEm, 'When creating a new Font object, unitsPerEm is required.');
40166        checkArgument(options.ascender, 'When creating a new Font object, ascender is required.');
40167        checkArgument(options.descender, 'When creating a new Font object, descender is required.');
40168        checkArgument(options.descender < 0, 'Descender should be negative (e.g. -512).');
40169
40170        // OS X will complain if the names are empty, so we put a single space everywhere by default.
40171        this.names = {
40172            fontFamily: {en: options.familyName || ' '},
40173            fontSubfamily: {en: options.styleName || ' '},
40174            fullName: {en: options.fullName || options.familyName + ' ' + options.styleName},
40175            postScriptName: {en: options.postScriptName || options.familyName + options.styleName},
40176            designer: {en: options.designer || ' '},
40177            designerURL: {en: options.designerURL || ' '},
40178            manufacturer: {en: options.manufacturer || ' '},
40179            manufacturerURL: {en: options.manufacturerURL || ' '},
40180            license: {en: options.license || ' '},
40181            licenseURL: {en: options.licenseURL || ' '},
40182            version: {en: options.version || 'Version 0.1'},
40183            description: {en: options.description || ' '},
40184            copyright: {en: options.copyright || ' '},
40185            trademark: {en: options.trademark || ' '}
40186        };
40187        this.unitsPerEm = options.unitsPerEm || 1000;
40188        this.ascender = options.ascender;
40189        this.descender = options.descender;
40190        this.createdTimestamp = options.createdTimestamp;
40191        this.tables = { os2: {
40192            usWeightClass: options.weightClass || this.usWeightClasses.MEDIUM,
40193            usWidthClass: options.widthClass || this.usWidthClasses.MEDIUM,
40194            fsSelection: options.fsSelection || this.fsSelectionValues.REGULAR
40195        } };
40196    }
40197
40198    this.supported = true; // Deprecated: parseBuffer will throw an error if font is not supported.
40199    this.glyphs = new glyphset.GlyphSet(this, options.glyphs || []);
40200    this.encoding = new DefaultEncoding(this);
40201    this.substitution = new Substitution(this);
40202    this.tables = this.tables || {};
40203
40204    Object.defineProperty(this, 'hinting', {
40205        get: function() {
40206            if (this._hinting) { return this._hinting; }
40207            if (this.outlinesFormat === 'truetype') {
40208                return (this._hinting = new Hinting(this));
40209            }
40210        }
40211    });
40212}
40213
40214/**
40215 * Check if the font has a glyph for the given character.
40216 * @param  {string}
40217 * @return {Boolean}
40218 */
40219Font.prototype.hasChar = function(c) {
40220    return this.encoding.charToGlyphIndex(c) !== null;
40221};
40222
40223/**
40224 * Convert the given character to a single glyph index.
40225 * Note that this function assumes that there is a one-to-one mapping between
40226 * the given character and a glyph; for complex scripts this might not be the case.
40227 * @param  {string}
40228 * @return {Number}
40229 */
40230Font.prototype.charToGlyphIndex = function(s) {
40231    return this.encoding.charToGlyphIndex(s);
40232};
40233
40234/**
40235 * Convert the given character to a single Glyph object.
40236 * Note that this function assumes that there is a one-to-one mapping between
40237 * the given character and a glyph; for complex scripts this might not be the case.
40238 * @param  {string}
40239 * @return {opentype.Glyph}
40240 */
40241Font.prototype.charToGlyph = function(c) {
40242    var glyphIndex = this.charToGlyphIndex(c);
40243    var glyph = this.glyphs.get(glyphIndex);
40244    if (!glyph) {
40245        // .notdef
40246        glyph = this.glyphs.get(0);
40247    }
40248
40249    return glyph;
40250};
40251
40252/**
40253 * Convert the given text to a list of Glyph objects.
40254 * Note that there is no strict one-to-one mapping between characters and
40255 * glyphs, so the list of returned glyphs can be larger or smaller than the
40256 * length of the given string.
40257 * @param  {string}
40258 * @param  {GlyphRenderOptions} [options]
40259 * @return {opentype.Glyph[]}
40260 */
40261Font.prototype.stringToGlyphs = function(s, options) {
40262    var this$1 = this;
40263
40264    options = options || this.defaultRenderOptions;
40265    // Get glyph indexes
40266    var indexes = [];
40267    for (var i = 0; i < s.length; i += 1) {
40268        var c = s[i];
40269        indexes.push(this$1.charToGlyphIndex(c));
40270    }
40271    var length = indexes.length;
40272
40273    // Apply substitutions on glyph indexes
40274    if (options.features) {
40275        var script = options.script || this.substitution.getDefaultScriptName();
40276        var manyToOne = [];
40277        if (options.features.liga) { manyToOne = manyToOne.concat(this.substitution.getFeature('liga', script, options.language)); }
40278        if (options.features.rlig) { manyToOne = manyToOne.concat(this.substitution.getFeature('rlig', script, options.language)); }
40279        for (var i$1 = 0; i$1 < length; i$1 += 1) {
40280            for (var j = 0; j < manyToOne.length; j++) {
40281                var ligature = manyToOne[j];
40282                var components = ligature.sub;
40283                var compCount = components.length;
40284                var k = 0;
40285                while (k < compCount && components[k] === indexes[i$1 + k]) { k++; }
40286                if (k === compCount) {
40287                    indexes.splice(i$1, compCount, ligature.by);
40288                    length = length - compCount + 1;
40289                }
40290            }
40291        }
40292    }
40293
40294    // convert glyph indexes to glyph objects
40295    var glyphs = new Array(length);
40296    var notdef = this.glyphs.get(0);
40297    for (var i$2 = 0; i$2 < length; i$2 += 1) {
40298        glyphs[i$2] = this$1.glyphs.get(indexes[i$2]) || notdef;
40299    }
40300    return glyphs;
40301};
40302
40303/**
40304 * @param  {string}
40305 * @return {Number}
40306 */
40307Font.prototype.nameToGlyphIndex = function(name) {
40308    return this.glyphNames.nameToGlyphIndex(name);
40309};
40310
40311/**
40312 * @param  {string}
40313 * @return {opentype.Glyph}
40314 */
40315Font.prototype.nameToGlyph = function(name) {
40316    var glyphIndex = this.nameToGlyphIndex(name);
40317    var glyph = this.glyphs.get(glyphIndex);
40318    if (!glyph) {
40319        // .notdef
40320        glyph = this.glyphs.get(0);
40321    }
40322
40323    return glyph;
40324};
40325
40326/**
40327 * @param  {Number}
40328 * @return {String}
40329 */
40330Font.prototype.glyphIndexToName = function(gid) {
40331    if (!this.glyphNames.glyphIndexToName) {
40332        return '';
40333    }
40334
40335    return this.glyphNames.glyphIndexToName(gid);
40336};
40337
40338/**
40339 * Retrieve the value of the kerning pair between the left glyph (or its index)
40340 * and the right glyph (or its index). If no kerning pair is found, return 0.
40341 * The kerning value gets added to the advance width when calculating the spacing
40342 * between glyphs.
40343 * @param  {opentype.Glyph} leftGlyph
40344 * @param  {opentype.Glyph} rightGlyph
40345 * @return {Number}
40346 */
40347Font.prototype.getKerningValue = function(leftGlyph, rightGlyph) {
40348    leftGlyph = leftGlyph.index || leftGlyph;
40349    rightGlyph = rightGlyph.index || rightGlyph;
40350    var gposKerning = this.getGposKerningValue;
40351    return gposKerning ? gposKerning(leftGlyph, rightGlyph) :
40352        (this.kerningPairs[leftGlyph + ',' + rightGlyph] || 0);
40353};
40354
40355/**
40356 * @typedef GlyphRenderOptions
40357 * @type Object
40358 * @property {string} [script] - script used to determine which features to apply. By default, 'DFLT' or 'latn' is used.
40359 *                               See https://www.microsoft.com/typography/otspec/scripttags.htm
40360 * @property {string} [language='dflt'] - language system used to determine which features to apply.
40361 *                                        See https://www.microsoft.com/typography/developers/opentype/languagetags.aspx
40362 * @property {boolean} [kerning=true] - whether to include kerning values
40363 * @property {object} [features] - OpenType Layout feature tags. Used to enable or disable the features of the given script/language system.
40364 *                                 See https://www.microsoft.com/typography/otspec/featuretags.htm
40365 */
40366Font.prototype.defaultRenderOptions = {
40367    kerning: true,
40368    features: {
40369        liga: true,
40370        rlig: true
40371    }
40372};
40373
40374/**
40375 * Helper function that invokes the given callback for each glyph in the given text.
40376 * The callback gets `(glyph, x, y, fontSize, options)`.* @param  {string} text
40377 * @param {string} text - The text to apply.
40378 * @param  {number} [x=0] - Horizontal position of the beginning of the text.
40379 * @param  {number} [y=0] - Vertical position of the *baseline* of the text.
40380 * @param  {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`.
40381 * @param  {GlyphRenderOptions=} options
40382 * @param  {Function} callback
40383 */
40384Font.prototype.forEachGlyph = function(text, x, y, fontSize, options, callback) {
40385    var this$1 = this;
40386
40387    x = x !== undefined ? x : 0;
40388    y = y !== undefined ? y : 0;
40389    fontSize = fontSize !== undefined ? fontSize : 72;
40390    options = options || this.defaultRenderOptions;
40391    var fontScale = 1 / this.unitsPerEm * fontSize;
40392    var glyphs = this.stringToGlyphs(text, options);
40393    for (var i = 0; i < glyphs.length; i += 1) {
40394        var glyph = glyphs[i];
40395        callback.call(this$1, glyph, x, y, fontSize, options);
40396        if (glyph.advanceWidth) {
40397            x += glyph.advanceWidth * fontScale;
40398        }
40399
40400        if (options.kerning && i < glyphs.length - 1) {
40401            var kerningValue = this$1.getKerningValue(glyph, glyphs[i + 1]);
40402            x += kerningValue * fontScale;
40403        }
40404
40405        if (options.letterSpacing) {
40406            x += options.letterSpacing * fontSize;
40407        } else if (options.tracking) {
40408            x += (options.tracking / 1000) * fontSize;
40409        }
40410    }
40411    return x;
40412};
40413
40414/**
40415 * Create a Path object that represents the given text.
40416 * @param  {string} text - The text to create.
40417 * @param  {number} [x=0] - Horizontal position of the beginning of the text.
40418 * @param  {number} [y=0] - Vertical position of the *baseline* of the text.
40419 * @param  {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`.
40420 * @param  {GlyphRenderOptions=} options
40421 * @return {opentype.Path}
40422 */
40423Font.prototype.getPath = function(text, x, y, fontSize, options) {
40424    var fullPath = new Path();
40425    this.forEachGlyph(text, x, y, fontSize, options, function(glyph, gX, gY, gFontSize) {
40426        var glyphPath = glyph.getPath(gX, gY, gFontSize, options, this);
40427        fullPath.extend(glyphPath);
40428    });
40429    return fullPath;
40430};
40431
40432/**
40433 * Create an array of Path objects that represent the glyphs of a given text.
40434 * @param  {string} text - The text to create.
40435 * @param  {number} [x=0] - Horizontal position of the beginning of the text.
40436 * @param  {number} [y=0] - Vertical position of the *baseline* of the text.
40437 * @param  {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`.
40438 * @param  {GlyphRenderOptions=} options
40439 * @return {opentype.Path[]}
40440 */
40441Font.prototype.getPaths = function(text, x, y, fontSize, options) {
40442    var glyphPaths = [];
40443    this.forEachGlyph(text, x, y, fontSize, options, function(glyph, gX, gY, gFontSize) {
40444        var glyphPath = glyph.getPath(gX, gY, gFontSize, options, this);
40445        glyphPaths.push(glyphPath);
40446    });
40447
40448    return glyphPaths;
40449};
40450
40451/**
40452 * Returns the advance width of a text.
40453 *
40454 * This is something different than Path.getBoundingBox() as for example a
40455 * suffixed whitespace increases the advanceWidth but not the bounding box
40456 * or an overhanging letter like a calligraphic 'f' might have a quite larger
40457 * bounding box than its advance width.
40458 *
40459 * This corresponds to canvas2dContext.measureText(text).width
40460 *
40461 * @param  {string} text - The text to create.
40462 * @param  {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`.
40463 * @param  {GlyphRenderOptions=} options
40464 * @return advance width
40465 */
40466Font.prototype.getAdvanceWidth = function(text, fontSize, options) {
40467    return this.forEachGlyph(text, 0, 0, fontSize, options, function() {});
40468};
40469
40470/**
40471 * Draw the text on the given drawing context.
40472 * @param  {CanvasRenderingContext2D} ctx - A 2D drawing context, like Canvas.
40473 * @param  {string} text - The text to create.
40474 * @param  {number} [x=0] - Horizontal position of the beginning of the text.
40475 * @param  {number} [y=0] - Vertical position of the *baseline* of the text.
40476 * @param  {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`.
40477 * @param  {GlyphRenderOptions=} options
40478 */
40479Font.prototype.draw = function(ctx, text, x, y, fontSize, options) {
40480    this.getPath(text, x, y, fontSize, options).draw(ctx);
40481};
40482
40483/**
40484 * Draw the points of all glyphs in the text.
40485 * On-curve points will be drawn in blue, off-curve points will be drawn in red.
40486 * @param {CanvasRenderingContext2D} ctx - A 2D drawing context, like Canvas.
40487 * @param {string} text - The text to create.
40488 * @param {number} [x=0] - Horizontal position of the beginning of the text.
40489 * @param {number} [y=0] - Vertical position of the *baseline* of the text.
40490 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`.
40491 * @param {GlyphRenderOptions=} options
40492 */
40493Font.prototype.drawPoints = function(ctx, text, x, y, fontSize, options) {
40494    this.forEachGlyph(text, x, y, fontSize, options, function(glyph, gX, gY, gFontSize) {
40495        glyph.drawPoints(ctx, gX, gY, gFontSize);
40496    });
40497};
40498
40499/**
40500 * Draw lines indicating important font measurements for all glyphs in the text.
40501 * Black lines indicate the origin of the coordinate system (point 0,0).
40502 * Blue lines indicate the glyph bounding box.
40503 * Green line indicates the advance width of the glyph.
40504 * @param {CanvasRenderingContext2D} ctx - A 2D drawing context, like Canvas.
40505 * @param {string} text - The text to create.
40506 * @param {number} [x=0] - Horizontal position of the beginning of the text.
40507 * @param {number} [y=0] - Vertical position of the *baseline* of the text.
40508 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`.
40509 * @param {GlyphRenderOptions=} options
40510 */
40511Font.prototype.drawMetrics = function(ctx, text, x, y, fontSize, options) {
40512    this.forEachGlyph(text, x, y, fontSize, options, function(glyph, gX, gY, gFontSize) {
40513        glyph.drawMetrics(ctx, gX, gY, gFontSize);
40514    });
40515};
40516
40517/**
40518 * @param  {string}
40519 * @return {string}
40520 */
40521Font.prototype.getEnglishName = function(name) {
40522    var translations = this.names[name];
40523    if (translations) {
40524        return translations.en;
40525    }
40526};
40527
40528/**
40529 * Validate
40530 */
40531Font.prototype.validate = function() {
40532    var warnings = [];
40533    var _this = this;
40534
40535    function assert(predicate, message) {
40536        if (!predicate) {
40537            warnings.push(message);
40538        }
40539    }
40540
40541    function assertNamePresent(name) {
40542        var englishName = _this.getEnglishName(name);
40543        assert(englishName && englishName.trim().length > 0,
40544               'No English ' + name + ' specified.');
40545    }
40546
40547    // Identification information
40548    assertNamePresent('fontFamily');
40549    assertNamePresent('weightName');
40550    assertNamePresent('manufacturer');
40551    assertNamePresent('copyright');
40552    assertNamePresent('version');
40553
40554    // Dimension information
40555    assert(this.unitsPerEm > 0, 'No unitsPerEm specified.');
40556};
40557
40558/**
40559 * Convert the font object to a SFNT data structure.
40560 * This structure contains all the necessary tables and metadata to create a binary OTF file.
40561 * @return {opentype.Table}
40562 */
40563Font.prototype.toTables = function() {
40564    return sfnt.fontToTable(this);
40565};
40566/**
40567 * @deprecated Font.toBuffer is deprecated. Use Font.toArrayBuffer instead.
40568 */
40569Font.prototype.toBuffer = function() {
40570    console.warn('Font.toBuffer is deprecated. Use Font.toArrayBuffer instead.');
40571    return this.toArrayBuffer();
40572};
40573/**
40574 * Converts a `opentype.Font` into an `ArrayBuffer`
40575 * @return {ArrayBuffer}
40576 */
40577Font.prototype.toArrayBuffer = function() {
40578    var sfntTable = this.toTables();
40579    var bytes = sfntTable.encode();
40580    var buffer = new ArrayBuffer(bytes.length);
40581    var intArray = new Uint8Array(buffer);
40582    for (var i = 0; i < bytes.length; i++) {
40583        intArray[i] = bytes[i];
40584    }
40585
40586    return buffer;
40587};
40588
40589/**
40590 * Initiate a download of the OpenType font.
40591 */
40592Font.prototype.download = function(fileName) {
40593    var familyName = this.getEnglishName('fontFamily');
40594    var styleName = this.getEnglishName('fontSubfamily');
40595    fileName = fileName || familyName.replace(/\s/g, '') + '-' + styleName + '.otf';
40596    var arrayBuffer = this.toArrayBuffer();
40597
40598    if (isBrowser()) {
40599        window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
40600        window.requestFileSystem(window.TEMPORARY, arrayBuffer.byteLength, function(fs) {
40601            fs.root.getFile(fileName, {create: true}, function(fileEntry) {
40602                fileEntry.createWriter(function(writer) {
40603                    var dataView = new DataView(arrayBuffer);
40604                    var blob = new Blob([dataView], {type: 'font/opentype'});
40605                    writer.write(blob);
40606
40607                    writer.addEventListener('writeend', function() {
40608                        // Navigating to the file will download it.
40609                        location.href = fileEntry.toURL();
40610                    }, false);
40611                });
40612            });
40613        },
40614        function(err) {
40615            throw new Error(err.name + ': ' + err.message);
40616        });
40617    } else {
40618        var fs = _dereq_('fs');
40619        var buffer = arrayBufferToNodeBuffer(arrayBuffer);
40620        fs.writeFileSync(fileName, buffer);
40621    }
40622};
40623/**
40624 * @private
40625 */
40626Font.prototype.fsSelectionValues = {
40627    ITALIC:              0x001, //1
40628    UNDERSCORE:          0x002, //2
40629    NEGATIVE:            0x004, //4
40630    OUTLINED:            0x008, //8
40631    STRIKEOUT:           0x010, //16
40632    BOLD:                0x020, //32
40633    REGULAR:             0x040, //64
40634    USER_TYPO_METRICS:   0x080, //128
40635    WWS:                 0x100, //256
40636    OBLIQUE:             0x200  //512
40637};
40638
40639/**
40640 * @private
40641 */
40642Font.prototype.usWidthClasses = {
40643    ULTRA_CONDENSED: 1,
40644    EXTRA_CONDENSED: 2,
40645    CONDENSED: 3,
40646    SEMI_CONDENSED: 4,
40647    MEDIUM: 5,
40648    SEMI_EXPANDED: 6,
40649    EXPANDED: 7,
40650    EXTRA_EXPANDED: 8,
40651    ULTRA_EXPANDED: 9
40652};
40653
40654/**
40655 * @private
40656 */
40657Font.prototype.usWeightClasses = {
40658    THIN: 100,
40659    EXTRA_LIGHT: 200,
40660    LIGHT: 300,
40661    NORMAL: 400,
40662    MEDIUM: 500,
40663    SEMI_BOLD: 600,
40664    BOLD: 700,
40665    EXTRA_BOLD: 800,
40666    BLACK:    900
40667};
40668
40669// The `fvar` table stores font variation axes and instances.
40670// https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6fvar.html
40671
40672function addName(name, names) {
40673    var nameString = JSON.stringify(name);
40674    var nameID = 256;
40675    for (var nameKey in names) {
40676        var n = parseInt(nameKey);
40677        if (!n || n < 256) {
40678            continue;
40679        }
40680
40681        if (JSON.stringify(names[nameKey]) === nameString) {
40682            return n;
40683        }
40684
40685        if (nameID <= n) {
40686            nameID = n + 1;
40687        }
40688    }
40689
40690    names[nameID] = name;
40691    return nameID;
40692}
40693
40694function makeFvarAxis(n, axis, names) {
40695    var nameID = addName(axis.name, names);
40696    return [
40697        {name: 'tag_' + n, type: 'TAG', value: axis.tag},
40698        {name: 'minValue_' + n, type: 'FIXED', value: axis.minValue << 16},
40699        {name: 'defaultValue_' + n, type: 'FIXED', value: axis.defaultValue << 16},
40700        {name: 'maxValue_' + n, type: 'FIXED', value: axis.maxValue << 16},
40701        {name: 'flags_' + n, type: 'USHORT', value: 0},
40702        {name: 'nameID_' + n, type: 'USHORT', value: nameID}
40703    ];
40704}
40705
40706function parseFvarAxis(data, start, names) {
40707    var axis = {};
40708    var p = new parse.Parser(data, start);
40709    axis.tag = p.parseTag();
40710    axis.minValue = p.parseFixed();
40711    axis.defaultValue = p.parseFixed();
40712    axis.maxValue = p.parseFixed();
40713    p.skip('uShort', 1);  // reserved for flags; no values defined
40714    axis.name = names[p.parseUShort()] || {};
40715    return axis;
40716}
40717
40718function makeFvarInstance(n, inst, axes, names) {
40719    var nameID = addName(inst.name, names);
40720    var fields = [
40721        {name: 'nameID_' + n, type: 'USHORT', value: nameID},
40722        {name: 'flags_' + n, type: 'USHORT', value: 0}
40723    ];
40724
40725    for (var i = 0; i < axes.length; ++i) {
40726        var axisTag = axes[i].tag;
40727        fields.push({
40728            name: 'axis_' + n + ' ' + axisTag,
40729            type: 'FIXED',
40730            value: inst.coordinates[axisTag] << 16
40731        });
40732    }
40733
40734    return fields;
40735}
40736
40737function parseFvarInstance(data, start, axes, names) {
40738    var inst = {};
40739    var p = new parse.Parser(data, start);
40740    inst.name = names[p.parseUShort()] || {};
40741    p.skip('uShort', 1);  // reserved for flags; no values defined
40742
40743    inst.coordinates = {};
40744    for (var i = 0; i < axes.length; ++i) {
40745        inst.coordinates[axes[i].tag] = p.parseFixed();
40746    }
40747
40748    return inst;
40749}
40750
40751function makeFvarTable(fvar, names) {
40752    var result = new table.Table('fvar', [
40753        {name: 'version', type: 'ULONG', value: 0x10000},
40754        {name: 'offsetToData', type: 'USHORT', value: 0},
40755        {name: 'countSizePairs', type: 'USHORT', value: 2},
40756        {name: 'axisCount', type: 'USHORT', value: fvar.axes.length},
40757        {name: 'axisSize', type: 'USHORT', value: 20},
40758        {name: 'instanceCount', type: 'USHORT', value: fvar.instances.length},
40759        {name: 'instanceSize', type: 'USHORT', value: 4 + fvar.axes.length * 4}
40760    ]);
40761    result.offsetToData = result.sizeOf();
40762
40763    for (var i = 0; i < fvar.axes.length; i++) {
40764        result.fields = result.fields.concat(makeFvarAxis(i, fvar.axes[i], names));
40765    }
40766
40767    for (var j = 0; j < fvar.instances.length; j++) {
40768        result.fields = result.fields.concat(makeFvarInstance(j, fvar.instances[j], fvar.axes, names));
40769    }
40770
40771    return result;
40772}
40773
40774function parseFvarTable(data, start, names) {
40775    var p = new parse.Parser(data, start);
40776    var tableVersion = p.parseULong();
40777    check.argument(tableVersion === 0x00010000, 'Unsupported fvar table version.');
40778    var offsetToData = p.parseOffset16();
40779    // Skip countSizePairs.
40780    p.skip('uShort', 1);
40781    var axisCount = p.parseUShort();
40782    var axisSize = p.parseUShort();
40783    var instanceCount = p.parseUShort();
40784    var instanceSize = p.parseUShort();
40785
40786    var axes = [];
40787    for (var i = 0; i < axisCount; i++) {
40788        axes.push(parseFvarAxis(data, start + offsetToData + i * axisSize, names));
40789    }
40790
40791    var instances = [];
40792    var instanceStart = start + offsetToData + axisCount * axisSize;
40793    for (var j = 0; j < instanceCount; j++) {
40794        instances.push(parseFvarInstance(data, instanceStart + j * instanceSize, axes, names));
40795    }
40796
40797    return {axes: axes, instances: instances};
40798}
40799
40800var fvar = { make: makeFvarTable, parse: parseFvarTable };
40801
40802// The `GPOS` table contains kerning pairs, among other things.
40803// https://www.microsoft.com/typography/OTSPEC/gpos.htm
40804
40805// Parse ScriptList and FeatureList tables of GPOS, GSUB, GDEF, BASE, JSTF tables.
40806// These lists are unused by now, this function is just the basis for a real parsing.
40807function parseTaggedListTable(data, start) {
40808    var p = new parse.Parser(data, start);
40809    var n = p.parseUShort();
40810    var list = [];
40811    for (var i = 0; i < n; i++) {
40812        list[p.parseTag()] = { offset: p.parseUShort() };
40813    }
40814
40815    return list;
40816}
40817
40818// Parse a coverage table in a GSUB, GPOS or GDEF table.
40819// Format 1 is a simple list of glyph ids,
40820// Format 2 is a list of ranges. It is expanded in a list of glyphs, maybe not the best idea.
40821function parseCoverageTable(data, start) {
40822    var p = new parse.Parser(data, start);
40823    var format = p.parseUShort();
40824    var count = p.parseUShort();
40825    if (format === 1) {
40826        return p.parseUShortList(count);
40827    } else if (format === 2) {
40828        var coverage = [];
40829        for (; count--;) {
40830            var begin = p.parseUShort();
40831            var end = p.parseUShort();
40832            var index = p.parseUShort();
40833            for (var i = begin; i <= end; i++) {
40834                coverage[index++] = i;
40835            }
40836        }
40837
40838        return coverage;
40839    }
40840}
40841
40842// Parse a Class Definition Table in a GSUB, GPOS or GDEF table.
40843// Returns a function that gets a class value from a glyph ID.
40844function parseClassDefTable(data, start) {
40845    var p = new parse.Parser(data, start);
40846    var format = p.parseUShort();
40847    if (format === 1) {
40848        // Format 1 specifies a range of consecutive glyph indices, one class per glyph ID.
40849        var startGlyph = p.parseUShort();
40850        var glyphCount = p.parseUShort();
40851        var classes = p.parseUShortList(glyphCount);
40852        return function(glyphID) {
40853            return classes[glyphID - startGlyph] || 0;
40854        };
40855    } else if (format === 2) {
40856        // Format 2 defines multiple groups of glyph indices that belong to the same class.
40857        var rangeCount = p.parseUShort();
40858        var startGlyphs = [];
40859        var endGlyphs = [];
40860        var classValues = [];
40861        for (var i = 0; i < rangeCount; i++) {
40862            startGlyphs[i] = p.parseUShort();
40863            endGlyphs[i] = p.parseUShort();
40864            classValues[i] = p.parseUShort();
40865        }
40866
40867        return function(glyphID) {
40868            var l = 0;
40869            var r = startGlyphs.length - 1;
40870            while (l < r) {
40871                var c = (l + r + 1) >> 1;
40872                if (glyphID < startGlyphs[c]) {
40873                    r = c - 1;
40874                } else {
40875                    l = c;
40876                }
40877            }
40878
40879            if (startGlyphs[l] <= glyphID && glyphID <= endGlyphs[l]) {
40880                return classValues[l] || 0;
40881            }
40882
40883            return 0;
40884        };
40885    }
40886}
40887
40888// Parse a pair adjustment positioning subtable, format 1 or format 2
40889// The subtable is returned in the form of a lookup function.
40890function parsePairPosSubTable(data, start) {
40891    var p = new parse.Parser(data, start);
40892    // This part is common to format 1 and format 2 subtables
40893    var format = p.parseUShort();
40894    var coverageOffset = p.parseUShort();
40895    var coverage = parseCoverageTable(data, start + coverageOffset);
40896    // valueFormat 4: XAdvance only, 1: XPlacement only, 0: no ValueRecord for second glyph
40897    // Only valueFormat1=4 and valueFormat2=0 is supported.
40898    var valueFormat1 = p.parseUShort();
40899    var valueFormat2 = p.parseUShort();
40900    var value1;
40901    var value2;
40902    if (valueFormat1 !== 4 || valueFormat2 !== 0) { return; }
40903    var sharedPairSets = {};
40904    if (format === 1) {
40905        // Pair Positioning Adjustment: Format 1
40906        var pairSetCount = p.parseUShort();
40907        var pairSet = [];
40908        // Array of offsets to PairSet tables-from beginning of PairPos subtable-ordered by Coverage Index
40909        var pairSetOffsets = p.parseOffset16List(pairSetCount);
40910        for (var firstGlyph = 0; firstGlyph < pairSetCount; firstGlyph++) {
40911            var pairSetOffset = pairSetOffsets[firstGlyph];
40912            var sharedPairSet = sharedPairSets[pairSetOffset];
40913            if (!sharedPairSet) {
40914                // Parse a pairset table in a pair adjustment subtable format 1
40915                sharedPairSet = {};
40916                p.relativeOffset = pairSetOffset;
40917                var pairValueCount = p.parseUShort();
40918                for (; pairValueCount--;) {
40919                    var secondGlyph = p.parseUShort();
40920                    if (valueFormat1) { value1 = p.parseShort(); }
40921                    if (valueFormat2) { value2 = p.parseShort(); }
40922                    // We only support valueFormat1 = 4 and valueFormat2 = 0,
40923                    // so value1 is the XAdvance and value2 is empty.
40924                    sharedPairSet[secondGlyph] = value1;
40925                }
40926            }
40927
40928            pairSet[coverage[firstGlyph]] = sharedPairSet;
40929        }
40930
40931        return function(leftGlyph, rightGlyph) {
40932            var pairs = pairSet[leftGlyph];
40933            if (pairs) { return pairs[rightGlyph]; }
40934        };
40935    } else if (format === 2) {
40936        // Pair Positioning Adjustment: Format 2
40937        var classDef1Offset = p.parseUShort();
40938        var classDef2Offset = p.parseUShort();
40939        var class1Count = p.parseUShort();
40940        var class2Count = p.parseUShort();
40941        var getClass1 = parseClassDefTable(data, start + classDef1Offset);
40942        var getClass2 = parseClassDefTable(data, start + classDef2Offset);
40943
40944        // Parse kerning values by class pair.
40945        var kerningMatrix = [];
40946        for (var i = 0; i < class1Count; i++) {
40947            var kerningRow = kerningMatrix[i] = [];
40948            for (var j = 0; j < class2Count; j++) {
40949                if (valueFormat1) { value1 = p.parseShort(); }
40950                if (valueFormat2) { value2 = p.parseShort(); }
40951                // We only support valueFormat1 = 4 and valueFormat2 = 0,
40952                // so value1 is the XAdvance and value2 is empty.
40953                kerningRow[j] = value1;
40954            }
40955        }
40956
40957        // Convert coverage list to a hash
40958        var covered = {};
40959        for (var i$1 = 0; i$1 < coverage.length; i$1++) {
40960            covered[coverage[i$1]] = 1;
40961        }
40962
40963        // Get the kerning value for a specific glyph pair.
40964        return function(leftGlyph, rightGlyph) {
40965            if (!covered[leftGlyph]) { return; }
40966            var class1 = getClass1(leftGlyph);
40967            var class2 = getClass2(rightGlyph);
40968            var kerningRow = kerningMatrix[class1];
40969
40970            if (kerningRow) {
40971                return kerningRow[class2];
40972            }
40973        };
40974    }
40975}
40976
40977// Parse a LookupTable (present in of GPOS, GSUB, GDEF, BASE, JSTF tables).
40978function parseLookupTable(data, start) {
40979    var p = new parse.Parser(data, start);
40980    var lookupType = p.parseUShort();
40981    var lookupFlag = p.parseUShort();
40982    var useMarkFilteringSet = lookupFlag & 0x10;
40983    var subTableCount = p.parseUShort();
40984    var subTableOffsets = p.parseOffset16List(subTableCount);
40985    var table = {
40986        lookupType: lookupType,
40987        lookupFlag: lookupFlag,
40988        markFilteringSet: useMarkFilteringSet ? p.parseUShort() : -1
40989    };
40990    // LookupType 2, Pair adjustment
40991    if (lookupType === 2) {
40992        var subtables = [];
40993        for (var i = 0; i < subTableCount; i++) {
40994            var pairPosSubTable = parsePairPosSubTable(data, start + subTableOffsets[i]);
40995            if (pairPosSubTable) { subtables.push(pairPosSubTable); }
40996        }
40997        // Return a function which finds the kerning values in the subtables.
40998        table.getKerningValue = function(leftGlyph, rightGlyph) {
40999            for (var i = subtables.length; i--;) {
41000                var value = subtables[i](leftGlyph, rightGlyph);
41001                if (value !== undefined) { return value; }
41002            }
41003
41004            return 0;
41005        };
41006    }
41007
41008    return table;
41009}
41010
41011// Parse the `GPOS` table which contains, among other things, kerning pairs.
41012// https://www.microsoft.com/typography/OTSPEC/gpos.htm
41013function parseGposTable(data, start, font) {
41014    var p = new parse.Parser(data, start);
41015    var tableVersion = p.parseFixed();
41016    check.argument(tableVersion === 1, 'Unsupported GPOS table version.');
41017
41018    // ScriptList and FeatureList - ignored for now
41019    parseTaggedListTable(data, start + p.parseUShort());
41020    // 'kern' is the feature we are looking for.
41021    parseTaggedListTable(data, start + p.parseUShort());
41022
41023    // LookupList
41024    var lookupListOffset = p.parseUShort();
41025    p.relativeOffset = lookupListOffset;
41026    var lookupCount = p.parseUShort();
41027    var lookupTableOffsets = p.parseOffset16List(lookupCount);
41028    var lookupListAbsoluteOffset = start + lookupListOffset;
41029    for (var i = 0; i < lookupCount; i++) {
41030        var table = parseLookupTable(data, lookupListAbsoluteOffset + lookupTableOffsets[i]);
41031        if (table.lookupType === 2 && !font.getGposKerningValue) { font.getGposKerningValue = table.getKerningValue; }
41032    }
41033}
41034
41035var gpos = { parse: parseGposTable };
41036
41037// The `kern` table contains kerning pairs.
41038// Note that some fonts use the GPOS OpenType layout table to specify kerning.
41039// https://www.microsoft.com/typography/OTSPEC/kern.htm
41040
41041function parseWindowsKernTable(p) {
41042    var pairs = {};
41043    // Skip nTables.
41044    p.skip('uShort');
41045    var subtableVersion = p.parseUShort();
41046    check.argument(subtableVersion === 0, 'Unsupported kern sub-table version.');
41047    // Skip subtableLength, subtableCoverage
41048    p.skip('uShort', 2);
41049    var nPairs = p.parseUShort();
vendor: 4,149 bytes, lines 41050-41165
41050    // Skip searchRange, entrySelector, rangeShift.
41051    p.skip('uShort', 3);
41052    for (var i = 0; i < nPairs; i += 1) {
41053        var leftIndex = p.parseUShort();
41054        var rightIndex = p.parseUShort();
41055        var value = p.parseShort();
41056        pairs[leftIndex + ',' + rightIndex] = value;
41057    }
41058    return pairs;
41059}
41060
41061function parseMacKernTable(p) {
41062    var pairs = {};
41063    // The Mac kern table stores the version as a fixed (32 bits) but we only loaded the first 16 bits.
41064    // Skip the rest.
41065    p.skip('uShort');
41066    var nTables = p.parseULong();
41067    //check.argument(nTables === 1, 'Only 1 subtable is supported (got ' + nTables + ').');
41068    if (nTables > 1) {
41069        console.warn('Only the first kern subtable is supported.');
41070    }
41071    p.skip('uLong');
41072    var coverage = p.parseUShort();
41073    var subtableVersion = coverage & 0xFF;
41074    p.skip('uShort');
41075    if (subtableVersion === 0) {
41076        var nPairs = p.parseUShort();
41077        // Skip searchRange, entrySelector, rangeShift.
41078        p.skip('uShort', 3);
41079        for (var i = 0; i < nPairs; i += 1) {
41080            var leftIndex = p.parseUShort();
41081            var rightIndex = p.parseUShort();
41082            var value = p.parseShort();
41083            pairs[leftIndex + ',' + rightIndex] = value;
41084        }
41085    }
41086    return pairs;
41087}
41088
41089// Parse the `kern` table which contains kerning pairs.
41090function parseKernTable(data, start) {
41091    var p = new parse.Parser(data, start);
41092    var tableVersion = p.parseUShort();
41093    if (tableVersion === 0) {
41094        return parseWindowsKernTable(p);
41095    } else if (tableVersion === 1) {
41096        return parseMacKernTable(p);
41097    } else {
41098        throw new Error('Unsupported kern table version (' + tableVersion + ').');
41099    }
41100}
41101
41102var kern = { parse: parseKernTable };
41103
41104// The `loca` table stores the offsets to the locations of the glyphs in the font.
41105// https://www.microsoft.com/typography/OTSPEC/loca.htm
41106
41107// Parse the `loca` table. This table stores the offsets to the locations of the glyphs in the font,
41108// relative to the beginning of the glyphData table.
41109// The number of glyphs stored in the `loca` table is specified in the `maxp` table (under numGlyphs)
41110// The loca table has two versions: a short version where offsets are stored as uShorts, and a long
41111// version where offsets are stored as uLongs. The `head` table specifies which version to use
41112// (under indexToLocFormat).
41113function parseLocaTable(data, start, numGlyphs, shortVersion) {
41114    var p = new parse.Parser(data, start);
41115    var parseFn = shortVersion ? p.parseUShort : p.parseULong;
41116    // There is an extra entry after the last index element to compute the length of the last glyph.
41117    // That's why we use numGlyphs + 1.
41118    var glyphOffsets = [];
41119    for (var i = 0; i < numGlyphs + 1; i += 1) {
41120        var glyphOffset = parseFn.call(p);
41121        if (shortVersion) {
41122            // The short table version stores the actual offset divided by 2.
41123            glyphOffset *= 2;
41124        }
41125
41126        glyphOffsets.push(glyphOffset);
41127    }
41128
41129    return glyphOffsets;
41130}
41131
41132var loca = { parse: parseLocaTable };
41133
41134// opentype.js
41135// https://github.com/nodebox/opentype.js
41136// (c) 2015 Frederik De Bleser
41137// opentype.js may be freely distributed under the MIT license.
41138
41139/* global DataView, Uint8Array, XMLHttpRequest  */
41140
41141/**
41142 * The opentype library.
41143 * @namespace opentype
41144 */
41145
41146// File loaders /////////////////////////////////////////////////////////
41147/**
41148 * Loads a font from a file. The callback throws an error message as the first parameter if it fails
41149 * and the font as an ArrayBuffer in the second parameter if it succeeds.
41150 * @param  {string} path - The path of the file
41151 * @param  {Function} callback - The function to call when the font load completes
41152 */
41153function loadFromFile(path, callback) {
41154    var fs = _dereq_('fs');
41155    fs.readFile(path, function(err, buffer) {
41156        if (err) {
41157            return callback(err.message);
41158        }
41159
41160        callback(null, nodeBufferToArrayBuffer(buffer));
41161    });
41162}
41163/**
41164 * Loads a font from a URL. The callback throws an error message as the first parameter if it fails
41165 * and the font as an ArrayBuffer in the second parameter if it succeeds.
41166 * @param  {string} url - The URL of the font file.
41167 * @param  {Function} callback - The function to call when the font load completes
41168 */
41169function loadFromUrl(url, callback) {
41170    var request = new XMLHttpRequest();
41171    request.open('get', url, true);
41172    request.responseType = 'arraybuffer';
41173    request.onload = function() {
41174        if (request.status !== 200) {
41175            return callback('Font could not be loaded: ' + request.statusText);
41176        }
41177
41178        return callback(null, request.response);
41179    };
41180
41181    request.onerror = function () {
41182        callback('Font could not be loaded');
41183    };
41184
41185    request.send();
41186}
41187
41188// Table Directory Entries //////////////////////////////////////////////
41189/**
41190 * Parses OpenType table entries.
41191 * @param  {DataView}
41192 * @param  {Number}
41193 * @return {Object[]}
41194 */
41195function parseOpenTypeTableEntries(data, numTables) {
41196    var tableEntries = [];
41197    var p = 12;
41198    for (var i = 0; i < numTables; i += 1) {
41199        var tag = parse.getTag(data, p);
41200        var checksum = parse.getULong(data, p + 4);
41201        var offset = parse.getULong(data, p + 8);
41202        var length = parse.getULong(data, p + 12);
41203        tableEntries.push({tag: tag, checksum: checksum, offset: offset, length: length, compression: false});
41204        p += 16;
41205    }
41206
41207    return tableEntries;
41208}
41209
41210/**
41211 * Parses WOFF table entries.
41212 * @param  {DataView}
41213 * @param  {Number}
41214 * @return {Object[]}
41215 */
41216function parseWOFFTableEntries(data, numTables) {
41217    var tableEntries = [];
41218    var p = 44; // offset to the first table directory entry.
41219    for (var i = 0; i < numTables; i += 1) {
41220        var tag = parse.getTag(data, p);
41221        var offset = parse.getULong(data, p + 4);
41222        var compLength = parse.getULong(data, p + 8);
41223        var origLength = parse.getULong(data, p + 12);
41224        var compression = (void 0);
41225        if (compLength < origLength) {
41226            compression = 'WOFF';
41227        } else {
41228            compression = false;
41229        }
41230
41231        tableEntries.push({tag: tag, offset: offset, compression: compression,
41232            compressedLength: compLength, length: origLength});
41233        p += 20;
41234    }
41235
41236    return tableEntries;
41237}
41238
41239/**
41240 * @typedef TableData
41241 * @type Object
41242 * @property {DataView} data - The DataView
41243 * @property {number} offset - The data offset.
41244 */
41245
41246/**
41247 * @param  {DataView}
41248 * @param  {Object}
41249 * @return {TableData}
41250 */
41251function uncompressTable(data, tableEntry) {
41252    if (tableEntry.compression === 'WOFF') {
41253        var inBuffer = new Uint8Array(data.buffer, tableEntry.offset + 2, tableEntry.compressedLength - 2);
41254        var outBuffer = new Uint8Array(tableEntry.length);
41255        index(inBuffer, outBuffer);
41256        if (outBuffer.byteLength !== tableEntry.length) {
41257            throw new Error('Decompression error: ' + tableEntry.tag + ' decompressed length doesn\'t match recorded length');
41258        }
41259
41260        var view = new DataView(outBuffer.buffer, 0);
41261        return {data: view, offset: 0};
41262    } else {
41263        return {data: data, offset: tableEntry.offset};
41264    }
41265}
41266
41267// Public API ///////////////////////////////////////////////////////////
41268
41269/**
41270 * Parse the OpenType file data (as an ArrayBuffer) and return a Font object.
41271 * Throws an error if the font could not be parsed.
41272 * @param  {ArrayBuffer}
41273 * @return {opentype.Font}
41274 */
41275function parseBuffer(buffer) {
41276    var indexToLocFormat;
41277    var ltagTable;
41278
41279    // Since the constructor can also be called to create new fonts from scratch, we indicate this
41280    // should be an empty font that we'll fill with our own data.
41281    var font = new Font({empty: true});
41282
41283    // OpenType fonts use big endian byte ordering.
41284    // We can't rely on typed array view types, because they operate with the endianness of the host computer.
41285    // Instead we use DataViews where we can specify endianness.
41286    var data = new DataView(buffer, 0);
41287    var numTables;
41288    var tableEntries = [];
41289    var signature = parse.getTag(data, 0);
41290    if (signature === String.fromCharCode(0, 1, 0, 0) || signature === 'true' || signature === 'typ1') {
41291        font.outlinesFormat = 'truetype';
41292        numTables = parse.getUShort(data, 4);
41293        tableEntries = parseOpenTypeTableEntries(data, numTables);
41294    } else if (signature === 'OTTO') {
41295        font.outlinesFormat = 'cff';
41296        numTables = parse.getUShort(data, 4);
41297        tableEntries = parseOpenTypeTableEntries(data, numTables);
41298    } else if (signature === 'wOFF') {
41299        var flavor = parse.getTag(data, 4);
41300        if (flavor === String.fromCharCode(0, 1, 0, 0)) {
41301            font.outlinesFormat = 'truetype';
41302        } else if (flavor === 'OTTO') {
41303            font.outlinesFormat = 'cff';
41304        } else {
41305            throw new Error('Unsupported OpenType flavor ' + signature);
41306        }
41307
41308        numTables = parse.getUShort(data, 12);
41309        tableEntries = parseWOFFTableEntries(data, numTables);
41310    } else {
41311        throw new Error('Unsupported OpenType signature ' + signature);
41312    }
41313
41314    var cffTableEntry;
41315    var fvarTableEntry;
41316    var glyfTableEntry;
41317    var gposTableEntry;
41318    var gsubTableEntry;
41319    var hmtxTableEntry;
41320    var kernTableEntry;
41321    var locaTableEntry;
41322    var nameTableEntry;
41323    var metaTableEntry;
41324    var p;
41325
41326    for (var i = 0; i < numTables; i += 1) {
41327        var tableEntry = tableEntries[i];
41328        var table = (void 0);
41329        switch (tableEntry.tag) {
41330            case 'cmap':
vendor: 4,048 bytes, lines 41331-41424
41331                table = uncompressTable(data, tableEntry);
41332                font.tables.cmap = cmap.parse(table.data, table.offset);
41333                font.encoding = new CmapEncoding(font.tables.cmap);
41334                break;
41335            case 'cvt ' :
41336                table = uncompressTable(data, tableEntry);
41337                p = new parse.Parser(table.data, table.offset);
41338                font.tables.cvt = p.parseShortList(tableEntry.length / 2);
41339                break;
41340            case 'fvar':
41341                fvarTableEntry = tableEntry;
41342                break;
41343            case 'fpgm' :
41344                table = uncompressTable(data, tableEntry);
41345                p = new parse.Parser(table.data, table.offset);
41346                font.tables.fpgm = p.parseByteList(tableEntry.length);
41347                break;
41348            case 'head':
41349                table = uncompressTable(data, tableEntry);
41350                font.tables.head = head.parse(table.data, table.offset);
41351                font.unitsPerEm = font.tables.head.unitsPerEm;
41352                indexToLocFormat = font.tables.head.indexToLocFormat;
41353                break;
41354            case 'hhea':
41355                table = uncompressTable(data, tableEntry);
41356                font.tables.hhea = hhea.parse(table.data, table.offset);
41357                font.ascender = font.tables.hhea.ascender;
41358                font.descender = font.tables.hhea.descender;
41359                font.numberOfHMetrics = font.tables.hhea.numberOfHMetrics;
41360                break;
41361            case 'hmtx':
41362                hmtxTableEntry = tableEntry;
41363                break;
41364            case 'ltag':
41365                table = uncompressTable(data, tableEntry);
41366                ltagTable = ltag.parse(table.data, table.offset);
41367                break;
41368            case 'maxp':
41369                table = uncompressTable(data, tableEntry);
41370                font.tables.maxp = maxp.parse(table.data, table.offset);
41371                font.numGlyphs = font.tables.maxp.numGlyphs;
41372                break;
41373            case 'name':
41374                nameTableEntry = tableEntry;
41375                break;
41376            case 'OS/2':
41377                table = uncompressTable(data, tableEntry);
41378                font.tables.os2 = os2.parse(table.data, table.offset);
41379                break;
41380            case 'post':
41381                table = uncompressTable(data, tableEntry);
41382                font.tables.post = post.parse(table.data, table.offset);
41383                font.glyphNames = new GlyphNames(font.tables.post);
41384                break;
41385            case 'prep' :
41386                table = uncompressTable(data, tableEntry);
41387                p = new parse.Parser(table.data, table.offset);
41388                font.tables.prep = p.parseByteList(tableEntry.length);
41389                break;
41390            case 'glyf':
41391                glyfTableEntry = tableEntry;
41392                break;
41393            case 'loca':
41394                locaTableEntry = tableEntry;
41395                break;
41396            case 'CFF ':
41397                cffTableEntry = tableEntry;
41398                break;
41399            case 'kern':
41400                kernTableEntry = tableEntry;
41401                break;
41402            case 'GPOS':
41403                gposTableEntry = tableEntry;
41404                break;
41405            case 'GSUB':
41406                gsubTableEntry = tableEntry;
41407                break;
41408            case 'meta':
41409                metaTableEntry = tableEntry;
41410                break;
41411        }
41412    }
41413
41414    var nameTable = uncompressTable(data, nameTableEntry);
41415    font.tables.name = _name.parse(nameTable.data, nameTable.offset, ltagTable);
41416    font.names = font.tables.name;
41417
41418    if (glyfTableEntry && locaTableEntry) {
41419        var shortVersion = indexToLocFormat === 0;
41420        var locaTable = uncompressTable(data, locaTableEntry);
41421        var locaOffsets = loca.parse(locaTable.data, locaTable.offset, font.numGlyphs, shortVersion);
41422        var glyfTable = uncompressTable(data, glyfTableEntry);
41423        font.glyphs = glyf.parse(glyfTable.data, glyfTable.offset, locaOffsets, font);
41424    } else if (cffTableEntry) {
41425        var cffTable = uncompressTable(data, cffTableEntry);
41426        cff.parse(cffTable.data, cffTable.offset, font);
41427    } else {
41428        throw new Error('Font doesn\'t contain TrueType or CFF outlines.');
41429    }
41430
41431    var hmtxTable = uncompressTable(data, hmtxTableEntry);
41432    hmtx.parse(hmtxTable.data, hmtxTable.offset, font.numberOfHMetrics, font.numGlyphs, font.glyphs);
41433    addGlyphNames(font);
41434
41435    if (kernTableEntry) {
41436        var kernTable = uncompressTable(data, kernTableEntry);
41437        font.kerningPairs = kern.parse(kernTable.data, kernTable.offset);
41438    } else {
41439        font.kerningPairs = {};
41440    }
41441
41442    if (gposTableEntry) {
41443        var gposTable = uncompressTable(data, gposTableEntry);
41444        gpos.parse(gposTable.data, gposTable.offset, font);
41445    }
41446
41447    if (gsubTableEntry) {
41448        var gsubTable = uncompressTable(data, gsubTableEntry);
41449        font.tables.gsub = gsub.parse(gsubTable.data, gsubTable.offset);
41450    }
41451
41452    if (fvarTableEntry) {
41453        var fvarTable = uncompressTable(data, fvarTableEntry);
41454        font.tables.fvar = fvar.parse(fvarTable.data, fvarTable.offset, font.names);
41455    }
41456
41457    if (metaTableEntry) {
41458        var metaTable = uncompressTable(data, metaTableEntry);
41459        font.tables.meta = meta.parse(metaTable.data, metaTable.offset);
41460        font.metas = font.tables.meta;
41461    }
41462
41463    return font;
41464}
41465
41466/**
41467 * Asynchronously load the font from a URL or a filesystem. When done, call the callback
41468 * with two arguments `(err, font)`. The `err` will be null on success,
41469 * the `font` is a Font object.
41470 * We use the node.js callback convention so that
41471 * opentype.js can integrate with frameworks like async.js.
41472 * @alias opentype.load
41473 * @param  {string} url - The URL of the font to load.
41474 * @param  {Function} callback - The callback.
41475 */
41476function load(url, callback) {
41477    var isNode$$1 = typeof window === 'undefined';
41478    var loadFn = isNode$$1 ? loadFromFile : loadFromUrl;
41479    loadFn(url, function(err, arrayBuffer) {
41480        if (err) {
41481            return callback(err);
41482        }
41483        var font;
41484        try {
41485            font = parseBuffer(arrayBuffer);
41486        } catch (e) {
41487            return callback(e, null);
41488        }
41489        return callback(null, font);
41490    });
41491}
41492
41493/**
41494 * Synchronously load the font from a URL or file.
41495 * When done, returns the font object or throws an error.
41496 * @alias opentype.loadSync
41497 * @param  {string} url - The URL of the font to load.
41498 * @return {opentype.Font}
41499 */
41500function loadSync(url) {
41501    var fs = _dereq_('fs');
41502    var buffer = fs.readFileSync(url);
41503    return parseBuffer(nodeBufferToArrayBuffer(buffer));
41504}
41505
41506exports.Font = Font;
41507exports.Glyph = Glyph;
41508exports.Path = Path;
41509exports.BoundingBox = BoundingBox;
41510exports._parse = parse;
41511exports.parse = parseBuffer;
41512exports.load = load;
41513exports.loadSync = loadSync;
41514
41515Object.defineProperty(exports, '__esModule', { value: true });
41516
41517})));
41518
41519
41520}).call(this,_dereq_("buffer").Buffer)
41521},{"buffer":4,"fs":3}],11:[function(_dereq_,module,exports){
41522// shim for using process in browser
41523var process = module.exports = {};
41524
41525// cached from whatever global is present so that test runners that stub it
41526// don't break things.  But we need to wrap it in a try catch in case it is
41527// wrapped in strict mode code which doesn't define any globals.  It's inside a
41528// function because try/catches deoptimize in certain engines.
41529
41530var cachedSetTimeout;
41531var cachedClearTimeout;
41532
41533function defaultSetTimout() {
41534    throw new Error('setTimeout has not been defined');
41535}
41536function defaultClearTimeout () {
41537    throw new Error('clearTimeout has not been defined');
41538}
41539(function () {
41540    try {
41541        if (typeof setTimeout === 'function') {
41542            cachedSetTimeout = setTimeout;
41543        } else {
41544            cachedSetTimeout = defaultSetTimout;
41545        }
41546    } catch (e) {
41547        cachedSetTimeout = defaultSetTimout;
41548    }
41549    try {
41550        if (typeof clearTimeout === 'function') {
41551            cachedClearTimeout = clearTimeout;
41552        } else {
41553            cachedClearTimeout = defaultClearTimeout;
41554        }
41555    } catch (e) {
41556        cachedClearTimeout = defaultClearTimeout;
41557    }
41558} ())
41559function runTimeout(fun) {
41560    if (cachedSetTimeout === setTimeout) {
41561        //normal enviroments in sane situations
41562        return setTimeout(fun, 0);
41563    }
41564    // if setTimeout wasn't available but was latter defined
41565    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
41566        cachedSetTimeout = setTimeout;
41567        return setTimeout(fun, 0);
41568    }
41569    try {
41570        // when when somebody has screwed with setTimeout but no I.E. maddness
41571        return cachedSetTimeout(fun, 0);
41572    } catch(e){
41573        try {
41574            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
41575            return cachedSetTimeout.call(null, fun, 0);
41576        } catch(e){
41577            // 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
41578            return cachedSetTimeout.call(this, fun, 0);
41579        }
41580    }
41581
41582
41583}
41584function runClearTimeout(marker) {
41585    if (cachedClearTimeout === clearTimeout) {
41586        //normal enviroments in sane situations
41587        return clearTimeout(marker);
41588    }
41589    // if clearTimeout wasn't available but was latter defined
41590    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
41591        cachedClearTimeout = clearTimeout;
41592        return clearTimeout(marker);
41593    }
41594    try {
41595        // when when somebody has screwed with setTimeout but no I.E. maddness
41596        return cachedClearTimeout(marker);
41597    } catch (e){
41598        try {
41599            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally
41600            return cachedClearTimeout.call(null, marker);
41601        } catch (e){
41602            // 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.
41603            // Some versions of I.E. have different rules for clearTimeout vs setTimeout
41604            return cachedClearTimeout.call(this, marker);
41605        }
41606    }
41607
41608
41609
41610}
41611var queue = [];
41612var draining = false;
vendor: 14,572 bytes, lines 41613-42159
41613var currentQueue;
41614var queueIndex = -1;
41615
41616function cleanUpNextTick() {
41617    if (!draining || !currentQueue) {
41618        return;
41619    }
41620    draining = false;
41621    if (currentQueue.length) {
41622        queue = currentQueue.concat(queue);
41623    } else {
41624        queueIndex = -1;
41625    }
41626    if (queue.length) {
41627        drainQueue();
41628    }
41629}
41630
41631function drainQueue() {
41632    if (draining) {
41633        return;
41634    }
41635    var timeout = runTimeout(cleanUpNextTick);
41636    draining = true;
41637
41638    var len = queue.length;
41639    while(len) {
41640        currentQueue = queue;
41641        queue = [];
41642        while (++queueIndex < len) {
41643            if (currentQueue) {
41644                currentQueue[queueIndex].run();
41645            }
41646        }
41647        queueIndex = -1;
41648        len = queue.length;
41649    }
41650    currentQueue = null;
41651    draining = false;
41652    runClearTimeout(timeout);
41653}
41654
41655process.nextTick = function (fun) {
41656    var args = new Array(arguments.length - 1);
41657    if (arguments.length > 1) {
41658        for (var i = 1; i < arguments.length; i++) {
41659            args[i - 1] = arguments[i];
41660        }
41661    }
41662    queue.push(new Item(fun, args));
41663    if (queue.length === 1 && !draining) {
41664        runTimeout(drainQueue);
41665    }
41666};
41667
41668// v8 likes predictible objects
41669function Item(fun, array) {
41670    this.fun = fun;
41671    this.array = array;
41672}
41673Item.prototype.run = function () {
41674    this.fun.apply(null, this.array);
41675};
41676process.title = 'browser';
41677process.browser = true;
41678process.env = {};
41679process.argv = [];
41680process.version = ''; // empty string to avoid regexp issues
41681process.versions = {};
41682
41683function noop() {}
41684
41685process.on = noop;
41686process.addListener = noop;
41687process.once = noop;
41688process.off = noop;
41689process.removeListener = noop;
41690process.removeAllListeners = noop;
41691process.emit = noop;
41692process.prependListener = noop;
41693process.prependOnceListener = noop;
41694
41695process.listeners = function (name) { return [] }
41696
41697process.binding = function (name) {
41698    throw new Error('process.binding is not supported');
41699};
41700
41701process.cwd = function () { return '/' };
41702process.chdir = function (dir) {
41703    throw new Error('process.chdir is not supported');
41704};
41705process.umask = function() { return 0; };
41706
41707},{}],12:[function(_dereq_,module,exports){
41708(function(self) {
41709  'use strict';
41710
41711  if (self.fetch) {
41712    return
41713  }
41714
41715  var support = {
41716    searchParams: 'URLSearchParams' in self,
41717    iterable: 'Symbol' in self && 'iterator' in Symbol,
41718    blob: 'FileReader' in self && 'Blob' in self && (function() {
41719      try {
41720        new Blob()
41721        return true
41722      } catch(e) {
41723        return false
41724      }
41725    })(),
41726    formData: 'FormData' in self,
41727    arrayBuffer: 'ArrayBuffer' in self
41728  }
41729
41730  if (support.arrayBuffer) {
41731    var viewClasses = [
41732      '[object Int8Array]',
41733      '[object Uint8Array]',
41734      '[object Uint8ClampedArray]',
41735      '[object Int16Array]',
41736      '[object Uint16Array]',
41737      '[object Int32Array]',
41738      '[object Uint32Array]',
41739      '[object Float32Array]',
41740      '[object Float64Array]'
41741    ]
41742
41743    var isDataView = function(obj) {
41744      return obj && DataView.prototype.isPrototypeOf(obj)
41745    }
41746
41747    var isArrayBufferView = ArrayBuffer.isView || function(obj) {
41748      return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1
41749    }
41750  }
41751
41752  function normalizeName(name) {
41753    if (typeof name !== 'string') {
41754      name = String(name)
41755    }
41756    if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) {
41757      throw new TypeError('Invalid character in header field name')
41758    }
41759    return name.toLowerCase()
41760  }
41761
41762  function normalizeValue(value) {
41763    if (typeof value !== 'string') {
41764      value = String(value)
41765    }
41766    return value
41767  }
41768
41769  // Build a destructive iterator for the value list
41770  function iteratorFor(items) {
41771    var iterator = {
41772      next: function() {
41773        var value = items.shift()
41774        return {done: value === undefined, value: value}
41775      }
41776    }
41777
41778    if (support.iterable) {
41779      iterator[Symbol.iterator] = function() {
41780        return iterator
41781      }
41782    }
41783
41784    return iterator
41785  }
41786
41787  function Headers(headers) {
41788    this.map = {}
41789
41790    if (headers instanceof Headers) {
41791      headers.forEach(function(value, name) {
41792        this.append(name, value)
41793      }, this)
41794    } else if (Array.isArray(headers)) {
41795      headers.forEach(function(header) {
41796        this.append(header[0], header[1])
41797      }, this)
41798    } else if (headers) {
41799      Object.getOwnPropertyNames(headers).forEach(function(name) {
41800        this.append(name, headers[name])
41801      }, this)
41802    }
41803  }
41804
41805  Headers.prototype.append = function(name, value) {
41806    name = normalizeName(name)
41807    value = normalizeValue(value)
41808    var oldValue = this.map[name]
41809    this.map[name] = oldValue ? oldValue+','+value : value
41810  }
41811
41812  Headers.prototype['delete'] = function(name) {
41813    delete this.map[normalizeName(name)]
41814  }
41815
41816  Headers.prototype.get = function(name) {
41817    name = normalizeName(name)
41818    return this.has(name) ? this.map[name] : null
41819  }
41820
41821  Headers.prototype.has = function(name) {
41822    return this.map.hasOwnProperty(normalizeName(name))
41823  }
41824
41825  Headers.prototype.set = function(name, value) {
41826    this.map[normalizeName(name)] = normalizeValue(value)
41827  }
41828
41829  Headers.prototype.forEach = function(callback, thisArg) {
41830    for (var name in this.map) {
41831      if (this.map.hasOwnProperty(name)) {
41832        callback.call(thisArg, this.map[name], name, this)
41833      }
41834    }
41835  }
41836
41837  Headers.prototype.keys = function() {
41838    var items = []
41839    this.forEach(function(value, name) { items.push(name) })
41840    return iteratorFor(items)
41841  }
41842
41843  Headers.prototype.values = function() {
41844    var items = []
41845    this.forEach(function(value) { items.push(value) })
41846    return iteratorFor(items)
41847  }
41848
41849  Headers.prototype.entries = function() {
41850    var items = []
41851    this.forEach(function(value, name) { items.push([name, value]) })
41852    return iteratorFor(items)
41853  }
41854
41855  if (support.iterable) {
41856    Headers.prototype[Symbol.iterator] = Headers.prototype.entries
41857  }
41858
41859  function consumed(body) {
41860    if (body.bodyUsed) {
41861      return Promise.reject(new TypeError('Already read'))
41862    }
41863    body.bodyUsed = true
41864  }
41865
41866  function fileReaderReady(reader) {
41867    return new Promise(function(resolve, reject) {
41868      reader.onload = function() {
41869        resolve(reader.result)
41870      }
41871      reader.onerror = function() {
41872        reject(reader.error)
41873      }
41874    })
41875  }
41876
41877  function readBlobAsArrayBuffer(blob) {
41878    var reader = new FileReader()
41879    var promise = fileReaderReady(reader)
41880    reader.readAsArrayBuffer(blob)
41881    return promise
41882  }
41883
41884  function readBlobAsText(blob) {
41885    var reader = new FileReader()
41886    var promise = fileReaderReady(reader)
41887    reader.readAsText(blob)
41888    return promise
41889  }
41890
41891  function readArrayBufferAsText(buf) {
41892    var view = new Uint8Array(buf)
41893    var chars = new Array(view.length)
41894
41895    for (var i = 0; i < view.length; i++) {
41896      chars[i] = String.fromCharCode(view[i])
41897    }
41898    return chars.join('')
41899  }
41900
41901  function bufferClone(buf) {
41902    if (buf.slice) {
41903      return buf.slice(0)
41904    } else {
41905      var view = new Uint8Array(buf.byteLength)
41906      view.set(new Uint8Array(buf))
41907      return view.buffer
41908    }
41909  }
41910
41911  function Body() {
41912    this.bodyUsed = false
41913
41914    this._initBody = function(body) {
41915      this._bodyInit = body
41916      if (!body) {
41917        this._bodyText = ''
41918      } else if (typeof body === 'string') {
41919        this._bodyText = body
41920      } else if (support.blob && Blob.prototype.isPrototypeOf(body)) {
41921        this._bodyBlob = body
41922      } else if (support.formData && FormData.prototype.isPrototypeOf(body)) {
41923        this._bodyFormData = body
41924      } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
41925        this._bodyText = body.toString()
41926      } else if (support.arrayBuffer && support.blob && isDataView(body)) {
41927        this._bodyArrayBuffer = bufferClone(body.buffer)
41928        // IE 10-11 can't handle a DataView body.
41929        this._bodyInit = new Blob([this._bodyArrayBuffer])
41930      } else if (support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) {
41931        this._bodyArrayBuffer = bufferClone(body)
41932      } else {
41933        throw new Error('unsupported BodyInit type')
41934      }
41935
41936      if (!this.headers.get('content-type')) {
41937        if (typeof body === 'string') {
41938          this.headers.set('content-type', 'text/plain;charset=UTF-8')
41939        } else if (this._bodyBlob && this._bodyBlob.type) {
41940          this.headers.set('content-type', this._bodyBlob.type)
41941        } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
41942          this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8')
41943        }
41944      }
41945    }
41946
41947    if (support.blob) {
41948      this.blob = function() {
41949        var rejected = consumed(this)
41950        if (rejected) {
41951          return rejected
41952        }
41953
41954        if (this._bodyBlob) {
41955          return Promise.resolve(this._bodyBlob)
41956        } else if (this._bodyArrayBuffer) {
41957          return Promise.resolve(new Blob([this._bodyArrayBuffer]))
41958        } else if (this._bodyFormData) {
41959          throw new Error('could not read FormData body as blob')
41960        } else {
41961          return Promise.resolve(new Blob([this._bodyText]))
41962        }
41963      }
41964
41965      this.arrayBuffer = function() {
41966        if (this._bodyArrayBuffer) {
41967          return consumed(this) || Promise.resolve(this._bodyArrayBuffer)
41968        } else {
41969          return this.blob().then(readBlobAsArrayBuffer)
41970        }
41971      }
41972    }
41973
41974    this.text = function() {
41975      var rejected = consumed(this)
41976      if (rejected) {
41977        return rejected
41978      }
41979
41980      if (this._bodyBlob) {
41981        return readBlobAsText(this._bodyBlob)
41982      } else if (this._bodyArrayBuffer) {
41983        return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer))
41984      } else if (this._bodyFormData) {
41985        throw new Error('could not read FormData body as text')
41986      } else {
41987        return Promise.resolve(this._bodyText)
41988      }
41989    }
41990
41991    if (support.formData) {
41992      this.formData = function() {
41993        return this.text().then(decode)
41994      }
41995    }
41996
41997    this.json = function() {
41998      return this.text().then(JSON.parse)
41999    }
42000
42001    return this
42002  }
42003
42004  // HTTP methods whose capitalization should be normalized
42005  var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT']
42006
42007  function normalizeMethod(method) {
42008    var upcased = method.toUpperCase()
42009    return (methods.indexOf(upcased) > -1) ? upcased : method
42010  }
42011
42012  function Request(input, options) {
42013    options = options || {}
42014    var body = options.body
42015
42016    if (input instanceof Request) {
42017      if (input.bodyUsed) {
42018        throw new TypeError('Already read')
42019      }
42020      this.url = input.url
42021      this.credentials = input.credentials
42022      if (!options.headers) {
42023        this.headers = new Headers(input.headers)
42024      }
42025      this.method = input.method
42026      this.mode = input.mode
42027      if (!body && input._bodyInit != null) {
42028        body = input._bodyInit
42029        input.bodyUsed = true
42030      }
42031    } else {
42032      this.url = String(input)
42033    }
42034
42035    this.credentials = options.credentials || this.credentials || 'omit'
42036    if (options.headers || !this.headers) {
42037      this.headers = new Headers(options.headers)
42038    }
42039    this.method = normalizeMethod(options.method || this.method || 'GET')
42040    this.mode = options.mode || this.mode || null
42041    this.referrer = null
42042
42043    if ((this.method === 'GET' || this.method === 'HEAD') && body) {
42044      throw new TypeError('Body not allowed for GET or HEAD requests')
42045    }
42046    this._initBody(body)
42047  }
42048
42049  Request.prototype.clone = function() {
42050    return new Request(this, { body: this._bodyInit })
42051  }
42052
42053  function decode(body) {
42054    var form = new FormData()
42055    body.trim().split('&').forEach(function(bytes) {
42056      if (bytes) {
42057        var split = bytes.split('=')
42058        var name = split.shift().replace(/\+/g, ' ')
42059        var value = split.join('=').replace(/\+/g, ' ')
42060        form.append(decodeURIComponent(name), decodeURIComponent(value))
42061      }
42062    })
42063    return form
42064  }
42065
42066  function parseHeaders(rawHeaders) {
42067    var headers = new Headers()
42068    rawHeaders.split(/\r?\n/).forEach(function(line) {
42069      var parts = line.split(':')
42070      var key = parts.shift().trim()
42071      if (key) {
42072        var value = parts.join(':').trim()
42073        headers.append(key, value)
42074      }
42075    })
42076    return headers
42077  }
42078
42079  Body.call(Request.prototype)
42080
42081  function Response(bodyInit, options) {
42082    if (!options) {
42083      options = {}
42084    }
42085
42086    this.type = 'default'
42087    this.status = 'status' in options ? options.status : 200
42088    this.ok = this.status >= 200 && this.status < 300
42089    this.statusText = 'statusText' in options ? options.statusText : 'OK'
42090    this.headers = new Headers(options.headers)
42091    this.url = options.url || ''
42092    this._initBody(bodyInit)
42093  }
42094
42095  Body.call(Response.prototype)
42096
42097  Response.prototype.clone = function() {
42098    return new Response(this._bodyInit, {
42099      status: this.status,
42100      statusText: this.statusText,
42101      headers: new Headers(this.headers),
42102      url: this.url
42103    })
42104  }
42105
42106  Response.error = function() {
42107    var response = new Response(null, {status: 0, statusText: ''})
42108    response.type = 'error'
42109    return response
42110  }
42111
42112  var redirectStatuses = [301, 302, 303, 307, 308]
42113
42114  Response.redirect = function(url, status) {
42115    if (redirectStatuses.indexOf(status) === -1) {
42116      throw new RangeError('Invalid status code')
42117    }
42118
42119    return new Response(null, {status: status, headers: {location: url}})
42120  }
42121
42122  self.Headers = Headers
42123  self.Request = Request
42124  self.Response = Response
42125
42126  self.fetch = function(input, init) {
42127    return new Promise(function(resolve, reject) {
42128      var request = new Request(input, init)
42129      var xhr = new XMLHttpRequest()
42130
42131      xhr.onload = function() {
42132        var options = {
42133          status: xhr.status,
42134          statusText: xhr.statusText,
42135          headers: parseHeaders(xhr.getAllResponseHeaders() || '')
42136        }
42137        options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL')
42138        var body = 'response' in xhr ? xhr.response : xhr.responseText
42139        resolve(new Response(body, options))
42140      }
42141
42142      xhr.onerror = function() {
42143        reject(new TypeError('Network request failed'))
42144      }
42145
42146      xhr.ontimeout = function() {
42147        reject(new TypeError('Network request failed'))
42148      }
42149
42150      xhr.open(request.method, request.url, true)
42151
42152      if (request.credentials === 'include') {
42153        xhr.withCredentials = true
42154      }
42155
42156      if ('responseType' in xhr && support.blob) {
42157        xhr.responseType = 'blob'
42158      }
42159
42160      request.headers.forEach(function(value, name) {
42161        xhr.setRequestHeader(name, value)
42162      })
42163
42164      xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit)
42165    })
42166  }
42167  self.fetch.polyfill = true
42168})(typeof self !== 'undefined' ? self : this);
42169
42170},{}],13:[function(_dereq_,module,exports){
42171'use strict';
42172
42173var p5 = _dereq_('./core/core');
42174_dereq_('./color/p5.Color');
42175_dereq_('./core/p5.Element');
42176_dereq_('./typography/p5.Font');
42177_dereq_('./core/p5.Graphics');
42178_dereq_('./core/p5.Renderer2D');
42179
42180_dereq_('./image/p5.Image');
42181_dereq_('./math/p5.Vector');
42182_dereq_('./io/p5.TableRow');
42183_dereq_('./io/p5.Table');
42184_dereq_('./io/p5.XML');
42185
42186_dereq_('./color/creating_reading');
42187_dereq_('./color/setting');
42188_dereq_('./core/constants');
42189_dereq_('./utilities/conversion');
42190_dereq_('./utilities/array_functions');
42191_dereq_('./utilities/string_functions');
42192_dereq_('./core/environment');
42193_dereq_('./image/image');
42194_dereq_('./image/loading_displaying');
42195_dereq_('./image/pixels');
42196_dereq_('./io/files');
42197_dereq_('./events/keyboard');
42198_dereq_('./events/acceleration'); //john
42199_dereq_('./events/mouse');
42200_dereq_('./utilities/time_date');
42201_dereq_('./events/touch');
42202_dereq_('./math/math');
42203_dereq_('./math/calculation');
42204_dereq_('./math/random');
42205_dereq_('./math/noise');
42206_dereq_('./math/trigonometry');
42207_dereq_('./core/rendering');
42208_dereq_('./core/2d_primitives');
42209
42210_dereq_('./core/attributes');
42211_dereq_('./core/curves');
42212_dereq_('./core/vertex');
42213_dereq_('./core/structure');
42214_dereq_('./core/transform');
42215_dereq_('./typography/attributes');
42216_dereq_('./typography/loading_displaying');
42217
42218_dereq_('./data/p5.TypedDict');
42219
42220_dereq_('./webgl/p5.RendererGL');
42221_dereq_('./webgl/p5.Geometry');
42222_dereq_('./webgl/p5.RendererGL.Retained');
42223_dereq_('./webgl/p5.RendererGL.Immediate');
42224_dereq_('./webgl/primitives');
42225_dereq_('./webgl/loading');
42226_dereq_('./webgl/p5.Matrix');
42227_dereq_('./webgl/material');
42228_dereq_('./webgl/light');
42229_dereq_('./webgl/p5.Shader');
42230_dereq_('./webgl/camera');
42231_dereq_('./webgl/interaction');
42232
42233_dereq_('./core/init.js');
42234
42235module.exports = p5;
42236
42237},{"./color/creating_reading":15,"./color/p5.Color":16,"./color/setting":17,"./core/2d_primitives":18,"./core/attributes":19,"./core/constants":21,"./core/core":22,"./core/curves":23,"./core/environment":24,"./core/init.js":26,"./core/p5.Element":27,"./core/p5.Graphics":28,"./core/p5.Renderer2D":30,"./core/rendering":31,"./core/structure":33,"./core/transform":34,"./core/vertex":35,"./data/p5.TypedDict":36,"./events/acceleration":37,"./events/keyboard":38,"./events/mouse":39,"./events/touch":40,"./image/image":42,"./image/loading_displaying":43,"./image/p5.Image":44,"./image/pixels":45,"./io/files":46,"./io/p5.Table":47,"./io/p5.TableRow":48,"./io/p5.XML":49,"./math/calculation":50,"./math/math":51,"./math/noise":52,"./math/p5.Vector":53,"./math/random":54,"./math/trigonometry":55,"./typography/attributes":56,"./typography/loading_displaying":57,"./typography/p5.Font":58,"./utilities/array_functions":59,"./utilities/conversion":60,"./utilities/string_functions":61,"./utilities/time_date":62,"./webgl/camera":63,"./webgl/interaction":64,"./webgl/light":65,"./webgl/loading":66,"./webgl/material":67,"./webgl/p5.Geometry":68,"./webgl/p5.Matrix":69,"./webgl/p5.RendererGL":72,"./webgl/p5.RendererGL.Immediate":70,"./webgl/p5.RendererGL.Retained":71,"./webgl/p5.Shader":73,"./webgl/primitives":75}],14:[function(_dereq_,module,exports){
42238/**
42239 * @module Conversion
42240 * @submodule Color Conversion
42241 * @for p5
42242 * @requires core
42243 */
42244
42245'use strict';
42246
42247/**
42248 * Conversions adapted from <http://www.easyrgb.com/en/math.php>.
42249 *
42250 * In these functions, hue is always in the range [0,1); all other components
42251 * are in the range [0,1]. 'Brightness' and 'value' are used interchangeably.
42252 */
42253
42254var p5 = _dereq_('../core/core');
42255p5.ColorConversion = {};
42256
42257/**
42258 * Convert an HSBA array to HSLA.
42259 */
42260p5.ColorConversion._hsbaToHSLA = function(hsba) {
42261  var hue = hsba[0];
42262  var sat = hsba[1];
42263  var val = hsba[2];
42264
42265  // Calculate lightness.
42266  var li = (2 - sat) * val / 2;
42267
42268  // Convert saturation.
42269  if (li !== 0) {
42270    if (li === 1) {
42271      sat = 0;
42272    } else if (li < 0.5) {
42273      sat = sat / (2 - sat);
42274    } else {
42275      sat = sat * val / (2 - li * 2);
42276    }
42277  }
42278
42279  // Hue and alpha stay the same.
42280  return [hue, sat, li, hsba[3]];
42281};
42282
42283/**
42284 * Convert an HSBA array to RGBA.
42285 */
42286p5.ColorConversion._hsbaToRGBA = function(hsba) {
42287  var hue = hsba[0] * 6; // We will split hue into 6 sectors.
42288  var sat = hsba[1];
42289  var val = hsba[2];
42290
42291  var RGBA = [];
42292
42293  if (sat === 0) {
42294    RGBA = [val, val, val, hsba[3]]; // Return early if grayscale.
42295  } else {
42296    var sector = Math.floor(hue);
42297    var tint1 = val * (1 - sat);
42298    var tint2 = val * (1 - sat * (hue - sector));
42299    var tint3 = val * (1 - sat * (1 + sector - hue));
42300    var red, green, blue;
42301    if (sector === 1) {
42302      // Yellow to green.
42303      red = tint2;
42304      green = val;
42305      blue = tint1;
42306    } else if (sector === 2) {
42307      // Green to cyan.
42308      red = tint1;
42309      green = val;
42310      blue = tint3;
42311    } else if (sector === 3) {
42312      // Cyan to blue.
42313      red = tint1;
42314      green = tint2;
42315      blue = val;
42316    } else if (sector === 4) {
42317      // Blue to magenta.
42318      red = tint3;
42319      green = tint1;
42320      blue = val;
42321    } else if (sector === 5) {
42322      // Magenta to red.
42323      red = val;
42324      green = tint1;
42325      blue = tint2;
42326    } else {
42327      // Red to yellow (sector could be 0 or 6).
42328      red = val;
42329      green = tint3;
42330      blue = tint1;
42331    }
42332    RGBA = [red, green, blue, hsba[3]];
42333  }
42334
42335  return RGBA;
42336};
42337
42338/**
42339 * Convert an HSLA array to HSBA.
42340 */
42341p5.ColorConversion._hslaToHSBA = function(hsla) {
42342  var hue = hsla[0];
42343  var sat = hsla[1];
42344  var li = hsla[2];
42345
42346  // Calculate brightness.
42347  var val;
42348  if (li < 0.5) {
42349    val = (1 + sat) * li;
42350  } else {
42351    val = li + sat - li * sat;
42352  }
42353
42354  // Convert saturation.
42355  sat = 2 * (val - li) / val;
42356
42357  // Hue and alpha stay the same.
42358  return [hue, sat, val, hsla[3]];
42359};
42360
42361/**
42362 * Convert an HSLA array to RGBA.
42363 *
42364 * We need to change basis from HSLA to something that can be more easily be
42365 * projected onto RGBA. We will choose hue and brightness as our first two
42366 * components, and pick a convenient third one ('zest') so that we don't need
42367 * to calculate formal HSBA saturation.
42368 */
42369p5.ColorConversion._hslaToRGBA = function(hsla) {
42370  var hue = hsla[0] * 6; // We will split hue into 6 sectors.
42371  var sat = hsla[1];
42372  var li = hsla[2];
42373
42374  var RGBA = [];
42375
42376  if (sat === 0) {
42377    RGBA = [li, li, li, hsla[3]]; // Return early if grayscale.
42378  } else {
42379    // Calculate brightness.
42380    var val;
42381    if (li < 0.5) {
42382      val = (1 + sat) * li;
42383    } else {
42384      val = li + sat - li * sat;
42385    }
42386
42387    // Define zest.
42388    var zest = 2 * li - val;
42389
42390    // Implement projection (project onto green by default).
42391    var hzvToRGB = function(hue, zest, val) {
42392      if (hue < 0) {
42393        // Hue must wrap to allow projection onto red and blue.
42394        hue += 6;
42395      } else if (hue >= 6) {
42396        hue -= 6;
42397      }
42398      if (hue < 1) {
42399        // Red to yellow (increasing green).
42400        return zest + (val - zest) * hue;
42401      } else if (hue < 3) {
42402        // Yellow to cyan (greatest green).
42403        return val;
42404      } else if (hue < 4) {
42405        // Cyan to blue (decreasing green).
42406        return zest + (val - zest) * (4 - hue);
42407      } else {
42408        // Blue to red (least green).
42409        return zest;
42410      }
42411    };
42412
42413    // Perform projections, offsetting hue as necessary.
42414    RGBA = [
42415      hzvToRGB(hue + 2, zest, val),
42416      hzvToRGB(hue, zest, val),
42417      hzvToRGB(hue - 2, zest, val),
42418      hsla[3]
42419    ];
42420  }
42421
42422  return RGBA;
42423};
42424
42425/**
42426 * Convert an RGBA array to HSBA.
42427 */
42428p5.ColorConversion._rgbaToHSBA = function(rgba) {
42429  var red = rgba[0];
42430  var green = rgba[1];
42431  var blue = rgba[2];
42432
42433  var val = Math.max(red, green, blue);
42434  var chroma = val - Math.min(red, green, blue);
42435
42436  var hue, sat;
42437  if (chroma === 0) {
42438    // Return early if grayscale.
42439    hue = 0;
42440    sat = 0;
42441  } else {
42442    sat = chroma / val;
42443    if (red === val) {
42444      // Magenta to yellow.
42445      hue = (green - blue) / chroma;
42446    } else if (green === val) {
42447      // Yellow to cyan.
42448      hue = 2 + (blue - red) / chroma;
42449    } else if (blue === val) {
42450      // Cyan to magenta.
42451      hue = 4 + (red - green) / chroma;
42452    }
42453    if (hue < 0) {
42454      // Confine hue to the interval [0, 1).
42455      hue += 6;
42456    } else if (hue >= 6) {
42457      hue -= 6;
42458    }
42459  }
42460
42461  return [hue / 6, sat, val, rgba[3]];
42462};
42463
42464/**
42465 * Convert an RGBA array to HSLA.
42466 */
42467p5.ColorConversion._rgbaToHSLA = function(rgba) {
42468  var red = rgba[0];
42469  var green = rgba[1];
42470  var blue = rgba[2];
42471
42472  var val = Math.max(red, green, blue);
42473  var min = Math.min(red, green, blue);
42474  var li = val + min; // We will halve this later.
42475  var chroma = val - min;
42476
42477  var hue, sat;
42478  if (chroma === 0) {
42479    // Return early if grayscale.
42480    hue = 0;
42481    sat = 0;
42482  } else {
42483    if (li < 1) {
42484      sat = chroma / li;
42485    } else {
42486      sat = chroma / (2 - li);
42487    }
42488    if (red === val) {
42489      // Magenta to yellow.
42490      hue = (green - blue) / chroma;
42491    } else if (green === val) {
42492      // Yellow to cyan.
42493      hue = 2 + (blue - red) / chroma;
42494    } else if (blue === val) {
42495      // Cyan to magenta.
42496      hue = 4 + (red - green) / chroma;
42497    }
42498    if (hue < 0) {
42499      // Confine hue to the interval [0, 1).
42500      hue += 6;
42501    } else if (hue >= 6) {
42502      hue -= 6;
42503    }
42504  }
42505
42506  return [hue / 6, sat, li / 2, rgba[3]];
42507};
42508
42509module.exports = p5.ColorConversion;
42510
42511},{"../core/core":22}],15:[function(_dereq_,module,exports){
42512/**
42513 * @module Color
42514 * @submodule Creating & Reading
42515 * @for p5
42516 * @requires core
42517 * @requires constants
42518 */
42519
42520'use strict';
42521
42522var p5 = _dereq_('../core/core');
42523var constants = _dereq_('../core/constants');
42524_dereq_('./p5.Color');
42525_dereq_('../core/error_helpers');
42526
42527/**
42528 * Extracts the alpha value from a color or pixel array.
42529 *
42530 * @method alpha
42531 * @param {p5.Color|Number[]|String} color p5.Color object, color components,
42532 *                                         or CSS color
42533 * @return {Number} the alpha value
42534 * @example
42535 * <div>
42536 * <code>
42537 * noStroke();
42538 * var c = color(0, 126, 255, 102);
42539 * fill(c);
42540 * rect(15, 15, 35, 70);
42541 * var value = alpha(c); // Sets 'value' to 102
42542 * fill(value);
42543 * rect(50, 15, 35, 70);
42544 * </code>
42545 * </div>
42546 *
42547 * @alt
42548 * Left half of canvas light blue and right half light charcoal grey.
42549 * Left half of canvas light purple and right half a royal blue.
42550 * Left half of canvas salmon pink and the right half white.
42551 * Yellow rect in middle right of canvas, with 55 pixel width and height.
42552 * Yellow ellipse in top left canvas, black ellipse in bottom right,both 80x80.
42553 * Bright fuschia rect in middle of canvas, 60 pixel width and height.
42554 * Two bright green rects on opposite sides of the canvas, both 45x80.
42555 * Four blue rects in each corner of the canvas, each are 35x35.
42556 * Bright sea green rect on left and darker rect on right of canvas, both 45x80.
42557 * Dark green rect on left and light green rect on right of canvas, both 45x80.
42558 * Dark blue rect on left and light teal rect on right of canvas, both 45x80.
42559 * blue rect on left and green on right, both with black outlines & 35x60.
42560 * salmon pink rect on left and black on right, both 35x60.
42561 * 4 rects, tan, brown, brownish purple and purple, with white outlines & 20x60.
42562 * light pastel green rect on left and dark grey rect on right, both 35x60.
42563 * yellow rect on left and red rect on right, both with black outlines & 35x60.
42564 * grey canvas
42565 * deep pink rect on left and grey rect on right, both 35x60.
42566 */
42567p5.prototype.alpha = function(c) {
42568  p5._validateParameters('alpha', arguments);
42569  return this.color(c)._getAlpha();
42570};
42571
42572/**
42573 * Extracts the blue value from a color or pixel array.
42574 *
42575 * @method blue
42576 * @param {p5.Color|Number[]|String} color p5.Color object, color components,
42577 *                                         or CSS color
42578 * @return {Number} the blue value
42579 * @example
42580 * <div>
42581 * <code>
42582 * var c = color(175, 100, 220); // Define color 'c'
42583 * fill(c); // Use color variable 'c' as fill color
42584 * rect(15, 20, 35, 60); // Draw left rectangle
42585 *
42586 * var blueValue = blue(c); // Get blue in 'c'
42587 * print(blueValue); // Prints "220.0"
42588 * fill(0, 0, blueValue); // Use 'blueValue' in new fill
42589 * rect(50, 20, 35, 60); // Draw right rectangle
42590 * </code>
42591 * </div>
42592 *
42593 * @alt
42594 * Left half of canvas light purple and right half a royal blue.
42595 *
42596 */
42597p5.prototype.blue = function(c) {
42598  p5._validateParameters('blue', arguments);
42599  return this.color(c)._getBlue();
42600};
42601
42602/**
42603 * Extracts the HSB brightness value from a color or pixel array.
42604 *
42605 * @method brightness
42606 * @param {p5.Color|Number[]|String} color p5.Color object, color components,
42607 *                                         or CSS color
42608 * @return {Number} the brightness value
42609 * @example
42610 * <div>
42611 * <code>
42612 * noStroke();
42613 * colorMode(HSB, 255);
42614 * var c = color(0, 126, 255);
42615 * fill(c);
42616 * rect(15, 20, 35, 60);
42617 * var value = brightness(c); // Sets 'value' to 255
42618 * fill(value);
42619 * rect(50, 20, 35, 60);
42620 * </code>
42621 * </div>
42622 *
42623 * @alt
42624 * Left half of canvas salmon pink and the right half white.
42625 *
42626 */
42627p5.prototype.brightness = function(c) {
42628  p5._validateParameters('brightness', arguments);
42629  return this.color(c)._getBrightness();
42630};
42631
42632/**
42633 * Creates colors for storing in variables of the color datatype. The
42634 * parameters are interpreted as RGB or HSB values depending on the
42635 * current colorMode(). The default mode is RGB values from 0 to 255
42636 * and, therefore, the function call color(255, 204, 0) will return a
42637 * bright yellow color.
42638 * <br><br>
42639 * Note that if only one value is provided to color(), it will be interpreted
42640 * as a grayscale value. Add a second value, and it will be used for alpha
42641 * transparency. When three values are specified, they are interpreted as
42642 * either RGB or HSB values. Adding a fourth value applies alpha
42643 * transparency.
42644 * <br><br>
42645 * If a single string argument is provided, RGB, RGBA and Hex CSS color
42646 * strings and all named color strings are supported. In this case, an alpha
42647 * number value as a second argument is not supported, the RGBA form should be
42648 * used.
42649 *
42650 * @method color
42651 * @param  {Number}        gray    number specifying value between white
42652 *                                 and black.
42653 * @param  {Number}        [alpha] alpha value relative to current color range
42654 *                                 (default is 0-255)
42655 * @return {p5.Color}              resulting color
42656 *
42657 * @example
42658 * <div>
42659 * <code>
42660 * var c = color(255, 204, 0); // Define color 'c'
42661 * fill(c); // Use color variable 'c' as fill color
42662 * noStroke(); // Don't draw a stroke around shapes
42663 * rect(30, 20, 55, 55); // Draw rectangle
42664 * </code>
42665 * </div>
42666 *
42667 * <div>
42668 * <code>
42669 * var c = color(255, 204, 0); // Define color 'c'
42670 * fill(c); // Use color variable 'c' as fill color
42671 * noStroke(); // Don't draw a stroke around shapes
42672 * ellipse(25, 25, 80, 80); // Draw left circle
42673 *
42674 * // Using only one value with color()
42675 * // generates a grayscale value.
42676 * c = color(65); // Update 'c' with grayscale value
42677 * fill(c); // Use updated 'c' as fill color
42678 * ellipse(75, 75, 80, 80); // Draw right circle
42679 * </code>
42680 * </div>
42681 *
42682 * <div>
42683 * <code>
42684 * // Named SVG & CSS colors may be used,
42685 * var c = color('magenta');
42686 * fill(c); // Use 'c' as fill color
42687 * noStroke(); // Don't draw a stroke around shapes
42688 * rect(20, 20, 60, 60); // Draw rectangle
42689 * </code>
42690 * </div>
42691 *
42692 * <div>
42693 * <code>
42694 * // as can hex color codes:
42695 * noStroke(); // Don't draw a stroke around shapes
42696 * var c = color('#0f0');
42697 * fill(c); // Use 'c' as fill color
42698 * rect(0, 10, 45, 80); // Draw rectangle
42699 *
42700 * c = color('#00ff00');
42701 * fill(c); // Use updated 'c' as fill color
42702 * rect(55, 10, 45, 80); // Draw rectangle
42703 * </code>
42704 * </div>
42705 *
42706 * <div>
42707 * <code>
42708 * // RGB and RGBA color strings are also supported:
42709 * // these all set to the same color (solid blue)
42710 * var c;
42711 * noStroke(); // Don't draw a stroke around shapes
42712 * c = color('rgb(0,0,255)');
42713 * fill(c); // Use 'c' as fill color
42714 * rect(10, 10, 35, 35); // Draw rectangle
42715 *
42716 * c = color('rgb(0%, 0%, 100%)');
42717 * fill(c); // Use updated 'c' as fill color
42718 * rect(55, 10, 35, 35); // Draw rectangle
42719 *
42720 * c = color('rgba(0, 0, 255, 1)');
42721 * fill(c); // Use updated 'c' as fill color
42722 * rect(10, 55, 35, 35); // Draw rectangle
42723 *
42724 * c = color('rgba(0%, 0%, 100%, 1)');
42725 * fill(c); // Use updated 'c' as fill color
42726 * rect(55, 55, 35, 35); // Draw rectangle
42727 * </code>
42728 * </div>
42729 *
42730 * <div>
42731 * <code>
42732 * // HSL color is also supported and can be specified
42733 * // by value
42734 * var c;
42735 * noStroke(); // Don't draw a stroke around shapes
42736 * c = color('hsl(160, 100%, 50%)');
42737 * fill(c); // Use 'c' as fill color
42738 * rect(0, 10, 45, 80); // Draw rectangle
42739 *
42740 * c = color('hsla(160, 100%, 50%, 0.5)');
42741 * fill(c); // Use updated 'c' as fill color
42742 * rect(55, 10, 45, 80); // Draw rectangle
42743 * </code>
42744 * </div>
42745 *
42746 * <div>
42747 * <code>
42748 * // HSB color is also supported and can be specified
42749 * // by value
42750 * var c;
42751 * noStroke(); // Don't draw a stroke around shapes
42752 * c = color('hsb(160, 100%, 50%)');
42753 * fill(c); // Use 'c' as fill color
42754 * rect(0, 10, 45, 80); // Draw rectangle
42755 *
42756 * c = color('hsba(160, 100%, 50%, 0.5)');
42757 * fill(c); // Use updated 'c' as fill color
42758 * rect(55, 10, 45, 80); // Draw rectangle
42759 * </code>
42760 * </div>
42761 *
42762 * <div>
42763 * <code>
42764 * var c; // Declare color 'c'
42765 * noStroke(); // Don't draw a stroke around shapes
42766 *
42767 * // If no colorMode is specified, then the
42768 * // default of RGB with scale of 0-255 is used.
42769 * c = color(50, 55, 100); // Create a color for 'c'
42770 * fill(c); // Use color variable 'c' as fill color
42771 * rect(0, 10, 45, 80); // Draw left rect
42772 *
42773 * colorMode(HSB, 100); // Use HSB with scale of 0-100
42774 * c = color(50, 55, 100); // Update 'c' with new color
42775 * fill(c); // Use updated 'c' as fill color
42776 * rect(55, 10, 45, 80); // Draw right rect
42777 * </code>
42778 * </div>
42779 *
42780 * @alt
42781 * Yellow rect in middle right of canvas, with 55 pixel width and height.
42782 * Yellow ellipse in top left of canvas, black ellipse in bottom right,both 80x80.
42783 * Bright fuschia rect in middle of canvas, 60 pixel width and height.
42784 * Two bright green rects on opposite sides of the canvas, both 45x80.
42785 * Four blue rects in each corner of the canvas, each are 35x35.
42786 * Bright sea green rect on left and darker rect on right of canvas, both 45x80.
42787 * Dark green rect on left and lighter green rect on right of canvas, both 45x80.
42788 * Dark blue rect on left and light teal rect on right of canvas, both 45x80.
42789 *
42790 */
42791/**
42792 * @method color
42793 * @param  {Number}        v1      red or hue value relative to
42794 *                                 the current color range
42795 * @param  {Number}        v2      green or saturation value
42796 *                                 relative to the current color range
42797 * @param  {Number}        v3      blue or brightness value
42798 *                                 relative to the current color range
42799 * @param  {Number}        [alpha]
42800 * @return {p5.Color}
42801 */
42802
42803/**
42804 * @method color
42805 * @param  {String}        value   a color string
42806 * @return {p5.Color}
42807 */
42808/**
42809 * @method color
42810 * @param  {Number[]}      values  an array containing the red,green,blue &
42811 *                                 and alpha components of the color
42812 * @return {p5.Color}
42813 */
42814/**
42815 * @method color
42816 * @param  {p5.Color}     color
42817 * @return {p5.Color}
42818 */
42819
42820p5.prototype.color = function() {
42821  p5._validateParameters('color', arguments);
42822  if (arguments[0] instanceof p5.Color) {
42823    return arguments[0];
42823 // Do nothing if argument is already a color object.
42824  }
42825
42826  var args = arguments[0] instanceof Array ? arguments[0] : arguments;
42827  return new p5.Color(this, args);
42828};
42829
42830/**
42831 * Extracts the green value from a color or pixel array.
42832 *
42833 * @method green
42834 * @param {p5.Color|Number[]|String} color p5.Color object, color components,
42835 *                                         or CSS color
42836 * @return {Number} the green value
42837 * @example
42838 * <div>
42839 * <code>
42840 * var c = color(20, 75, 200); // Define color 'c'
42841 * fill(c); // Use color variable 'c' as fill color
42842 * rect(15, 20, 35, 60); // Draw left rectangle
42843 *
42844 * var greenValue = green(c); // Get green in 'c'
42845 * print(greenValue); // Print "75.0"
42846 * fill(0, greenValue, 0); // Use 'greenValue' in new fill
42847 * rect(50, 20, 35, 60); // Draw right rectangle
42848 * </code>
42849 * </div>
42850 *
42851 * @alt
42852 * blue rect on left and green on right, both with black outlines & 35x60.
42853 *
42854 */
42855
42856p5.prototype.green = function(c) {
42857  p5._validateParameters('green', arguments);
42858  return this.color(c)._getGreen();
42859};
42860
42861/**
42862 * Extracts the hue value from a color or pixel array.
42863 *
42864 * Hue exists in both HSB and HSL. This function will return the
42865 * HSB-normalized hue when supplied with an HSB color object (or when supplied
42866 * with a pixel array while the color mode is HSB), but will default to the
42867 * HSL-normalized hue otherwise. (The values will only be different if the
42868 * maximum hue setting for each system is different.)
42869 *
42870 * @method hue
42871 * @param {p5.Color|Number[]|String} color p5.Color object, color components,
42872 *                                         or CSS color
42873 * @return {Number} the hue
42874 * @example
42875 * <div>
42876 * <code>
42877 * noStroke();
42878 * colorMode(HSB, 255);
42879 * var c = color(0, 126, 255);
42880 * fill(c);
42881 * rect(15, 20, 35, 60);
42882 * var value = hue(c); // Sets 'value' to "0"
42883 * fill(value);
42884 * rect(50, 20, 35, 60);
42885 * </code>
42886 * </div>
42887 *
42888 * @alt
42889 * salmon pink rect on left and black on right, both 35x60.
42890 *
42891 */
42892
42893p5.prototype.hue = function(c) {
42894  p5._validateParameters('hue', arguments);
42895  return this.color(c)._getHue();
42896};
42897
42898/**
42899 * Blends two colors to find a third color somewhere between them. The amt
42900 * parameter is the amount to interpolate between the two values where 0.0
42901 * equal to the first color, 0.1 is very near the first color, 0.5 is halfway
42902 * in between, etc. An amount below 0 will be treated as 0. Likewise, amounts
42903 * above 1 will be capped at 1. This is different from the behavior of lerp(),
42904 * but necessary because otherwise numbers outside the range will produce
42905 * strange and unexpected colors.
42906 * <br><br>
42907 * The way that colours are interpolated depends on the current color mode.
42908 *
42909 * @method lerpColor
42910 * @param  {p5.Color} c1  interpolate from this color
42911 * @param  {p5.Color} c2  interpolate to this color
42912 * @param  {Number}       amt number between 0 and 1
42913 * @return {p5.Color}     interpolated color
42914 * @example
42915 * <div>
42916 * <code>
42917 * colorMode(RGB);
42918 * stroke(255);
42919 * background(51);
42920 * var from = color(218, 165, 32);
42921 * var to = color(72, 61, 139);
42922 * colorMode(RGB); // Try changing to HSB.
42923 * var interA = lerpColor(from, to, 0.33);
42924 * var interB = lerpColor(from, to, 0.66);
42925 * fill(from);
42926 * rect(10, 20, 20, 60);
42927 * fill(interA);
42928 * rect(30, 20, 20, 60);
42929 * fill(interB);
42930 * rect(50, 20, 20, 60);
42931 * fill(to);
42932 * rect(70, 20, 20, 60);
42933 * </code>
42934 * </div>
42935 *
42936 * @alt
42937 * 4 rects one tan, brown, brownish purple, purple, with white outlines & 20x60
42938 *
42939 */
42940
42941p5.prototype.lerpColor = function(c1, c2, amt) {
42942  p5._validateParameters('lerpColor', arguments);
42943  var mode = this._colorMode;
42944  var maxes = this._colorMaxes;
42945  var l0, l1, l2, l3;
42946  var fromArray, toArray;
42947
42948  if (mode === constants.RGB) {
42949    fromArray = c1.levels.map(function(level) {
42950      return level / 255;
42951    });
42952    toArray = c2.levels.map(function(level) {
42953      return level / 255;
42954    });
42955  } else if (mode === constants.HSB) {
42956    c1._getBrightness(); // Cache hsba so it definitely exists.
42957    c2._getBrightness();
42958    fromArray = c1.hsba;
42959    toArray = c2.hsba;
42960  } else if (mode === constants.HSL) {
42961    c1._getLightness();
42961 // Cache hsla so it definitely exists.
42962    c2._getLightness();
42963    fromArray = c1.hsla;
42964    toArray = c2.hsla;
42965  } else {
42966    throw new Error(mode + 'cannot be used for interpolation.');
42967  }
42968
42969  // Prevent extrapolation.
42970  amt = Math.max(Math.min(amt, 1), 0);
42971
42972  // Define lerp here itself if user isn't using math module.
42973  // Maintains the definition as found in math/calculation.js
42974  if (typeof this.lerp === 'undefined') {
42975    this.lerp = function(start, stop, amt) {
42976      return amt * (stop - start) + start;
42977    };
42978  }
42979
42980  // Perform interpolation.
42981  l0 = this.lerp(fromArray[0], toArray[0], amt);
42982  l1 = this.lerp(fromArray[1], toArray[1], amt);
42983  l2 = this.lerp(fromArray[2], toArray[2], amt);
42984  l3 = this.lerp(fromArray[3], toArray[3], amt);
42985
42986  // Scale components.
42987  l0 *= maxes[mode][0];
42988  l1 *= maxes[mode][1];
42989  l2 *= maxes[mode][2];
42990  l3 *= maxes[mode][3];
42991
42992  return this.color(l0, l1, l2, l3);
42993};
42994
42995/**
42996 * Extracts the HSL lightness value from a color or pixel array.
42997 *
42998 * @method lightness
42999 * @param {p5.Color|Number[]|String} color p5.Color object, color components,
43000 *                                         or CSS color
43001 * @return {Number} the lightness
43002 * @example
43003 * <div>
43004 * <code>
43005 * noStroke();
43006 * colorMode(HSL);
43007 * var c = color(156, 100, 50, 1);
43008 * fill(c);
43009 * rect(15, 20, 35, 60);
43010 * var value = lightness(c); // Sets 'value' to 50
43011 * fill(value);
43012 * rect(50, 20, 35, 60);
43013 * </code>
43014 * </div>
43015 *
43016 * @alt
43017 * light pastel green rect on left and dark grey rect on right, both 35x60.
43018 *
43019 */
43020p5.prototype.lightness = function(c) {
43021  p5._validateParameters('lightness', arguments);
43022  return this.color(c)._getLightness();
43023};
43024
43025/**
43026 * Extracts the red value from a color or pixel array.
43027 *
43028 * @method red
43029 * @param {p5.Color|Number[]|String} color p5.Color object, color components,
43030 *                                         or CSS color
43031 * @return {Number} the red value
43032 * @example
43033 * <div>
43034 * <code>
43035 * var c = color(255, 204, 0); // Define color 'c'
43036 * fill(c); // Use color variable 'c' as fill color
43037 * rect(15, 20, 35, 60); // Draw left rectangle
43038 *
43039 * var redValue = red(c); // Get red in 'c'
43040 * print(redValue); // Print "255.0"
43041 * fill(redValue, 0, 0); // Use 'redValue' in new fill
43042 * rect(50, 20, 35, 60); // Draw right rectangle
43043 * </code>
43044 * </div>
43045 *
43046 * <div>
43047 * <code>
43048 * colorMode(RGB, 255);
43049 * var c = color(127, 255, 0);
43050 * colorMode(RGB, 1);
43051 * var myColor = red(c);
43052 * print(myColor);
43053 * </code>
43054 * </div>
43055 *
43056 * @alt
43057 * yellow rect on left and red rect on right, both with black outlines and 35x60.
43058 * grey canvas
43059 */
43060p5.prototype.red = function(c) {
43061  p5._validateParameters('red', arguments);
43062  return this.color(c)._getRed();
43063};
43064
43065/**
43066 * Extracts the saturation value from a color or pixel array.
43067 *
43068 * Saturation is scaled differently in HSB and HSL. This function will return
43069 * the HSB saturation when supplied with an HSB color object (or when supplied
43070 * with a pixel array while the color mode is HSB), but will default to the
43071 * HSL saturation otherwise.
43072 *
43073 * @method saturation
43074 * @param {p5.Color|Number[]|String} color p5.Color object, color components,
43075 *                                         or CSS color
43076 * @return {Number} the saturation value
43077 * @example
43078 * <div>
43079 * <code>
43080 * noStroke();
43081 * colorMode(HSB, 255);
43082 * var c = color(0, 126, 255);
43083 * fill(c);
43084 * rect(15, 20, 35, 60);
43085 * var value = saturation(c); // Sets 'value' to 126
43086 * fill(value);
43087 * rect(50, 20, 35, 60);
43088 * </code>
43089 * </div>
43090 *
43091 * @alt
43092 *deep pink rect on left and grey rect on right, both 35x60.
43093 *
43094 */
43095
43096p5.prototype.saturation = function(c) {
43097  p5._validateParameters('saturation', arguments);
43098  return this.color(c)._getSaturation();
43099};
43100
43101module.exports = p5;
43102
43103},{"../core/constants":21,"../core/core":22,"../core/error_helpers":25,"./p5.Color":16}],16:[function(_dereq_,module,exports){
43104/**
43105 * @module Color
43106 * @submodule Creating & Reading
43107 * @for p5
43108 * @requires core
43109 * @requires constants
43110 * @requires color_conversion
43111 */
43112
43113'use strict';
43114
43115var p5 = _dereq_('../core/core');
43116var constants = _dereq_('../core/constants');
43117var color_conversion = _dereq_('./color_conversion');
43118
43119/**
43120 * Each color stores the color mode and level maxes that applied at the
43121 * time of its construction. These are used to interpret the input arguments
43122 * (at construction and later for that instance of color) and to format the
43123 * output e.g. when saturation() is requested.
43124 *
43125 * Internally we store an array representing the ideal RGBA values in floating
43126 * point form, normalized from 0 to 1. From this we calculate the closest
43127 * screen color (RGBA levels from 0 to 255) and expose this to the renderer.
43128 *
43129 * We also cache normalized, floating point components of the color in various
43130 * representations as they are calculated. This is done to prevent repeating a
43131 * conversion that has already been performed.
43132 *
43133 * @class p5.Color
43134 */
43135p5.Color = function(pInst, vals) {
43136  // Record color mode and maxes at time of construction.
43137  this._storeModeAndMaxes(pInst._colorMode, pInst._colorMaxes);
43138
43139  // Calculate normalized RGBA values.
43140  if (
43141    this.mode !== constants.RGB &&
43142    this.mode !== constants.HSL &&
43143    this.mode !== constants.HSB
43144  ) {
43145    throw new Error(this.mode + ' is an invalid colorMode.');
43146  } else {
43147    this._array = p5.Color._parseInputs.apply(this, vals);
43148  }
43149
43150  // Expose closest screen color.
43151  this._calculateLevels();
43152  return this;
43153};
43154
43155/**
43156 * This function returns the color formatted as a string. This can be useful
43157 * for debugging, or for using p5.js with other libraries.
43158 * @method toString
43159 * @param {String} [format] How the color string will be formatted.
43160 * Leaving this empty formats the string as rgba(r, g, b, a).
43161 * '#rgb' '#rgba' '#rrggbb' and '#rrggbbaa' format as hexadecimal color codes.
43162 * 'rgb' 'hsb' and 'hsl' return the color formatted in the specified color mode.
43163 * 'rgba' 'hsba' and 'hsla' are the same as above but with alpha channels.
43164 * 'rgb%' 'hsb%' 'hsl%' 'rgba%' 'hsba%' and 'hsla%' format as percentages.
43165 * @return {String} the formatted string
43166 * @example
43167 * <div>
43168 * <code>
43169 * var myColor;
43170 * function setup() {
43171 *   createCanvas(200, 200);
43172 *   stroke(255);
43173 *   myColor = color(100, 100, 250);
43174 *   fill(myColor);
43175 * }
43176 *
43177 * function draw() {
43178 *   text(myColor.toString(), 10, 10);
43179 *   text(myColor.toString('#rrggbb'), 10, 95);
43180 *   text(myColor.toString('rgba%'), 10, 180);
43181 * }
43182 * </code>
43183 * </div>
43184 *
43185 * @alt
43186 * canvas with text representation of color
43187 */
43188p5.Color.prototype.toString = function(format) {
43189  if (!this.hsba) this.hsba = color_conversion._rgbaToHSBA(this._array);
43190  if (!this.hsla) this.hsla = color_conversion._rgbaToHSLA(this._array);
43191
43192  var a = this.levels;
43193  var f = this._array;
43194  var alpha = f[3]; // String representation uses normalized alpha
43195
43196  switch (format) {
43197    case '#rrggbb':
43198      return '#'.concat(
43199        a[0] < 16 ? '0'.concat(a[0].toString(16)) : a[0].toString(16),
43200        a[1] < 16 ? '0'.concat(a[1].toString(16)) : a[1].toString(16),
43201        a[2] < 16 ? '0'.concat(a[2].toString(16)) : a[2].toString(16)
43202      );
43203
43204    case '#rrggbbaa':
43205      return '#'.concat(
43206        a[0] < 16 ? '0'.concat(a[0].toString(16)) : a[0].toString(16),
43207        a[1] < 16 ? '0'.concat(a[1].toString(16)) : a[1].toString(16),
43208        a[2] < 16 ? '0'.concat(a[2].toString(16)) : a[2].toString(16),
43209        a[3] < 16 ? '0'.concat(a[2].toString(16)) : a[3].toString(16)
43210      );
43211
43212    case '#rgb':
43213      return '#'.concat(
43214        Math.round(f[0] * 15).toString(16),
43215        Math.round(f[1] * 15).toString(16),
43216        Math.round(f[2] * 15).toString(16)
43217      );
43218
43219    case '#rgba':
43220      return '#'.concat(
43221        Math.round(f[0] * 15).toString(16),
43222        Math.round(f[1] * 15).toString(16),
43223        Math.round(f[2] * 15).toString(16),
43224        Math.round(f[3] * 15).toString(16)
43225      );
43226
43227    case 'rgb':
43228      return 'rgb('.concat(a[0], ', ', a[1], ', ', a[2], ')');
43229
43230    case 'rgb%':
43231      return 'rgb('.concat(
43232        (100 * f[0]).toPrecision(3),
43233        '%, ',
43234        (100 * f[1]).toPrecision(3),
43235        '%, ',
43236        (100 * f[2]).toPrecision(3),
43237        '%)'
43238      );
43239
43240    case 'rgba%':
43241      return 'rgba('.concat(
43242        (100 * f[0]).toPrecision(3),
43243        '%, ',
43244        (100 * f[1]).toPrecision(3),
43245        '%, ',
43246        (100 * f[2]).toPrecision(3),
43247        '%, ',
43248        (100 * f[3]).toPrecision(3),
43249        '%)'
43250      );
43251
43252    case 'hsb':
43253    case 'hsv':
43254      return 'hsb('.concat(
43255        this.hsba[0] * this.maxes[constants.HSB][0],
43256        ', ',
43257        this.hsba[1] * this.maxes[constants.HSB][1],
43258        ', ',
43259        this.hsba[2] * this.maxes[constants.HSB][2],
43260        ')'
43261      );
43262
43263    case 'hsb%':
43264    case 'hsv%':
43265      return 'hsb('.concat(
43266        (100 * this.hsba[0]).toPrecision(3),
43267        '%, ',
43268        (100 * this.hsba[1]).toPrecision(3),
43269        '%, ',
43270        (100 * this.hsba[2]).toPrecision(3),
43271        '%)'
43272      );
43273
43274    case 'hsba':
43275    case 'hsva':
43276      return 'hsba('.concat(
43277        this.hsba[0] * this.maxes[constants.HSB][0],
43278        ', ',
43279        this.hsba[1] * this.maxes[constants.HSB][1],
43280        ', ',
43281        this.hsba[2] * this.maxes[constants.HSB][2],
43282        ', ',
43283        alpha,
43284        ')'
43285      );
43286
43287    case 'hsba%':
43288    case 'hsva%':
43289      return 'hsba('.concat(
43290        (100 * this.hsba[0]).toPrecision(3),
43291        '%, ',
43292        (100 * this.hsba[1]).toPrecision(3),
43293        '%, ',
43294        (100 * this.hsba[2]).toPrecision(3),
43295        '%, ',
43296        (100 * alpha).toPrecision(3),
43297        '%)'
43298      );
43299
43300    case 'hsl':
43301      return 'hsl('.concat(
43302        this.hsla[0] * this.maxes[constants.HSL][0],
43303        ', ',
43304        this.hsla[1] * this.maxes[constants.HSL][1],
43305        ', ',
43306        this.hsla[2] * this.maxes[constants.HSL][2],
43307        ')'
43308      );
43309
43310    case 'hsl%':
43311      return 'hsl('.concat(
43312        (100 * this.hsla[0]).toPrecision(3),
43313        '%, ',
43314        (100 * this.hsla[1]).toPrecision(3),
43315        '%, ',
43316        (100 * this.hsla[2]).toPrecision(3),
43317        '%)'
43318      );
43319
43320    case 'hsla':
43321      return 'hsla('.concat(
43322        this.hsla[0] * this.maxes[constants.HSL][0],
43323        ', ',
43324        this.hsla[1] * this.maxes[constants.HSL][1],
43325        ', ',
43326        this.hsla[2] * this.maxes[constants.HSL][2],
43327        ', ',
43328        alpha,
43329        ')'
43330      );
43331
43332    case 'hsla%':
43333      return 'hsl('.concat(
43334        (100 * this.hsla[0]).toPrecision(3),
43335        '%, ',
43336        (100 * this.hsla[1]).toPrecision(3),
43337        '%, ',
43338        (100 * this.hsla[2]).toPrecision(3),
43339        '%, ',
43340        (100 * alpha).toPrecision(3),
43341        '%)'
43342      );
43343
43344    case 'rgba':
43345    default:
43346      return 'rgba(' + a[0] + ',' + a[1] + ',' + a[2] + ',' + alpha + ')';
43347  }
43348};
43349
43350/**
43351 * @method setRed
43352 * @param {Number} red the new red value
43353 * @example
43354 * <div>
43355 * <code>
43356 * var backgroundColor;
43357 *
43358 * function setup() {
43359 *   backgroundColor = color(100, 50, 150);
43360 * }
43361 *
43362 * function draw() {
43363 *   backgroundColor.setRed(128 + 128 * sin(millis() / 1000));
43364 *   background(backgroundColor);
43365 * }
43366 * </code>
43367 * </div>
43368 *
43369 * @alt
43370 * canvas with gradually changing background color
43371 */
43372p5.Color.prototype.setRed = function(new_red) {
43373  this._array[0] = new_red / this.maxes[constants.RGB][0];
43374  this._calculateLevels();
43375};
43376
43377/**
43378 * @method setGreen
43379 * @param {Number} green the new green value
43380 * @example
43381 * <div>
43382 * <code>
43383 * var backgroundColor;
43384 *
43385 * function setup() {
43386 *   backgroundColor = color(100, 50, 150);
43387 * }
43388 *
43389 * function draw() {
43390 *   backgroundColor.setGreen(128 + 128 * sin(millis() / 1000));
43391 *   background(backgroundColor);
43392 * }
43393 * </code>
43394 * </div>
43395 *
43396 * @alt
43397 * canvas with gradually changing background color
43398 **/
43399p5.Color.prototype.setGreen = function(new_green) {
43400  this._array[1] = new_green / this.maxes[constants.RGB][1];
43401  this._calculateLevels();
43402};
43403
43404/**
43405 * @method setBlue
43406 * @param {Number} blue the new blue value
43407 * @example
43408 * <div>
43409 * <code>
43410 * var backgroundColor;
43411 *
43412 * function setup() {
43413 *   backgroundColor = color(100, 50, 150);
43414 * }
43415 *
43416 * function draw() {
43417 *   backgroundColor.setBlue(128 + 128 * sin(millis() / 1000));
43418 *   background(backgroundColor);
43419 * }
43420 * </code>
43421 * </div>
43422 *
43423 * @alt
43424 * canvas with gradually changing background color
43425 **/
43426p5.Color.prototype.setBlue = function(new_blue) {
43427  this._array[2] = new_blue / this.maxes[constants.RGB][2];
43428  this._calculateLevels();
43429};
43430
43431/**
43432 * @method setAlpha
43433 * @param {Number} alpha the new alpha value
43434 * @example
43435 * <div>
43436 * <code>
43437 * var squareColor;
43438 *
43439 * function setup() {
43440 *   ellipseMode(CORNERS);
43441 *   strokeWeight(4);
43442 *   squareColor = color(100, 50, 150);
43443 * }
43444 *
43445 * function draw() {
43446 *   background(255);
43447 *
43448 *   noFill();
43449 *   stroke(0);
43450 *   ellipse(10, 10, width - 10, height - 10);
43451 *
43452 *   squareColor.setAlpha(128 + 128 * sin(millis() / 1000));
43453 *   fill(squareColor);
43454 *   noStroke();
43455 *   rect(13, 13, width - 26, height - 26);
43456 * }
43457 * </code>
43458 * </div>
43459 *
43460 * @alt
43461 * circle behind a square with gradually changing opacity
43462 **/
43463p5.Color.prototype.setAlpha = function(new_alpha) {
43464  this._array[3] = new_alpha / this.maxes[this.mode][3];
43465  this._calculateLevels();
43466};
43467
43468// calculates and stores the closest screen levels
43469p5.Color.prototype._calculateLevels = function() {
43470  this.levels = this._array.map(function(level) {
43471    return Math.round(level * 255);
43472  });
43473};
43474
43475p5.Color.prototype._getAlpha = function() {
43476  return this._array[3] * this.maxes[this.mode][3];
43477};
43478
43479// stores the color mode and maxes in this instance of Color
43480// for later use (by _parseInputs())
43481p5.Color.prototype._storeModeAndMaxes = function(new_mode, new_maxes) {
43482  this.mode = new_mode;
43483  this.maxes = new_maxes;
43484};
43485
43486p5.Color.prototype._getMode = function() {
43487  return this.mode;
43488};
43489
43490p5.Color.prototype._getMaxes = function() {
43491  return this.maxes;
43492};
43493
43494p5.Color.prototype._getBlue = function() {
43495  return this._array[2] * this.maxes[constants.RGB][2];
43496};
43497
43498p5.Color.prototype._getBrightness = function() {
43499  if (!this.hsba) {
43500    this.hsba = color_conversion._rgbaToHSBA(this._array);
43501  }
43502  return this.hsba[2] * this.maxes[constants.HSB][2];
43503};
43504
43505p5.Color.prototype._getGreen = function() {
43506  return this._array[1] * this.maxes[constants.RGB][1];
43507};
43508
43509/**
43510 * Hue is the same in HSB and HSL, but the maximum value may be different.
43511 * This function will return the HSB-normalized saturation when supplied with
43512 * an HSB color object, but will default to the HSL-normalized saturation
43513 * otherwise.
43514 */
43515p5.Color.prototype._getHue = function() {
43516  if (this.mode === constants.HSB) {
43517    if (!this.hsba) {
43518      this.hsba = color_conversion._rgbaToHSBA(this._array);
43519    }
43520    return this.hsba[0] * this.maxes[constants.HSB][0];
43521  } else {
43522    if (!this.hsla) {
43523      this.hsla = color_conversion._rgbaToHSLA(this._array);
43524    }
43525    return this.hsla[0] * this.maxes[constants.HSL][0];
43526  }
43527};
43528
43529p5.Color.prototype._getLightness = function() {
43530  if (!this.hsla) {
43531    this.hsla = color_conversion._rgbaToHSLA(this._array);
43532  }
43533  return this.hsla[2] * this.maxes[constants.HSL][2];
43534};
43535
43536p5.Color.prototype._getRed = function() {
43537  return this._array[0] * this.maxes[constants.RGB][0];
43538};
43539
43540/**
43541 * Saturation is scaled differently in HSB and HSL. This function will return
43542 * the HSB saturation when supplied with an HSB color object, but will default
43543 * to the HSL saturation otherwise.
43544 */
43545p5.Color.prototype._getSaturation = function() {
43546  if (this.mode === constants.HSB) {
43547    if (!this.hsba) {
43548      this.hsba = color_conversion._rgbaToHSBA(this._array);
43549    }
43550    return this.hsba[1] * this.maxes[constants.HSB][1];
43551  } else {
43552    if (!this.hsla) {
43553      this.hsla = color_conversion._rgbaToHSLA(this._array);
43554    }
43555    return this.hsla[1] * this.maxes[constants.HSL][1];
43556  }
43557};
43558
43559/**
43560 * CSS named colors.
43561 */
43562var namedColors = {
43563  aliceblue: '#f0f8ff',
43564  antiquewhite: '#faebd7',
43565  aqua: '#00ffff',
43566  aquamarine: '#7fffd4',
43567  azure: '#f0ffff',
43568  beige: '#f5f5dc',
43569  bisque: '#ffe4c4',
43570  black: '#000000',
43571  blanchedalmond: '#ffebcd',
43572  blue: '#0000ff',
43573  blueviolet: '#8a2be2',
43574  brown: '#a52a2a',
43575  burlywood: '#deb887',
43576  cadetblue: '#5f9ea0',
43577  chartreuse: '#7fff00',
43578  chocolate: '#d2691e',
43579  coral: '#ff7f50',
43580  cornflowerblue: '#6495ed',
43581  cornsilk: '#fff8dc',
43582  crimson: '#dc143c',
43583  cyan: '#00ffff',
43584  darkblue: '#00008b',
43585  darkcyan: '#008b8b',
43586  darkgoldenrod: '#b8860b',
43587  darkgray: '#a9a9a9',
43588  darkgreen: '#006400',
43589  darkgrey: '#a9a9a9',
43590  darkkhaki: '#bdb76b',
43591  darkmagenta: '#8b008b',
43592  darkolivegreen: '#556b2f',
43593  darkorange: '#ff8c00',
43594  darkorchid: '#9932cc',
43595  darkred: '#8b0000',
43596  darksalmon: '#e9967a',
43597  darkseagreen: '#8fbc8f',
43598  darkslateblue: '#483d8b',
43599  darkslategray: '#2f4f4f',
43600  darkslategrey: '#2f4f4f',
43601  darkturquoise: '#00ced1',
43602  darkviolet: '#9400d3',
43603  deeppink: '#ff1493',
43604  deepskyblue: '#00bfff',
43605  dimgray: '#696969',
43606  dimgrey: '#696969',
43607  dodgerblue: '#1e90ff',
43608  firebrick: '#b22222',
43609  floralwhite: '#fffaf0',
43610  forestgreen: '#228b22',
43611  fuchsia: '#ff00ff',
43612  gainsboro: '#dcdcdc',
43613  ghostwhite: '#f8f8ff',
43614  gold: '#ffd700',
43615  goldenrod: '#daa520',
43616  gray: '#808080',
43617  green: '#008000',
43618  greenyellow: '#adff2f',
43619  grey: '#808080',
43620  honeydew: '#f0fff0',
43621  hotpink: '#ff69b4',
43622  indianred: '#cd5c5c',
43623  indigo: '#4b0082',
43624  ivory: '#fffff0',
43625  khaki: '#f0e68c',
43626  lavender: '#e6e6fa',
43627  lavenderblush: '#fff0f5',
43628  lawngreen: '#7cfc00',
43629  lemonchiffon: '#fffacd',
43630  lightblue: '#add8e6',
43631  lightcoral: '#f08080',
43632  lightcyan: '#e0ffff',
43633  lightgoldenrodyellow: '#fafad2',
43634  lightgray: '#d3d3d3',
43635  lightgreen: '#90ee90',
43636  lightgrey: '#d3d3d3',
43637  lightpink: '#ffb6c1',
43638  lightsalmon: '#ffa07a',
43639  lightseagreen: '#20b2aa',
43640  lightskyblue: '#87cefa',
43641  lightslategray: '#778899',
43642  lightslategrey: '#778899',
43643  lightsteelblue: '#b0c4de',
43644  lightyellow: '#ffffe0',
43645  lime: '#00ff00',
43646  limegreen: '#32cd32',
43647  linen: '#faf0e6',
43648  magenta: '#ff00ff',
43649  maroon: '#800000',
43650  mediumaquamarine: '#66cdaa',
43651  mediumblue: '#0000cd',
43652  mediumorchid: '#ba55d3',
43653  mediumpurple: '#9370db',
43654  mediumseagreen: '#3cb371',
43655  mediumslateblue: '#7b68ee',
43656  mediumspringgreen: '#00fa9a',
43657  mediumturquoise: '#48d1cc',
43658  mediumvioletred: '#c71585',
43659  midnightblue: '#191970',
43660  mintcream: '#f5fffa',
43661  mistyrose: '#ffe4e1',
43662  moccasin: '#ffe4b5',
43663  navajowhite: '#ffdead',
43664  navy: '#000080',
43665  oldlace: '#fdf5e6',
43666  olive: '#808000',
43667  olivedrab: '#6b8e23',
43668  orange: '#ffa500',
43669  orangered: '#ff4500',
43670  orchid: '#da70d6',
43671  palegoldenrod: '#eee8aa',
43672  palegreen: '#98fb98',
43673  paleturquoise: '#afeeee',
43674  palevioletred: '#db7093',
43675  papayawhip: '#ffefd5',
43676  peachpuff: '#ffdab9',
43677  peru: '#cd853f',
43678  pink: '#ffc0cb',
43679  plum: '#dda0dd',
43680  powderblue: '#b0e0e6',
43681  purple: '#800080',
43682  red: '#ff0000',
43683  rosybrown: '#bc8f8f',
43684  royalblue: '#4169e1',
43685  saddlebrown: '#8b4513',
43686  salmon: '#fa8072',
43687  sandybrown: '#f4a460',
43688  seagreen: '#2e8b57',
43689  seashell: '#fff5ee',
43690  sienna: '#a0522d',
43691  silver: '#c0c0c0',
43692  skyblue: '#87ceeb',
43693  slateblue: '#6a5acd',
43694  slategray: '#708090',
43695  slategrey: '#708090',
43696  snow: '#fffafa',
43697  springgreen: '#00ff7f',
43698  steelblue: '#4682b4',
43699  tan: '#d2b48c',
43700  teal: '#008080',
43701  thistle: '#d8bfd8',
43702  tomato: '#ff6347',
43703  turquoise: '#40e0d0',
43704  violet: '#ee82ee',
43705  wheat: '#f5deb3',
43706  white: '#ffffff',
43707  whitesmoke: '#f5f5f5',
43708  yellow: '#ffff00',
43709  yellowgreen: '#9acd32'
43710};
43711
43712/**
43713 * These regular expressions are used to build up the patterns for matching
43714 * viable CSS color strings: fragmenting the regexes in this way increases the
43715 * legibility and comprehensibility of the code.
43716 *
43717 * Note that RGB values of .9 are not parsed by IE, but are supported here for
43718 * color string consistency.
43719 */
43720var WHITESPACE = /\s*/; // Match zero or more whitespace characters.
43721var INTEGER = /(\d{1,3})/; // Match integers: 79, 255, etc.
43722var DECIMAL = /((?:\d+(?:\.\d+)?)|(?:\.\d+))/; // Match 129.6, 79, .9, etc.
43723var PERCENT = new RegExp(DECIMAL.source + '%'); // Match 12.9%, 79%, .9%, etc.
43724
43725/**
43726 * Full color string patterns. The capture groups are necessary.
43727 */
43728var colorPatterns = {
43729  // Match colors in format #XXX, e.g. #416.
43730  HEX3: /^#([a-f0-9])([a-f0-9])([a-f0-9])$/i,
43731
43732  // Match colors in format #XXXX, e.g. #5123.
43733  HEX4: /^#([a-f0-9])([a-f0-9])([a-f0-9])([a-f0-9])$/i,
43734
43735  // Match colors in format #XXXXXX, e.g. #b4d455.
43736  HEX6: /^#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})$/i,
43737
43738  // Match colors in format #XXXXXXXX, e.g. #b4d45535.
43739  HEX8: /^#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})$/i,
43740
43741  // Match colors in format rgb(R, G, B), e.g. rgb(255, 0, 128).
43742  RGB: new RegExp(
43743    [
43744      '^rgb\\(',
43745      INTEGER.source,
43746      ',',
43747      INTEGER.source,
43748      ',',
43749      INTEGER.source,
43750      '\\)$'
43751    ].join(WHITESPACE.source),
43752    'i'
43753  ),
43754
43755  // Match colors in format rgb(R%, G%, B%), e.g. rgb(100%, 0%, 28.9%).
43756  RGB_PERCENT: new RegExp(
43757    [
43758      '^rgb\\(',
43759      PERCENT.source,
43760      ',',
43761      PERCENT.source,
43762      ',',
43763      PERCENT.source,
43764      '\\)$'
43765    ].join(WHITESPACE.source),
43766    'i'
43767  ),
43768
43769  // Match colors in format rgb(R, G, B, A), e.g. rgb(255, 0, 128, 0.25).
43770  RGBA: new RegExp(
43771    [
43772      '^rgba\\(',
43773      INTEGER.source,
43774      ',',
43775      INTEGER.source,
43776      ',',
43777      INTEGER.source,
43778      ',',
43779      DECIMAL.source,
43780      '\\)$'
43781    ].join(WHITESPACE.source),
43782    'i'
43783  ),
43784
43785  // Match colors in format rgb(R%, G%, B%, A), e.g. rgb(100%, 0%, 28.9%, 0.5).
43786  RGBA_PERCENT: new RegExp(
43787    [
43788      '^rgba\\(',
43789      PERCENT.source,
43790      ',',
43791      PERCENT.source,
43792      ',',
43793      PERCENT.source,
43794      ',',
43795      DECIMAL.source,
43796      '\\)$'
43797    ].join(WHITESPACE.source),
43798    'i'
43799  ),
43800
43801  // Match colors in format hsla(H, S%, L%), e.g. hsl(100, 40%, 28.9%).
43802  HSL: new RegExp(
43803    [
43804      '^hsl\\(',
43805      INTEGER.source,
43806      ',',
43807      PERCENT.source,
43808      ',',
43809      PERCENT.source,
43810      '\\)$'
43811    ].join(WHITESPACE.source),
43812    'i'
43813  ),
43814
43815  // Match colors in format hsla(H, S%, L%, A), e.g. hsla(100, 40%, 28.9%, 0.5).
43816  HSLA: new RegExp(
43817    [
43818      '^hsla\\(',
43819      INTEGER.source,
43820      ',',
43821      PERCENT.source,
43822      ',',
43823      PERCENT.source,
43824      ',',
43825      DECIMAL.source,
43826      '\\)$'
43827    ].join(WHITESPACE.source),
43828    'i'
43829  ),
43830
43831  // Match colors in format hsb(H, S%, B%), e.g. hsb(100, 40%, 28.9%).
43832  HSB: new RegExp(
43833    [
43834      '^hsb\\(',
43835      INTEGER.source,
43836      ',',
43837      PERCENT.source,
43838      ',',
43839      PERCENT.source,
43840      '\\)$'
43841    ].join(WHITESPACE.source),
43842    'i'
43843  ),
43844
43845  // Match colors in format hsba(H, S%, B%, A), e.g. hsba(100, 40%, 28.9%, 0.5).
43846  HSBA: new RegExp(
43847    [
43848      '^hsba\\(',
43849      INTEGER.source,
43850      ',',
43851      PERCENT.source,
43852      ',',
43853      PERCENT.source,
43854      ',',
43855      DECIMAL.source,
43856      '\\)$'
43857    ].join(WHITESPACE.source),
43858    'i'
43859  )
43860};
43861
43862/**
43863 * For a number of different inputs, returns a color formatted as [r, g, b, a]
43864 * arrays, with each component normalized between 0 and 1.
43865 *
43866 * @private
43867 * @param {Array} [...args] An 'array-like' object that represents a list of
43868 *                          arguments
43869 * @return {Number[]}       a color formatted as [r, g, b, a]
43870 *                          Example:
43871 *                          input        ==> output
43872 *                          g            ==> [g, g, g, 255]
43873 *                          g,a          ==> [g, g, g, a]
43874 *                          r, g, b      ==> [r, g, b, 255]
43875 *                          r, g, b, a   ==> [r, g, b, a]
43876 *                          [g]          ==> [g, g, g, 255]
43877 *                          [g, a]       ==> [g, g, g, a]
43878 *                          [r, g, b]    ==> [r, g, b, 255]
43879 *                          [r, g, b, a] ==> [r, g, b, a]
43880 * @example
43881 * <div>
43882 * <code>
43883 * // todo
43884 * </code>
43885 * </div>
43886 *
43887 * @alt
43888 * //todo
43889 *
43890 */
43891p5.Color._parseInputs = function(r, g, b, a) {
43892  var numArgs = arguments.length;
43893  var mode = this.mode;
43894  var maxes = this.maxes;
43895  var results = [];
43896
43897  if (numArgs >= 3) {
43898    // Argument is a list of component values.
43899
43900    results[0] = r / maxes[mode][0];
43901    results[1] = g / maxes[mode][1];
43902    results[2] = b / maxes[mode][2];
43903
43904    // Alpha may be undefined, so default it to 100%.
43905    if (typeof a === 'number') {
43906      results[3] = a / maxes[mode][3];
43907    } else {
43908      results[3] = 1;
43909    }
43910
43911    // Constrain components to the range [0,1].
43912    results = results.map(function(value) {
43913      return Math.max(Math.min(value, 1), 0);
43914    });
43915
43916    // Convert to RGBA and return.
43917    if (mode === constants.HSL) {
43918      return color_conversion._hslaToRGBA(results);
43919    } else if (mode === constants.HSB) {
43920      return color_conversion._hsbaToRGBA(results);
43921    } else {
43922      return results;
43923    }
43924  } else if (numArgs === 1 && typeof r === 'string') {
43925    var str = r.trim().toLowerCase();
43926
43927    // Return if string is a named colour.
43928    if (namedColors[str]) {
43929      return p5.Color._parseInputs.call(this, namedColors[str]);
43930    }
43931
43932    // Try RGBA pattern matching.
43933    if (colorPatterns.HEX3.test(str)) {
43934      // #rgb
43935      results = colorPatterns.HEX3.exec(str)
43936        .slice(1)
43937        .map(function(color) {
43938          return parseInt(color + color, 16) / 255;
43939        });
43940      results[3] = 1;
43941      return results;
43942    } else if (colorPatterns.HEX6.test(str)) {
43943      // #rrggbb
43944      results = colorPatterns.HEX6.exec(str)
43945        .slice(1)
43946        .map(function(color) {
43947          return parseInt(color, 16) / 255;
43948        });
43949      results[3] = 1;
43950      return results;
43951    } else if (colorPatterns.HEX4.test(str)) {
43952      // #rgba
43953      results = colorPatterns.HEX4.exec(str)
43954        .slice(1)
43955        .map(function(color) {
43956          return parseInt(color + color, 16) / 255;
43957        });
43958      return results;
43959    } else if (colorPatterns.HEX8.test(str)) {
43960      // #rrggbbaa
43961      results = colorPatterns.HEX8.exec(str)
43962        .slice(1)
43963        .map(function(color) {
43964          return parseInt(color, 16) / 255;
43965        });
43966      return results;
43967    } else if (colorPatterns.RGB.test(str)) {
43968      // rgb(R,G,B)
43969      results = colorPatterns.RGB.exec(str)
43970        .slice(1)
43971        .map(function(color) {
43972          return color / 255;
43973        });
43974      results[3] = 1;
43975      return results;
43976    } else if (colorPatterns.RGB_PERCENT.test(str)) {
43977      // rgb(R%,G%,B%)
43978      results = colorPatterns.RGB_PERCENT.exec(str)
43979        .slice(1)
43980        .map(function(color) {
43981          return parseFloat(color) / 100;
43982        });
43983      results[3] = 1;
43984      return results;
43985    } else if (colorPatterns.RGBA.test(str)) {
43986      // rgba(R,G,B,A)
43987      results = colorPatterns.RGBA.exec(str)
43988        .slice(1)
43989        .map(function(color, idx) {
43990          if (idx === 3) {
43991            return parseFloat(color);
43992          }
43993          return color / 255;
43994        });
43995      return results;
43996    } else if (colorPatterns.RGBA_PERCENT.test(str)) {
43997      // rgba(R%,G%,B%,A%)
43998      results = colorPatterns.RGBA_PERCENT.exec(str)
43999        .slice(1)
44000        .map(function(color, idx) {
44001          if (idx === 3) {
44002            return parseFloat(color);
44003          }
44004          return parseFloat(color) / 100;
44005        });
44006      return results;
44007    }
44008
44009    // Try HSLA pattern matching.
44010    if (colorPatterns.HSL.test(str)) {
44011      // hsl(H,S,L)
44012      results = colorPatterns.HSL.exec(str)
44013        .slice(1)
44014        .map(function(color, idx) {
44015          if (idx === 0) {
44016            return parseInt(color, 10) / 360;
44017          }
44018          return parseInt(color, 10) / 100;
44019        });
44020      results[3] = 1;
44021    } else if (colorPatterns.HSLA.test(str)) {
44022      // hsla(H,S,L,A)
44023      results = colorPatterns.HSLA.exec(str)
44024        .slice(1)
44025        .map(function(color, idx) {
44026          if (idx === 0) {
44027            return parseInt(color, 10) / 360;
44028          } else if (idx === 3) {
44029            return parseFloat(color);
44030          }
44031          return parseInt(color, 10) / 100;
44032        });
44033    }
44034    results = results.map(function(value) {
44035      return Math.max(Math.min(value, 1), 0);
44036    });
44037    if (results.length) {
44038      return color_conversion._hslaToRGBA(results);
44039    }
44040
44041    // Try HSBA pattern matching.
44042    if (colorPatterns.HSB.test(str)) {
44043      // hsb(H,S,B)
44044      results = colorPatterns.HSB.exec(str)
44045        .slice(1)
44046        .map(function(color, idx) {
44047          if (idx === 0) {
44048            return parseInt(color, 10) / 360;
44049          }
44050          return parseInt(color, 10) / 100;
44051        });
44052      results[3] = 1;
44053    } else if (colorPatterns.HSBA.test(str)) {
44054      // hsba(H,S,B,A)
44055      results = colorPatterns.HSBA.exec(str)
44056        .slice(1)
44057        .map(function(color, idx) {
44058          if (idx === 0) {
44059            return parseInt(color, 10) / 360;
44060          } else if (idx === 3) {
44061            return parseFloat(color);
44062          }
44063          return parseInt(color, 10) / 100;
44064        });
44065    }
44066    results = results.map(function(value) {
44067      return Math.max(Math.min(value, 1), 0);
44068    });
44069
44070    if (results.length) {
44071      return color_conversion._hsbaToRGBA(results);
44072    }
44073
44074    // Input did not match any CSS color pattern: default to white.
44075    results = [1, 1, 1, 1];
44076  } else if ((numArgs === 1 || numArgs === 2) && typeof r === 'number') {
44077    // 'Grayscale' mode.
44078
44079    /**
44080     * For HSB and HSL, interpret the gray level as a brightness/lightness
44081     * value (they are equivalent when chroma is zero). For RGB, normalize the
44082     * gray level according to the blue maximum.
44083     */
44084    results[0] = r / maxes[mode][2];
44085    results[1] = r / maxes[mode][2];
44086    results[2] = r / maxes[mode][2];
44087
44088    // Alpha may be undefined, so default it to 100%.
44089    if (typeof g === 'number') {
44090      results[3] = g / maxes[mode][3];
44091    } else {
44092      results[3] = 1;
44093    }
44094
44095    // Constrain components to the range [0,1].
44096    results = results.map(function(value) {
44097      return Math.max(Math.min(value, 1), 0);
44098    });
44099  } else {
44100    throw new Error(arguments + 'is not a valid color representation.');
44101  }
44102
44103  return results;
44104};
44105
44106module.exports = p5.Color;
44107
44108},{"../core/constants":21,"../core/core":22,"./color_conversion":14}],17:[function(_dereq_,module,exports){
44109/**
44110 * @module Color
44111 * @submodule Setting
44112 * @for p5
44113 * @requires core
44114 * @requires constants
44115 */
44116
44117'use strict';
44118
44119var p5 = _dereq_('../core/core');
44120var constants = _dereq_('../core/constants');
44121_dereq_('./p5.Color');
44122
44123/**
44124 * The background() function sets the color used for the background of the
44125 * p5.js canvas. The default background is light gray. This function is
44126 * typically used within draw() to clear the display window at the beginning
44127 * of each frame, but it can be used inside setup() to set the background on
44128 * the first frame of animation or if the background need only be set once.
44129 * <br><br>
44130 * The color is either specified in terms of the RGB, HSB, or HSL color
44131 * depending on the current colorMode. (The default color space is RGB, with
44132 * each value in the range from 0 to 255). The alpha range by default is also 0 to 255.
44133 * <br><br>
44134 * If a single string argument is provided, RGB, RGBA and Hex CSS color strings
44135 * and all named color strings are supported. In this case, an alpha number
44136 * value as a second argument is not supported, the RGBA form should be used.
44137 * <br><br>
44138 * A p5.Color object can also be provided to set the background color.
44139 * <br><br>
44140 * A p5.Image can also be provided to set the background image.
44141 *
44142 * @method background
44143 * @param {p5.Color} color     any value created by the color() function
44144 * @chainable
44145 *
44146 * @example
44147 * <div>
44148 * <code>
44149 * // Grayscale integer value
44150 * background(51);
44151 * </code>
44152 * </div>
44153 *
44154 * <div>
44155 * <code>
44156 * // R, G & B integer values
44157 * background(255, 204, 0);
44158 * </code>
44159 * </div>
44160 *
44161 * <div>
44162 * <code>
44163 * // H, S & B integer values
44164 * colorMode(HSB);
44165 * background(255, 204, 100);
44166 * </code>
44167 * </div>
44168 *
44169 * <div>
44170 * <code>
44171 * // Named SVG/CSS color string
44172 * background('red');
44173 * </code>
44174 * </div>
44175 *
44176 * <div>
44177 * <code>
44178 * // three-digit hexadecimal RGB notation
44179 * background('#fae');
44180 * </code>
44181 * </div>
44182 *
44183 * <div>
44184 * <code>
44185 * // six-digit hexadecimal RGB notation
44186 * background('#222222');
44187 * </code>
44188 * </div>
44189 *
44190 * <div>
44191 * <code>
44192 * // integer RGB notation
44193 * background('rgb(0,255,0)');
44194 * </code>
44195 * </div>
44196 *
44197 * <div>
44198 * <code>
44199 * // integer RGBA notation
44200 * background('rgba(0,255,0, 0.25)');
44201 * </code>
44202 * </div>
44203 *
44204 * <div>
44205 * <code>
44206 * // percentage RGB notation
44207 * background('rgb(100%,0%,10%)');
44208 * </code>
44209 * </div>
44210 *
44211 * <div>
44212 * <code>
44213 * // percentage RGBA notation
44214 * background('rgba(100%,0%,100%,0.5)');
44215 * </code>
44216 * </div>
44217 *
44218 * <div>
44219 * <code>
44220 * // p5 Color object
44221 * background(color(0, 0, 255));
44222 * </code>
44223 * </div>
44224 *
44225 * @alt
44226 * canvas with darkest charcoal grey background.
44227 * canvas with yellow background.
44228 * canvas with royal blue background.
44229 * canvas with red background.
44230 * canvas with pink background.
44231 * canvas with black background.
44232 * canvas with bright green background.
44233 * canvas with soft green background.
44234 * canvas with red background.
44235 * canvas with light purple background.
44236 * canvas with blue background.
44237 */
44238
44239/**
44240 * @method background
44241 * @param {String} colorstring color string, possible formats include: integer
44242 *                         rgb() or rgba(), percentage rgb() or rgba(),
44243 *                         3-digit hex, 6-digit hex
44244 * @param {Number} [a]         opacity of the background relative to current
44245 *                             color range (default is 0-255)
44246 * @chainable
44247 */
44248
44249/**
44250 * @method background
44251 * @param {Number} gray   specifies a value between white and black
44252 * @param {Number} [a]
44253 * @chainable
44254 */
44255
44256/**
44257 * @method background
44258 * @param {Number} v1     red or hue value (depending on the current color
44259 *                        mode)
44260 * @param {Number} v2     green or saturation value (depending on the current
44261 *                        color mode)
44262 * @param {Number} v3     blue or brightness value (depending on the current
44263 *                        color mode)
44264 * @param  {Number} [a]
44265 * @chainable
44266 */
44267
44268/**
44269 * @method background
44270 * @param  {Number[]}      values  an array containing the red,green,blue &
44271 *                                 and alpha components of the color
44272 * @chainable
44273 */
44274
44275/**
44276 * @method background
44277 * @param {p5.Image} image     image created with loadImage() or createImage(),
44278 *                             to set as background
44279 *                             (must be same size as the sketch window)
44280 * @param  {Number}  [a]
44281 * @chainable
44282 */
44283
44284p5.prototype.background = function() {
44285  if (arguments[0] instanceof p5.Image) {
44286    this.image(arguments[0], 0, 0, this.width, this.height);
44287  } else {
44288    this._renderer.background.apply(this._renderer, arguments);
44289  }
44290  return this;
44291};
44292
44293/**
44294 * Clears the pixels within a buffer. This function only works on p5.Canvas
44295 * objects created with the createCanvas() function; it won't work with the
44296 * main display window. Unlike the main graphics context, pixels in
44297 * additional graphics areas created with createGraphics() can be entirely
44298 * or partially transparent. This function clears everything to make all of
44299 * the pixels 100% transparent.
44300 *
44301 * @method clear
44302 * @chainable
44303 * @example
44304 * <div>
44305 * <code>
44306 * // Clear the screen on mouse press.
44307 * function setup() {
44308 *   createCanvas(100, 100);
44309 * }
44310 *
44311 * function draw() {
44312 *   ellipse(mouseX, mouseY, 20, 20);
44313 * }
44314 *
44315 * function mousePressed() {
44316 *   clear();
44317 * }
44318 * </code>
44319 * </div>
44320 *
44321 * @alt
44322 * 20x20 white ellipses are continually drawn at mouse x and y coordinates.
44323 *
44324 */
44325
44326p5.prototype.clear = function() {
44327  this._renderer.clear();
44328  return this;
44329};
44330
44331/**
44332 * colorMode() changes the way p5.js interprets color data. By default, the
44333 * parameters for fill(), stroke(), background(), and color() are defined by
44334 * values between 0 and 255 using the RGB color model. This is equivalent to
44335 * setting colorMode(RGB, 255). Setting colorMode(HSB) lets you use the HSB
44336 * system instead. By default, this is colorMode(HSB, 360, 100, 100, 1). You
44337 * can also use HSL.
44338 * <br><br>
44339 * Note: existing color objects remember the mode that they were created in,
44340 * so you can change modes as you like without affecting their appearance.
44341 *
44342 *
44343 * @method colorMode
44344 * @param {Constant} mode   either RGB, HSB or HSL, corresponding to
44345 *                          Red/Green/Blue and Hue/Saturation/Brightness
44346 *                          (or Lightness)
44347 * @param {Number}  [max]  range for all values
44348 * @chainable
44349 *
44350 * @example
44351 * <div>
44352 * <code>
44353 * noStroke();
44354 * colorMode(RGB, 100);
44355 * for (var i = 0; i < 100; i++) {
44356 *   for (var j = 0; j < 100; j++) {
44357 *     stroke(i, j, 0);
44358 *     point(i, j);
44359 *   }
44360 * }
44361 * </code>
44362 * </div>
44363 *
44364 * <div>
44365 * <code>
44366 * noStroke();
44367 * colorMode(HSB, 100);
44368 * for (var i = 0; i < 100; i++) {
44369 *   for (var j = 0; j < 100; j++) {
44370 *     stroke(i, j, 100);
44371 *     point(i, j);
44372 *   }
44373 * }
44374 * </code>
44375 * </div>
44376 *
44377 * <div>
44378 * <code>
44379 * colorMode(RGB, 255);
44380 * var c = color(127, 255, 0);
44381 *
44382 * colorMode(RGB, 1);
44383 * var myColor = c._getRed();
44384 * text(myColor, 10, 10, 80, 80);
44385 * </code>
44386 * </div>
44387 *
44388 * <div>
44389 * <code>
44390 * noFill();
44391 * colorMode(RGB, 255, 255, 255, 1);
44392 * background(255);
44393 *
44394 * strokeWeight(4);
44395 * stroke(255, 0, 10, 0.3);
44396 * ellipse(40, 40, 50, 50);
44397 * ellipse(50, 50, 40, 40);
44398 * </code>
44399 * </div>
44400 *
44401 * @alt
44402 *Green to red gradient from bottom L to top R. shading originates from top left.
44403 *Rainbow gradient from left to right. Brightness increasing to white at top.
44404 *unknown image.
44405 *50x50 ellipse at middle L & 40x40 ellipse at center. Transluscent pink outlines.
44406 *
44407 */
44408/**
44409 * @method colorMode
44410 * @param {Constant} mode
44411 * @param {Number} max1     range for the red or hue depending on the
44412 *                              current color mode
44413 * @param {Number} max2     range for the green or saturation depending
44414 *                              on the current color mode
44415 * @param {Number} max3     range for the blue or brightness/lighntess
44416 *                              depending on the current color mode
44417 * @param {Number} [maxA]   range for the alpha
44418 * @chainable
44419 */
44420p5.prototype.colorMode = function(mode, max1, max2, max3, maxA) {
44421  p5._validateParameters('colorMode', arguments);
44422  if (
44423    mode === constants.RGB ||
44424    mode === constants.HSB ||
44425    mode === constants.HSL
44426  ) {
44427    // Set color mode.
44428    this._colorMode = mode;
44429
44430    // Set color maxes.
44431    var maxes = this._colorMaxes[mode];
44432    if (arguments.length === 2) {
44433      maxes[0] = max1; // Red
44434      maxes[1] = max1; // Green
44435      maxes[2] = max1; // Blue
44436      maxes[3] = max1; // Alpha
44437    } else if (arguments.length === 4) {
44438      maxes[0] = max1; // Red
44439      maxes[1] = max2; // Green
44440      maxes[2] = max3; // Blue
44441    } else if (arguments.length === 5) {
44442      maxes[0] = max1; // Red
44443      maxes[1] = max2; // Green
44444      maxes[2] = max3; // Blue
44445      maxes[3] = maxA; // Alpha
44446    }
44447  }
44448
44449  return this;
44450};
44451
44452/**
44453 * Sets the color used to fill shapes. For example, if you run
44454 * fill(204, 102, 0), all subsequent shapes will be filled with orange. This
44455 * color is either specified in terms of the RGB or HSB color depending on
44456 * the current colorMode(). (The default color space is RGB, with each value
44457 * in the range from 0 to 255). The alpha range by default is also 0 to 255.
44458 * <br><br>
44459 * If a single string argument is provided, RGB, RGBA and Hex CSS color strings
44460 * and all named color strings are supported. In this case, an alpha number
44461 * value as a second argument is not supported, the RGBA form should be used.
44462 * <br><br>
44463 * A p5 Color object can also be provided to set the fill color.
44464 *
44465 * @method fill
44466 * @param  {Number}        v1      red or hue value relative to
44467 *                                 the current color range
44468 * @param  {Number}        v2      green or saturation value
44469 *                                 relative to the current color range
44470 * @param  {Number}        v3      blue or brightness value
44471 *                                 relative to the current color range
44472 * @param  {Number}        [alpha]
44473 * @chainable
44474 * @example
44475 * <div>
44476 * <code>
44477 * // Grayscale integer value
44478 * fill(51);
44479 * rect(20, 20, 60, 60);
44480 * </code>
44481 * </div>
44482 *
44483 * <div>
44484 * <code>
44485 * // R, G & B integer values
44486 * fill(255, 204, 0);
44487 * rect(20, 20, 60, 60);
44488 * </code>
44489 * </div>
44490 *
44491 * <div>
44492 * <code>
44493 * // H, S & B integer values
44494 * colorMode(HSB);
44495 * fill(255, 204, 100);
44496 * rect(20, 20, 60, 60);
44497 * </code>
44498 * </div>
44499 *
44500 * <div>
44501 * <code>
44502 * // Named SVG/CSS color string
44503 * fill('red');
44504 * rect(20, 20, 60, 60);
44505 * </code>
44506 * </div>
44507 *
44508 * <div>
44509 * <code>
44510 * // three-digit hexadecimal RGB notation
44511 * fill('#fae');
44512 * rect(20, 20, 60, 60);
44513 * </code>
44514 * </div>
44515 *
44516 * <div>
44517 * <code>
44518 * // six-digit hexadecimal RGB notation
44519 * fill('#222222');
44520 * rect(20, 20, 60, 60);
44521 * </code>
44522 * </div>
44523 *
44524 * <div>
44525 * <code>
44526 * // integer RGB notation
44527 * fill('rgb(0,255,0)');
44528 * rect(20, 20, 60, 60);
44529 * </code>
44530 * </div>
44531 *
44532 * <div>
44533 * <code>
44534 * // integer RGBA notation
44535 * fill('rgba(0,255,0, 0.25)');
44536 * rect(20, 20, 60, 60);
44537 * </code>
44538 * </div>
44539 *
44540 * <div>
44541 * <code>
44542 * // percentage RGB notation
44543 * fill('rgb(100%,0%,10%)');
44544 * rect(20, 20, 60, 60);
44545 * </code>
44546 * </div>
44547 *
44548 * <div>
44549 * <code>
44550 * // percentage RGBA notation
44551 * fill('rgba(100%,0%,100%,0.5)');
44552 * rect(20, 20, 60, 60);
44553 * </code>
44554 * </div>
44555 *
44556 * <div>
44557 * <code>
44558 * // p5 Color object
44559 * fill(color(0, 0, 255));
44560 * rect(20, 20, 60, 60);
44561 * </code>
44562 * </div>
44563 * @alt
44564 * 60x60 dark charcoal grey rect with black outline in center of canvas.
44565 * 60x60 yellow rect with black outline in center of canvas.
44566 * 60x60 royal blue rect with black outline in center of canvas.
44567 * 60x60 red rect with black outline in center of canvas.
44568 * 60x60 pink rect with black outline in center of canvas.
44569 * 60x60 black rect with black outline in center of canvas.
44570 * 60x60 light green rect with black outline in center of canvas.
44571 * 60x60 soft green rect with black outline in center of canvas.
44572 * 60x60 red rect with black outline in center of canvas.
44573 * 60x60 dark fushcia rect with black outline in center of canvas.
44574 * 60x60 blue rect with black outline in center of canvas.
44575 */
44576
44577/**
44578 * @method fill
44579 * @param  {String}        value   a color string
44580 * @chainable
44581 */
44582
44583/**
44584 * @method fill
44585 * @param  {Number}        gray   a gray value
44586 * @param  {Number}        [alpha]
44587 * @chainable
44588 */
44589
44590/**
44591 * @method fill
44592 * @param  {Number[]}      values  an array containing the red,green,blue &
44593 *                                 and alpha components of the color
44594 * @chainable
44595 */
44596
44597/**
44598 * @method fill
44599 * @param  {p5.Color}      color   the fill color
44600 * @chainable
44601 */
44602p5.prototype.fill = function() {
44603  this._renderer._setProperty('_fillSet', true);
44604  this._renderer._setProperty('_doFill', true);
44605  this._renderer.fill.apply(this._renderer, arguments);
44606  return this;
44607};
44608
44609/**
44610 * Disables filling geometry. If both noStroke() and noFill() are called,
44611 * nothing will be drawn to the screen.
44612 *
44613 * @method noFill
44614 * @chainable
44615 * @example
44616 * <div>
44617 * <code>
44618 * rect(15, 10, 55, 55);
44619 * noFill();
44620 * rect(20, 20, 60, 60);
44621 * </code>
44622 * </div>
44623 *
44624 * <div modernizr='webgl'>
44625 * <code>
44626 * function setup() {
44627 *   createCanvas(100, 100, WEBGL);
44628 * }
44629 *
44630 * function draw() {
44631 *   background(0);
44632 *   noFill();
44633 *   stroke(100, 100, 240);
44634 *   rotateX(frameCount * 0.01);
44635 *   rotateY(frameCount * 0.01);
44636 *   box(45, 45, 45);
44637 * }
44638 * </code>
44639 * </div>
44640 *
44641 * @alt
44642 * white rect top middle and noFill rect center. Both 60x60 with black outlines.
44643 * black canvas with purple cube wireframe spinning
44644 */
44645p5.prototype.noFill = function() {
44646  this._renderer._setProperty('_doFill', false);
44647  return this;
44648};
44649
44650/**
44651 * Disables drawing the stroke (outline). If both noStroke() and noFill()
44652 * are called, nothing will be drawn to the screen.
44653 *
44654 * @method noStroke
44655 * @chainable
44656 * @example
44657 * <div>
44658 * <code>
44659 * noStroke();
44660 * rect(20, 20, 60, 60);
44661 * </code>
44662 * </div>
44663 *
44664 * <div modernizr='webgl'>
44665 * <code>
44666 * function setup() {
44667 *   createCanvas(100, 100, WEBGL);
44668 * }
44669 *
44670 * function draw() {
44671 *   background(0);
44672 *   noStroke();
44673 *   fill(240, 150, 150);
44674 *   rotateX(frameCount * 0.01);
44675 *   rotateY(frameCount * 0.01);
44676 *   box(45, 45, 45);
44677 * }
44678 * </code>
44679 * </div>
44680 *
44681 * @alt
44682 * 60x60 white rect at center. no outline.
44683 * black canvas with pink cube spinning
44684 */
44685p5.prototype.noStroke = function() {
44686  this._renderer._setProperty('_doStroke', false);
44687  return this;
44688};
44689
44690/**
44691 * Sets the color used to draw lines and borders around shapes. This color
44692 * is either specified in terms of the RGB or HSB color depending on the
44693 * current colorMode() (the default color space is RGB, with each value in
44694 * the range from 0 to 255). The alpha range by default is also 0 to 255.
44695 * <br><br>
44696 * If a single string argument is provided, RGB, RGBA and Hex CSS color
44697 * strings and all named color strings are supported. In this case, an alpha
44698 * number value as a second argument is not supported, the RGBA form should be
44699 * used.
44700 * <br><br>
44701 * A p5 Color object can also be provided to set the stroke color.
44702 *
44703 *
44704 * @method stroke
44705 * @param  {Number}        v1      red or hue value relative to
44706 *                                 the current color range
44707 * @param  {Number}        v2      green or saturation value
44708 *                                 relative to the current color range
44709 * @param  {Number}        v3      blue or brightness value
44710 *                                 relative to the current color range
44711 * @param  {Number}        [alpha]
44712 * @chainable
44713 *
44714 * @example
44715 * <div>
44716 * <code>
44717 * // Grayscale integer value
44718 * strokeWeight(4);
44719 * stroke(51);
44720 * rect(20, 20, 60, 60);
44721 * </code>
44722 * </div>
44723 *
44724 * <div>
44725 * <code>
44726 * // R, G & B integer values
44727 * stroke(255, 204, 0);
44728 * strokeWeight(4);
44729 * rect(20, 20, 60, 60);
44730 * </code>
44731 * </div>
44732 *
44733 * <div>
44734 * <code>
44735 * // H, S & B integer values
44736 * colorMode(HSB);
44737 * strokeWeight(4);
44738 * stroke(255, 204, 100);
44739 * rect(20, 20, 60, 60);
44740 * </code>
44741 * </div>
44742 *
44743 * <div>
44744 * <code>
44745 * // Named SVG/CSS color string
44746 * stroke('red');
44747 * strokeWeight(4);
44748 * rect(20, 20, 60, 60);
44749 * </code>
44750 * </div>
44751 *
44752 * <div>
44753 * <code>
44754 * // three-digit hexadecimal RGB notation
44755 * stroke('#fae');
44756 * strokeWeight(4);
44757 * rect(20, 20, 60, 60);
44758 * </code>
44759 * </div>
44760 *
44761 * <div>
44762 * <code>
44763 * // six-digit hexadecimal RGB notation
44764 * stroke('#222222');
44765 * strokeWeight(4);
44766 * rect(20, 20, 60, 60);
44767 * </code>
44768 * </div>
44769 *
44770 * <div>
44771 * <code>
44772 * // integer RGB notation
44773 * stroke('rgb(0,255,0)');
44774 * strokeWeight(4);
44775 * rect(20, 20, 60, 60);
44776 * </code>
44777 * </div>
44778 *
44779 * <div>
44780 * <code>
44781 * // integer RGBA notation
44782 * stroke('rgba(0,255,0,0.25)');
44783 * strokeWeight(4);
44784 * rect(20, 20, 60, 60);
44785 * </code>
44786 * </div>
44787 *
44788 * <div>
44789 * <code>
44790 * // percentage RGB notation
44791 * stroke('rgb(100%,0%,10%)');
44792 * strokeWeight(4);
44793 * rect(20, 20, 60, 60);
44794 * </code>
44795 * </div>
44796 *
44797 * <div>
44798 * <code>
44799 * // percentage RGBA notation
44800 * stroke('rgba(100%,0%,100%,0.5)');
44801 * strokeWeight(4);
44802 * rect(20, 20, 60, 60);
44803 * </code>
44804 * </div>
44805 *
44806 * <div>
44807 * <code>
44808 * // p5 Color object
44809 * stroke(color(0, 0, 255));
44810 * strokeWeight(4);
44811 * rect(20, 20, 60, 60);
44812 * </code>
44813 * </div>
44814 *
44815 * @alt
44816 * 60x60 white rect at center. Dark charcoal grey outline.
44817 * 60x60 white rect at center. Yellow outline.
44818 * 60x60 white rect at center. Royal blue outline.
44819 * 60x60 white rect at center. Red outline.
44820 * 60x60 white rect at center. Pink outline.
44821 * 60x60 white rect at center. Black outline.
44822 * 60x60 white rect at center. Bright green outline.
44823 * 60x60 white rect at center. Soft green outline.
44824 * 60x60 white rect at center. Red outline.
44825 * 60x60 white rect at center. Dark fushcia outline.
44826 * 60x60 white rect at center. Blue outline.
44827 */
44828
44829/**
44830 * @method stroke
44831 * @param  {String}        value   a color string
44832 * @chainable
44833 */
44834
44835/**
44836 * @method stroke
44837 * @param  {Number}        gray   a gray value
44838 * @param  {Number}        [alpha]
44839 * @chainable
44840 */
44841
44842/**
44843 * @method stroke
44844 * @param  {Number[]}      values  an array containing the red,green,blue &
44845 *                                 and alpha components of the color
44846 * @chainable
44847 */
44848
44849/**
44850 * @method stroke
44851 * @param  {p5.Color}      color   the stroke color
44852 * @chainable
44853 */
44854
44855p5.prototype.stroke = function() {
44856  this._renderer._setProperty('_strokeSet', true);
44857  this._renderer._setProperty('_doStroke', true);
44858  this._renderer.stroke.apply(this._renderer, arguments);
44859  return this;
44860};
44861
44862module.exports = p5;
44863
44864},{"../core/constants":21,"../core/core":22,"./p5.Color":16}],18:[function(_dereq_,module,exports){
44865/**
44866 * @module Shape
44867 * @submodule 2D Primitives
44868 * @for p5
44869 * @requires core
44870 * @requires constants
44871 */
44872
44873'use strict';
44874
44875var p5 = _dereq_('./core');
44876var constants = _dereq_('./constants');
44877var canvas = _dereq_('./canvas');
44878_dereq_('./error_helpers');
44879
44880/**
44881 * Draw an arc to the screen. If called with only x, y, w, h, start, and
44882 * stop, the arc will be drawn and filled as an open pie segment. If a mode parameter is provided, the arc
44883 * will be filled like an open semi-circle (OPEN) , a closed semi-circle (CHORD), or as a closed pie segment (PIE). The
44884 * origin may be changed with the ellipseMode() function.<br><br>
44885 * Note that drawing a full circle (ex: 0 to TWO_PI) will appear blank
44886 * because 0 and TWO_PI are the same position on the unit circle. The
44887 * best way to handle this is by using the ellipse() function instead
44888 * to create a closed ellipse, and to use the arc() function
44889 * only to draw parts of an ellipse.
44890 *
44891 * @method arc
44892 * @param  {Number} x      x-coordinate of the arc's ellipse
44893 * @param  {Number} y      y-coordinate of the arc's ellipse
44894 * @param  {Number} w      width of the arc's ellipse by default
44895 * @param  {Number} h      height of the arc's ellipse by default
44896 * @param  {Number} start  angle to start the arc, specified in radians
44897 * @param  {Number} stop   angle to stop the arc, specified in radians
44898 * @param  {Constant} [mode] optional parameter to determine the way of drawing
44899 *                         the arc. either CHORD, PIE or OPEN
44900 * @chainable
44901 * @example
44902 * <div>
44903 * <code>
44904 * arc(50, 55, 50, 50, 0, HALF_PI);
44905 * noFill();
44906 * arc(50, 55, 60, 60, HALF_PI, PI);
44907 * arc(50, 55, 70, 70, PI, PI + QUARTER_PI);
44908 * arc(50, 55, 80, 80, PI + QUARTER_PI, TWO_PI);
44909 * </code>
44910 * </div>
44911 *
44912 * <div>
44913 * <code>
44914 * arc(50, 50, 80, 80, 0, PI + QUARTER_PI);
44915 * </code>
44916 * </div>
44917 *
44918 * <div>
44919 * <code>
44920 * arc(50, 50, 80, 80, 0, PI + QUARTER_PI, OPEN);
44921 * </code>
44922 * </div>
44923 *
44924 * <div>
44925 * <code>
44926 * arc(50, 50, 80, 80, 0, PI + QUARTER_PI, CHORD);
44927 * </code>
44928 * </div>
44929 *
44930 * <div>
44931 * <code>
44932 * arc(50, 50, 80, 80, 0, PI + QUARTER_PI, PIE);
44933 * </code>
44934 * </div>
44935 *
44936 * @alt
44937 *shattered outline of an ellipse with a quarter of a white circle bottom-right.
44938 *white ellipse with top right quarter missing.
44939 *white ellipse with black outline with top right missing.
44940 *white ellipse with top right missing with black outline around shape.
44941 *white ellipse with top right quarter missing with black outline around the shape.
44942 *
44943 */
44944p5.prototype.arc = function(x, y, w, h, start, stop, mode) {
44945  p5._validateParameters('arc', arguments);
44946  if (!this._renderer._doStroke && !this._renderer._doFill) {
44947    return this;
44948  }
44949
44950  start = this._toRadians(start);
44951  stop = this._toRadians(stop);
44952
44953  // Make all angles positive...
44954  while (start < 0) {
44955    start += constants.TWO_PI;
44956  }
44957  while (stop < 0) {
44958    stop += constants.TWO_PI;
44959  }
44960  // ...and confine them to the interval [0,TWO_PI).
44961  start %= constants.TWO_PI;
44962  stop %= constants.TWO_PI;
44963
44964  // account for full circle
44965  if (stop === start) {
44966    stop += constants.TWO_PI;
44967  }
44968
44969  // Adjust angles to counter linear scaling.
44970  if (start <= constants.HALF_PI) {
44971    start = Math.atan(w / h * Math.tan(start));
44972  } else if (start > constants.HALF_PI && start <= 3 * constants.HALF_PI) {
44973    start = Math.atan(w / h * Math.tan(start)) + constants.PI;
44974  } else {
44975    start = Math.atan(w / h * Math.tan(start)) + constants.TWO_PI;
44976  }
44977  if (stop <= constants.HALF_PI) {
44978    stop = Math.atan(w / h * Math.tan(stop));
44979  } else if (stop > constants.HALF_PI && stop <= 3 * constants.HALF_PI) {
44980    stop = Math.atan(w / h * Math.tan(stop)) + constants.PI;
44981  } else {
44982    stop = Math.atan(w / h * Math.tan(stop)) + constants.TWO_PI;
44983  }
44984
44985  // Exceed the interval if necessary in order to preserve the size and
44986  // orientation of the arc.
44987  if (start > stop) {
44988    stop += constants.TWO_PI;
44989  }
44990  // p5 supports negative width and heights for ellipses
44991  w = Math.abs(w);
44992  h = Math.abs(h);
44993  this._renderer.arc(x, y, w, h, start, stop, mode);
44994  return this;
44995};
44996
44997/**
44998 * Draws an ellipse (oval) to the screen. An ellipse with equal width and
44999 * height is a circle. By default, the first two parameters set the location,
45000 * and the third and fourth parameters set the shape's width and height. If
45001 * no height is specified, the value of width is used for both the width and
45002 * height. If a negative height or width is specified, the absolute value is taken.
45003 * The origin may be changed with the ellipseMode() function.
45004 *
45005 * @method ellipse
45006 * @param  {Number} x x-coordinate of the ellipse.
45007 * @param  {Number} y y-coordinate of the ellipse.
45008 * @param  {Number} w width of the ellipse.
45009 * @param  {Number} [h] height of the ellipse.
45010 * @chainable
45011 * @example
45012 * <div>
45013 * <code>
45014 * ellipse(56, 46, 55, 55);
45015 * </code>
45016 * </div>
45017 *
45018 * @alt
45019 *white ellipse with black outline in middle-right of canvas that is 55x55.
45020 *
45021 */
45022/**
45023 * @method ellipse
45024 * @param  {Number} x
45025 * @param  {Number} y
45026 * @param  {Number} w
45027 * @param  {Number} h
45028 * @param  {Integer} detail number of radial sectors to draw
45029 */
45030p5.prototype.ellipse = function(x, y, w, h, detailX) {
45031  p5._validateParameters('ellipse', arguments);
45032
45033  // p5 supports negative width and heights for rects
45034  if (w < 0) {
45035    w = Math.abs(w);
45036  }
45037
45038  if (typeof h === 'undefined') {
45039    // Duplicate 3rd argument if only 3 given.
45040    h = w;
45041  } else if (h < 0) {
45042    h = Math.abs(h);
45043  }
45044
45045  if (this._renderer._doStroke || this._renderer._doFill) {
45046    var vals = canvas.modeAdjust(x, y, w, h, this._renderer._ellipseMode);
45047    this._renderer.ellipse([vals.x, vals.y, vals.w, vals.h, detailX]);
45048  }
45049
45050  return this;
45051};
45052/**
45053 * Draws a line (a direct path between two points) to the screen. The version
45054 * of line() with four parameters draws the line in 2D. To color a line, use
45055 * the stroke() function. A line cannot be filled, therefore the fill()
45056 * function will not affect the color of a line. 2D lines are drawn with a
45057 * width of one pixel by default, but this can be changed with the
45058 * strokeWeight() function.
45059 *
45060 * @method line
45061 * @param  {Number} x1 the x-coordinate of the first point
45062 * @param  {Number} y1 the y-coordinate of the first point
45063 * @param  {Number} x2 the x-coordinate of the second point
45064 * @param  {Number} y2 the y-coordinate of the second point
45065 * @chainable
45066 * @example
45067 * <div>
45068 * <code>
45069 * line(30, 20, 85, 75);
45070 * </code>
45071 * </div>
45072 *
45073 * <div>
45074 * <code>
45075 * line(30, 20, 85, 20);
45076 * stroke(126);
45077 * line(85, 20, 85, 75);
45078 * stroke(255);
45079 * line(85, 75, 30, 75);
45080 * </code>
45081 * </div>
45082 *
45083 * @alt
45084 *line 78 pixels long running from mid-top to bottom-right of canvas.
45085 *3 lines of various stroke sizes. Form top, bottom and right sides of a square.
45086 *
45087 */
45088/**
45089 * @method line
45090 * @param  {Number} x1
45091 * @param  {Number} y1
45092 * @param  {Number} z1 the z-coordinate of the first point
45093 * @param  {Number} x2
45094 * @param  {Number} y2
45095 * @param  {Number} z2 the z-coordinate of the second point
45096 * @chainable
45097 */
45098p5.prototype.line = function() {
45099  p5._validateParameters('line', arguments);
45100
45101  if (this._renderer._doStroke) {
45102    this._renderer.line.apply(this._renderer, arguments);
45103  }
45104
45105  return this;
45106};
45107
45108/**
45109 * Draws a point, a coordinate in space at the dimension of one pixel.
45110 * The first parameter is the horizontal value for the point, the second
45111 * value is the vertical value for the point. The color of the point is
45112 * determined by the current stroke.
45113 *
45114 * @method point
45115 * @param  {Number} x the x-coordinate
45116 * @param  {Number} y the y-coordinate
45117 * @param  {Number} [z] the z-coordinate (for WEBGL mode)
45118 * @chainable
45119 * @example
45120 * <div>
45121 * <code>
45122 * point(30, 20);
45123 * point(85, 20);
45124 * point(85, 75);
45125 * point(30, 75);
45126 * </code>
45127 * </div>
45128 *
45129 * @alt
45130 *4 points centered in the middle-right of the canvas.
45131 *
45132 */
45133p5.prototype.point = function() {
45134  p5._validateParameters('point', arguments);
45135
45136  if (this._renderer._doStroke) {
45137    this._renderer.point.apply(this._renderer, arguments);
45138  }
45139
45140  return this;
45141};
45142
45143/**
45144 * Draw a quad. A quad is a quadrilateral, a four sided polygon. It is
45145 * similar to a rectangle, but the angles between its edges are not
45146 * constrained to ninety degrees. The first pair of parameters (x1,y1)
45147 * sets the first vertex and the subsequent pairs should proceed
45148 * clockwise or counter-clockwise around the defined shape.
45149 *
45150 * @method quad
45151 * @param {Number} x1 the x-coordinate of the first point
45152 * @param {Number} y1 the y-coordinate of the first point
45153 * @param {Number} x2 the x-coordinate of the second point
45154 * @param {Number} y2 the y-coordinate of the second point
45155 * @param {Number} x3 the x-coordinate of the third point
45156 * @param {Number} y3 the y-coordinate of the third point
45157 * @param {Number} x4 the x-coordinate of the fourth point
45158 * @param {Number} y4 the y-coordinate of the fourth point
45159 * @chainable
45160 * @example
45161 * <div>
45162 * <code>
45163 * quad(38, 31, 86, 20, 69, 63, 30, 76);
45164 * </code>
45165 * </div>
45166 *
45167 * @alt
45168 *irregular white quadrilateral shape with black outline mid-right of canvas.
45169 *
45170 */
45171/**
45172 * @method quad
45173 * @param {Number} x1
45174 * @param {Number} y1
45175 * @param {Number} z1
45176 * @param {Number} x2
45177 * @param {Number} y2
45178 * @param {Number} z2
45179 * @param {Number} x3
45180 * @param {Number} y3
45181 * @param {Number} z3
45182 * @param {Number} x4
45183 * @param {Number} y4
45184 * @param {Number} z4
45185 * @chainable
45186 */
45187p5.prototype.quad = function() {
45188  p5._validateParameters('quad', arguments);
45189
45190  if (this._renderer._doStroke || this._renderer._doFill) {
45191    this._renderer.quad.apply(this._renderer, arguments);
45192  }
45193
45194  return this;
45195};
45196
45197/**
45198 * Draws a rectangle to the screen. A rectangle is a four-sided shape with
45199 * every angle at ninety degrees. By default, the first two parameters set
45200 * the location of the upper-left corner, the third sets the width, and the
45201 * fourth sets the height. The way these parameters are interpreted, however,
45202 * may be changed with the rectMode() function.
45203 * <br><br>
45204 * The fifth, sixth, seventh and eighth parameters, if specified,
45205 * determine corner radius for the top-right, top-left, lower-right and
45206 * lower-left corners, respectively. An omitted corner radius parameter is set
45207 * to the value of the previously specified radius value in the parameter list.
45208 *
45209 * @method rect
45210 * @param  {Number} x  x-coordinate of the rectangle.
45211 * @param  {Number} y  y-coordinate of the rectangle.
45212 * @param  {Number} w  width of the rectangle.
45213 * @param  {Number} h  height of the rectangle.
45214 * @param  {Number} [tl] optional radius of top-left corner.
45215 * @param  {Number} [tr] optional radius of top-right corner.
45216 * @param  {Number} [br] optional radius of bottom-right corner.
45217 * @param  {Number} [bl] optional radius of bottom-left corner.
45218 * @chainable
45219 * @example
45220 * <div>
45221 * <code>
45222 * // Draw a rectangle at location (30, 20) with a width and height of 55.
45223 * rect(30, 20, 55, 55);
45224 * </code>
45225 * </div>
45226 *
45227 * <div>
45228 * <code>
45229 * // Draw a rectangle with rounded corners, each having a radius of 20.
45230 * rect(30, 20, 55, 55, 20);
45231 * </code>
45232 * </div>
45233 *
45234 * <div>
45235 * <code>
45236 * // Draw a rectangle with rounded corners having the following radii:
45237 * // top-left = 20, top-right = 15, bottom-right = 10, bottom-left = 5.
45238 * rect(30, 20, 55, 55, 20, 15, 10, 5);
45239 * </code>
45240 * </div>
45241 *
45242 * @alt
45243 * 55x55 white rect with black outline in mid-right of canvas.
45244 * 55x55 white rect with black outline and rounded edges in mid-right of canvas.
45245 * 55x55 white rect with black outline and rounded edges of different radii.
45246 */
45247/**
45248 * @method rect
45249 * @param  {Number} x
45250 * @param  {Number} y
45251 * @param  {Number} w
45252 * @param  {Number} h
45253 * @param  {Integer} [detailX] number of segments in the x-direction
45254 * @param  {Integer} [detailY] number of segments in the y-direction
45255 * @chainable
45256 */
45257p5.prototype.rect = function() {
45258  p5._validateParameters('rect', arguments);
45259
45260  if (this._renderer._doStroke || this._renderer._doFill) {
45261    var vals = canvas.modeAdjust(
45262      arguments[0],
45263      arguments[1],
45264      arguments[2],
45265      arguments[3],
45266      this._renderer._rectMode
45267    );
45268    var args = [vals.x, vals.y, vals.w, vals.h];
45269    // append the additional arguments (either cornder radii, or
45270    // segment details) to the argument list
45271    for (var i = 4; i < arguments.length; i++) {
45272      args[i] = arguments[i];
45273    }
45274    this._renderer.rect(args);
45275  }
45276
45277  return this;
45278};
45279
45280/**
45281 * A triangle is a plane created by connecting three points. The first two
45282 * arguments specify the first point, the middle two arguments specify the
45283 * second point, and the last two arguments specify the third point.
45284 *
45285 * @method triangle
45286 * @param  {Number} x1 x-coordinate of the first point
45287 * @param  {Number} y1 y-coordinate of the first point
45288 * @param  {Number} x2 x-coordinate of the second point
45289 * @param  {Number} y2 y-coordinate of the second point
45290 * @param  {Number} x3 x-coordinate of the third point
45291 * @param  {Number} y3 y-coordinate of the third point
45292 * @chainable
45293 * @example
45294 * <div>
45295 * <code>
45296 * triangle(30, 75, 58, 20, 86, 75);
45297 * </code>
45298 * </div>
45299 *
45300 *@alt
45301 * white triangle with black outline in mid-right of canvas.
45302 *
45303 */
45304p5.prototype.triangle = function() {
45305  p5._validateParameters('triangle', arguments);
45306
45307  if (this._renderer._doStroke || this._renderer._doFill) {
45308    this._renderer.triangle(arguments);
45309  }
45310
45311  return this;
45312};
45313
45314module.exports = p5;
45315
45316},{"./canvas":20,"./constants":21,"./core":22,"./error_helpers":25}],19:[function(_dereq_,module,exports){
45317/**
45318 * @module Shape
45319 * @submodule Attributes
45320 * @for p5
45321 * @requires core
45322 * @requires constants
45323 */
45324
45325'use strict';
45326
45327var p5 = _dereq_('./core');
45328var constants = _dereq_('./constants');
45329
45330/**
45331 * Modifies the location from which ellipses are drawn by changing the way
45332 * in which parameters given to ellipse() are interpreted.
45333 * <br><br>
45334 * The default mode is ellipseMode(CENTER), which interprets the first two
45335 * parameters of ellipse() as the shape's center point, while the third and
45336 * fourth parameters are its width and height.
45337 * <br><br>
45338 * ellipseMode(RADIUS) also uses the first two parameters of ellipse() as
45339 * the shape's center point, but uses the third and fourth parameters to
45340 * specify half of the shapes's width and height.
45341 * <br><br>
45342 * ellipseMode(CORNER) interprets the first two parameters of ellipse() as
45343 * the upper-left corner of the shape, while the third and fourth parameters
45344 * are its width and height.
45345 * <br><br>
45346 * ellipseMode(CORNERS) interprets the first two parameters of ellipse() as
45347 * the location of one corner of the ellipse's bounding box, and the third
45348 * and fourth parameters as the location of the opposite corner.
45349 * <br><br>
45350 * The parameter must be written in ALL CAPS because Javascript is a
45351 * case-sensitive language.
45352 *
45353 * @method ellipseMode
45354 * @param  {Constant} mode either CENTER, RADIUS, CORNER, or CORNERS
45355 * @chainable
45356 * @example
45357 * <div>
45358 * <code>
45359 * ellipseMode(RADIUS); // Set ellipseMode to RADIUS
45360 * fill(255); // Set fill to white
45361 * ellipse(50, 50, 30, 30); // Draw white ellipse using RADIUS mode
45362 *
45363 * ellipseMode(CENTER); // Set ellipseMode to CENTER
45364 * fill(100); // Set fill to gray
45365 * ellipse(50, 50, 30, 30); // Draw gray ellipse using CENTER mode
45366 * </code>
45367 * </div>
45368 *
45369 * <div>
45370 * <code>
45371 * ellipseMode(CORNER); // Set ellipseMode is CORNER
45372 * fill(255); // Set fill to white
45373 * ellipse(25, 25, 50, 50); // Draw white ellipse using CORNER mode
45374 *
45375 * ellipseMode(CORNERS); // Set ellipseMode to CORNERS
45376 * fill(100); // Set fill to gray
45377 * ellipse(25, 25, 50, 50); // Draw gray ellipse using CORNERS mode
45378 * </code>
45379 * </div>
45380 *
45381 * @alt
45382 * 60x60 white ellipse and 30x30 grey ellipse with black outlines at center.
45383 * 60x60 white ellipse @center and 30x30 grey ellipse top-right, black outlines.
45384 *
45385 */
45386p5.prototype.ellipseMode = function(m) {
45387  p5._validateParameters('ellipseMode', arguments);
45388  if (
45389    m === constants.CORNER ||
45390    m === constants.CORNERS ||
45391    m === constants.RADIUS ||
45392    m === constants.CENTER
45393  ) {
45394    this._renderer._ellipseMode = m;
45395  }
45396  return this;
45397};
45398
45399/**
45400 * Draws all geometry with jagged (aliased) edges. Note that smooth() is
45401 * active by default, so it is necessary to call noSmooth() to disable
45402 * smoothing of geometry, images, and fonts.
45403 *
45404 * @method noSmooth
45405 * @chainable
45406 * @example
45407 * <div>
45408 * <code>
45409 * background(0);
45410 * noStroke();
45411 * smooth();
45412 * ellipse(30, 48, 36, 36);
45413 * noSmooth();
45414 * ellipse(70, 48, 36, 36);
45415 * </code>
45416 * </div>
45417 *
45418 * @alt
45419 * 2 pixelated 36x36 white ellipses to left & right of center, black background
45420 *
45421 */
45422p5.prototype.noSmooth = function() {
45423  this._renderer.noSmooth();
45424  return this;
45425};
45426
45427/**
45428 * Modifies the location from which rectangles are drawn by changing the way
45429 * in which parameters given to rect() are interpreted.
45430 * <br><br>
45431 * The default mode is rectMode(CORNER), which interprets the first two
45432 * parameters of rect() as the upper-left corner of the shape, while the
45433 * third and fourth parameters are its width and height.
45434 * <br><br>
45435 * rectMode(CORNERS) interprets the first two parameters of rect() as the
45436 * location of one corner, and the third and fourth parameters as the
45437 * location of the opposite corner.
45438 * <br><br>
45439 * rectMode(CENTER) interprets the first two parameters of rect() as the
45440 * shape's center point, while the third and fourth parameters are its
45441 * width and height.
45442 * <br><br>
45443 * rectMode(RADIUS) also uses the first two parameters of rect() as the
45444 * shape's center point, but uses the third and fourth parameters to specify
45445 * half of the shapes's width and height.
45446 * <br><br>
45447 * The parameter must be written in ALL CAPS because Javascript is a
45448 * case-sensitive language.
45449 *
45450 * @method rectMode
45451 * @param  {Constant} mode either CORNER, CORNERS, CENTER, or RADIUS
45452 * @chainable
45453 * @example
45454 * <div>
45455 * <code>
45456 * rectMode(CORNER); // Default rectMode is CORNER
45457 * fill(255); // Set fill to white
45458 * rect(25, 25, 50, 50); // Draw white rect using CORNER mode
45459 *
45460 * rectMode(CORNERS); // Set rectMode to CORNERS
45461 * fill(100); // Set fill to gray
45462 * rect(25, 25, 50, 50); // Draw gray rect using CORNERS mode
45463 * </code>
45464 * </div>
45465 *
45466 * <div>
45467 * <code>
45468 * rectMode(RADIUS); // Set rectMode to RADIUS
45469 * fill(255); // Set fill to white
45470 * rect(50, 50, 30, 30); // Draw white rect using RADIUS mode
45471 *
45472 * rectMode(CENTER); // Set rectMode to CENTER
45473 * fill(100); // Set fill to gray
45474 * rect(50, 50, 30, 30); // Draw gray rect using CENTER mode
45475 * </code>
45476 * </div>
45477 *
45478 * @alt
45479 * 50x50 white rect at center and 25x25 grey rect in the top left of the other.
45480 * 50x50 white rect at center and 25x25 grey rect in the center of the other.
45481 *
45482 */
45483p5.prototype.rectMode = function(m) {
45484  p5._validateParameters('rectMode', arguments);
45485  if (
45486    m === constants.CORNER ||
45487    m === constants.CORNERS ||
45488    m === constants.RADIUS ||
45489    m === constants.CENTER
45490  ) {
45491    this._renderer._rectMode = m;
45492  }
45493  return this;
45494};
45495
45496/**
45497 * Draws all geometry with smooth (anti-aliased) edges. smooth() will also
45498 * improve image quality of resized images. Note that smooth() is active by
45499 * default; noSmooth() can be used to disable smoothing of geometry,
45500 * images, and fonts.
45501 *
45502 * @method smooth
45503 * @chainable
45504 * @example
45505 * <div>
45506 * <code>
45507 * background(0);
45508 * noStroke();
45509 * smooth();
45510 * ellipse(30, 48, 36, 36);
45511 * noSmooth();
45512 * ellipse(70, 48, 36, 36);
45513 * </code>
45514 * </div>
45515 *
45516 * @alt
45517 * 2 pixelated 36x36 white ellipses one left one right of center. On black.
45518 *
45519 */
45520p5.prototype.smooth = function() {
45521  this._renderer.smooth();
45522  return this;
45523};
45524
45525/**
45526 * Sets the style for rendering line endings. These ends are either squared,
45527 * extended, or rounded, each of which specified with the corresponding
45528 * parameters: SQUARE, PROJECT, and ROUND. The default cap is ROUND.
45529 *
45530 * @method strokeCap
45531 * @param  {Constant} cap either SQUARE, PROJECT, or ROUND
45532 * @chainable
45533 * @example
45534 * <div>
45535 * <code>
45536 * strokeWeight(12.0);
45537 * strokeCap(ROUND);
45538 * line(20, 30, 80, 30);
45539 * strokeCap(SQUARE);
45540 * line(20, 50, 80, 50);
45541 * strokeCap(PROJECT);
45542 * line(20, 70, 80, 70);
45543 * </code>
45544 * </div>
45545 *
45546 * @alt
45547 * 3 lines. Top line: rounded ends, mid: squared, bottom:longer squared ends.
45548 *
45549 */
45550p5.prototype.strokeCap = function(cap) {
45551  p5._validateParameters('strokeCap', arguments);
45552  if (
45553    cap === constants.ROUND ||
45554    cap === constants.SQUARE ||
45555    cap === constants.PROJECT
45556  ) {
45557    this._renderer.strokeCap(cap);
45558  }
45559  return this;
45560};
45561
45562/**
45563 * Sets the style of the joints which connect line segments. These joints
45564 * are either mitered, beveled, or rounded and specified with the
45565 * corresponding parameters MITER, BEVEL, and ROUND. The default joint is
45566 * MITER.
45567 *
45568 * @method strokeJoin
45569 * @param  {Constant} join either MITER, BEVEL, ROUND
45570 * @chainable
45571 * @example
45572 * <div>
45573 * <code>
45574 * noFill();
45575 * strokeWeight(10.0);
45576 * strokeJoin(MITER);
45577 * beginShape();
45578 * vertex(35, 20);
45579 * vertex(65, 50);
45580 * vertex(35, 80);
45581 * endShape();
45582 * </code>
45583 * </div>
45584 *
45585 * <div>
45586 * <code>
45587 * noFill();
45588 * strokeWeight(10.0);
45589 * strokeJoin(BEVEL);
45590 * beginShape();
45591 * vertex(35, 20);
45592 * vertex(65, 50);
45593 * vertex(35, 80);
45594 * endShape();
45595 * </code>
45596 * </div>
45597 *
45598 * <div>
45599 * <code>
45600 * noFill();
45601 * strokeWeight(10.0);
45602 * strokeJoin(ROUND);
45603 * beginShape();
45604 * vertex(35, 20);
45605 * vertex(65, 50);
45606 * vertex(35, 80);
45607 * endShape();
45608 * </code>
45609 * </div>
45610 *
45611 * @alt
45612 * Right-facing arrowhead shape with pointed tip in center of canvas.
45613 * Right-facing arrowhead shape with flat tip in center of canvas.
45614 * Right-facing arrowhead shape with rounded tip in center of canvas.
45615 *
45616 */
45617p5.prototype.strokeJoin = function(join) {
45618  p5._validateParameters('strokeJoin', arguments);
45619  if (
45620    join === constants.ROUND ||
45621    join === constants.BEVEL ||
45622    join === constants.MITER
45623  ) {
45624    this._renderer.strokeJoin(join);
45625  }
45626  return this;
45627};
45628
45629/**
45630 * Sets the width of the stroke used for lines, points, and the border
45631 * around shapes. All widths are set in units of pixels.
45632 *
45633 * @method strokeWeight
45634 * @param  {Number} weight the weight (in pixels) of the stroke
45635 * @chainable
45636 * @example
45637 * <div>
45638 * <code>
45639 * strokeWeight(1); // Default
45640 * line(20, 20, 80, 20);
45641 * strokeWeight(4); // Thicker
45642 * line(20, 40, 80, 40);
45643 * strokeWeight(10); // Beastly
45644 * line(20, 70, 80, 70);
45645 * </code>
45646 * </div>
45647 *
45648 * @alt
45649 * 3 horizontal black lines. Top line: thin, mid: medium, bottom:thick.
45650 *
45651 */
45652p5.prototype.strokeWeight = function(w) {
45653  p5._validateParameters('strokeWeight', arguments);
45654  this._renderer.strokeWeight(w);
45655  return this;
45656};
45657
45658module.exports = p5;
45659
45660},{"./constants":21,"./core":22}],20:[function(_dereq_,module,exports){
45661/**
45662 * @requires constants
45663 */
45664
45665'use strict';
45666
45667var constants = _dereq_('./constants');
45668
45669module.exports = {
45670  modeAdjust: function(a, b, c, d, mode) {
45671    if (mode === constants.CORNER) {
45672      return { x: a, y: b, w: c, h: d };
45673    } else if (mode === constants.CORNERS) {
45674      return { x: a, y: b, w: c - a, h: d - b };
45675    } else if (mode === constants.RADIUS) {
45676      return { x: a - c, y: b - d, w: 2 * c, h: 2 * d };
45677    } else if (mode === constants.CENTER) {
45678      return { x: a - c * 0.5, y: b - d * 0.5, w: c, h: d };
45679    }
45680  },
45681
45682  arcModeAdjust: function(a, b, c, d, mode) {
45683    if (mode === constants.CORNER) {
45684      return { x: a + c * 0.5, y: b + d * 0.5, w: c, h: d };
45685    } else if (mode === constants.CORNERS) {
45686      return { x: a, y: b, w: c + a, h: d + b };
45687    } else if (mode === constants.RADIUS) {
45688      return { x: a, y: b, w: 2 * c, h: 2 * d };
45689    } else if (mode === constants.CENTER) {
45690      return { x: a, y: b, w: c, h: d };
45691    }
45692  }
45693};
45694
45695},{"./constants":21}],21:[function(_dereq_,module,exports){
45696/**
45697 * @module Constants
45698 * @submodule Constants
45699 * @for p5
45700 */
45701
45702'use strict';
45703
45704var PI = Math.PI;
45705
45706module.exports = {
45707  // GRAPHICS RENDERER
45708  /**
45709   * @property {String} P2D
45710   * @final
45711   */
45712  P2D: 'p2d',
45713  /**
45714   * @property {String} WEBGL
45715   * @final
45716   */
45717  WEBGL: 'webgl',
45718
45719  // ENVIRONMENT
45720  ARROW: 'default',
45721  CROSS: 'crosshair',
45722  HAND: 'pointer',
45723  MOVE: 'move',
45724  TEXT: 'text',
45725  WAIT: 'wait',
45726
45727  // TRIGONOMETRY
45728
45729  /**
45730   * HALF_PI is a mathematical constant with the value
45731   * 1.57079632679489661923. It is half the ratio of the
45732   * circumference of a circle to its diameter. It is useful in
45733   * combination with the trigonometric functions sin() and cos().
45734   *
45735   * @property {Number} HALF_PI
45736   * @final
45737   *
45738   * @example
45739   * <div><code>
45740   * arc(50, 50, 80, 80, 0, HALF_PI);
45741   * </code></div>
45742   *
45743   * @alt
45744   * 80x80 white quarter-circle with curve toward bottom right of canvas.
45745   *
45746   */
45747  HALF_PI: PI / 2,
45748  /**
45749   * PI is a mathematical constant with the value
45750   * 3.14159265358979323846. It is the ratio of the circumference
45751   * of a circle to its diameter. It is useful in combination with
45752   * the trigonometric functions sin() and cos().
45753   *
45754   * @property {Number} PI
45755   * @final
45756   *
45757   * @example
45758   * <div><code>
45759   * arc(50, 50, 80, 80, 0, PI);
45760   * </code></div>
45761   *
45762   * @alt
45763   * white half-circle with curve toward bottom of canvas.
45764   *
45765   */
45766  PI: PI,
45767  /**
45768   * QUARTER_PI is a mathematical constant with the value 0.7853982.
45769   * It is one quarter the ratio of the circumference of a circle to
45770   * its diameter. It is useful in combination with the trigonometric
45771   * functions sin() and cos().
45772   *
45773   * @property {Number} QUARTER_PI
45774   * @final
45775   *
45776   * @example
45777   * <div><code>
45778   * arc(50, 50, 80, 80, 0, QUARTER_PI);
45779   * </code></div>
45780   *
45781   * @alt
45782   * white eighth-circle rotated about 40 degrees with curve bottom right canvas.
45783   *
45784   */
45785  QUARTER_PI: PI / 4,
45786  /**
45787   * TAU is an alias for TWO_PI, a mathematical constant with the
45788   * value 6.28318530717958647693. It is twice the ratio of the
45789   * circumference of a circle to its diameter. It is useful in
45790   * combination with the trigonometric functions sin() and cos().
45791   *
45792   * @property {Number} TAU
45793   * @final
45794   *
45795   * @example
45796   * <div><code>
45797   * arc(50, 50, 80, 80, 0, TAU);
45798   * </code></div>
45799   *
45800   * @alt
45801   * 80x80 white ellipse shape in center of canvas.
45802   *
45803   */
45804  TAU: PI * 2,
45805  /**
45806   * TWO_PI is a mathematical constant with the value
45807   * 6.28318530717958647693. It is twice the ratio of the
45808   * circumference of a circle to its diameter. It is useful in
45809   * combination with the trigonometric functions sin() and cos().
45810   *
45811   * @property {Number} TWO_PI
45812   * @final
45813   *
45814   * @example
45815   * <div><code>
45816   * arc(50, 50, 80, 80, 0, TWO_PI);
45817   * </code></div>
45818   *
45819   * @alt
45820   * 80x80 white ellipse shape in center of canvas.
45821   *
45822   */
45823  TWO_PI: PI * 2,
45824  /**
45825   * Constant to be used with angleMode() function, to set the mode which
45826   * p5.js interprates and calculates angles (either DEGREES or RADIANS).
45827   * @property {String} DEGREES
45828   * @final
45829   *
45830   * @example
45831   * <div class='norender'><code>
45832   * function setup() {
45833   *   angleMode(DEGREES);
45834   * }
45835   * </code></div>
45836   */
45837  DEGREES: 'degrees',
45838  /**
45839   * Constant to be used with angleMode() function, to set the mode which
45840   * p5.js interprates and calculates angles (either RADIANS or DEGREES).
45841   * @property {String} RADIANS
45842   * @final
45843   *
45844   * @example
45845   * <div class='norender'><code>
45846   * function setup() {
45847   *   angleMode(RADIANS);
45848   * }
45849   * </code></div>
45850   */
45851  RADIANS: 'radians',
45852  DEG_TO_RAD: PI / 180.0,
45853  RAD_TO_DEG: 180.0 / PI,
45854
45855  // SHAPE
45856  /**
45857   * @property {String} CORNER
45858   * @final
45859   */
45860  CORNER: 'corner',
45861  /**
45862   * @property {String} CORNERS
45863   * @final
45864   */
45865  CORNERS: 'corners',
45866  /**
45867   * @property {String} RADIUS
45868   * @final
45869   */
45870  RADIUS: 'radius',
45871  /**
45872   * @property {String} RIGHT
45873   * @final
45874   */
45875  RIGHT: 'right',
45876  /**
45877   * @property {String} LEFT
45878   * @final
45879   */
45880  LEFT: 'left',
45881  /**
45882   * @property {String} CENTER
45883   * @final
45884   */
45885  CENTER: 'center',
45886  /**
45887   * @property {String} TOP
45888   * @final
45889   */
45890  TOP: 'top',
45891  /**
45892   * @property {String} BOTTOM
45893   * @final
45894   */
45895  BOTTOM: 'bottom',
45896  /**
45897   * @property {String} BASELINE
45898   * @final
45899   * @default alphabetic
45900   */
45901  BASELINE: 'alphabetic',
45902  /**
45903   * @property {Number} POINTS
45904   * @final
45905   * @default 0x0000
45906   */
45907  POINTS: 0x0000,
45908  /**
45909   * @property {Number} LINES
45910   * @final
45911   * @default 0x0001
45912   */
45913  LINES: 0x0001,
45914  /**
45915   * @property {Number} LINE_STRIP
45916   * @final
45917   * @default 0x0003
45918   */
45919  LINE_STRIP: 0x0003,
45920  /**
45921   * @property {Number} LINE_LOOP
45922   * @final
45923   * @default 0x0002
45924   */
45925  LINE_LOOP: 0x0002,
45926  /**
45927   * @property {Number} TRIANGLES
45928   * @final
45929   * @default 0x0004
45930   */
45931  TRIANGLES: 0x0004,
45932  /**
45933   * @property {Number} TRIANGLE_FAN
45934   * @final
45935   * @default 0x0006
45936   */
45937  TRIANGLE_FAN: 0x0006,
45938  /**
45939   * @property {Number} TRIANGLE_STRIP
45940   * @final
45941   * @default 0x0005
45942   */
45943  TRIANGLE_STRIP: 0x0005,
45944  /**
45945   * @property {String} QUADS
45946   * @final
45947   */
45948  QUADS: 'quads',
45949  /**
45950   * @property {String} QUAD_STRIP
45951   * @final
45952   * @default quad_strip
45953   */
45954  QUAD_STRIP: 'quad_strip',
45955  /**
45956   * @property {String} CLOSE
45957   * @final
45958   */
45959  CLOSE: 'close',
45960  /**
45961   * @property {String} OPEN
45962   * @final
45963   */
45964  OPEN: 'open',
45965  /**
45966   * @property {String} CHORD
45967   * @final
45968   */
45969  CHORD: 'chord',
45970  /**
45971   * @property {String} PIE
45972   * @final
45973   */
45974  PIE: 'pie',
45975  /**
45976   * @property {String} PROJECT
45977   * @final
45978   * @default square
45979   */
45980  PROJECT: 'square', // PEND: careful this is counterintuitive
45981  /**
45982   * @property {String} SQUARE
45983   * @final
45984   * @default butt
45985   */
45986  SQUARE: 'butt',
45987  /**
45988   * @property {String} ROUND
45989   * @final
45990   */
45991  ROUND: 'round',
45992  /**
45993   * @property {String} BEVEL
45994   * @final
45995   */
45996  BEVEL: 'bevel',
45997  /**
45998   * @property {String} MITER
45999   * @final
46000   */
46001  MITER: 'miter',
46002
46003  // COLOR
46004  /**
46005   * @property {String} RGB
46006   * @final
46007   */
46008  RGB: 'rgb',
46009  /**
46010   * @property {String} HSB
46011   * @final
46012   */
46013  HSB: 'hsb',
46014  /**
46015   * @property {String} HSL
46016   * @final
46017   */
46018  HSL: 'hsl',
46019
46020  // DOM EXTENSION
46021  AUTO: 'auto',
46022
46023  // INPUT
46024  ALT: 18,
46025  BACKSPACE: 8,
46026  CONTROL: 17,
46027  DELETE: 46,
46028  DOWN_ARROW: 40,
46029  ENTER: 13,
46030  ESCAPE: 27,
46031  LEFT_ARROW: 37,
46032  OPTION: 18,
46033  RETURN: 13,
46034  RIGHT_ARROW: 39,
46035  SHIFT: 16,
46036  TAB: 9,
46037  UP_ARROW: 38,
46038
46039  // RENDERING
46040  /**
46041   * @property {String} BLEND
46042   * @final
46043   * @default source-over
46044   */
46045  BLEND: 'source-over',
46046  /**
46047   * @property {String} ADD
46048   * @final
46049   * @default lighter
46050   */
46051  ADD: 'lighter',
46052  //ADD: 'add', //
46053  //SUBTRACT: 'subtract', //
46054  /**
46055   * @property {String} DARKEST
46056   * @final
46057   */
46058  DARKEST: 'darken',
46059  /**
46060   * @property {String} LIGHTEST
46061   * @final
46062   * @default lighten
46063   */
46064  LIGHTEST: 'lighten',
46065  /**
46066   * @property {String} DIFFERENCE
46067   * @final
46068   */
46069  DIFFERENCE: 'difference',
46070  /**
46071   * @property {String} EXCLUSION
46072   * @final
46073   */
46074  EXCLUSION: 'exclusion',
46075  /**
46076   * @property {String} MULTIPLY
46077   * @final
46078   */
46079  MULTIPLY: 'multiply',
46080  /**
46081   * @property {String} SCREEN
46082   * @final
46083   */
46084  SCREEN: 'screen',
46085  /**
46086   * @property {String} REPLACE
46087   * @final
46088   * @default copy
46089   */
46090  REPLACE: 'copy',
46091  /**
46092   * @property {String} OVERLAY
46093   * @final
46094   */
46095  OVERLAY: 'overlay',
46096  /**
46097   * @property {String} HARD_LIGHT
46098   * @final
46099   */
46100  HARD_LIGHT: 'hard-light',
46101  /**
46102   * @property {String} SOFT_LIGHT
46103   * @final
46104   */
46105  SOFT_LIGHT: 'soft-light',
46106  /**
46107   * @property {String} DODGE
46108   * @final
46109   * @default color-dodge
46110   */
46111  DODGE: 'color-dodge',
46112  /**
46113   * @property {String} BURN
46114   * @final
46115   * @default color-burn
46116   */
46117  BURN: 'color-burn',
46118
46119  // FILTERS
46120  /**
46121   * @property {String} THRESHOLD
46122   * @final
46123   */
46124  THRESHOLD: 'threshold',
46125  /**
46126   * @property {String} GRAY
46127   * @final
46128   */
46129  GRAY: 'gray',
46130  /**
46131   * @property {String} OPAQUE
46132   * @final
46133   */
46134  OPAQUE: 'opaque',
46135  /**
46136   * @property {String} INVERT
46137   * @final
46138   */
46139  INVERT: 'invert',
46140  /**
46141   * @property {String} POSTERIZE
46142   * @final
46143   */
46144  POSTERIZE: 'posterize',
46145  /**
46146   * @property {String} DILATE
46147   * @final
46148   */
46149  DILATE: 'dilate',
46150  /**
46151   * @property {String} ERODE
46152   * @final
46153   */
46154  ERODE: 'erode',
46155  /**
46156   * @property {String} BLUR
46157   * @final
46158   */
46159  BLUR: 'blur',
46160
46161  // TYPOGRAPHY
46162  /**
46163   * @property {String} NORMAL
46164   * @final
46165   */
46166  NORMAL: 'normal',
46167  /**
46168   * @property {String} ITALIC
46169   * @final
46170   */
46171  ITALIC: 'italic',
46172  /**
46173   * @property {String} BOLD
46174   * @final
46175   */
46176  BOLD: 'bold',
46177
46178  // TYPOGRAPHY-INTERNAL
46179  _DEFAULT_TEXT_FILL: '#000000',
46180  _DEFAULT_LEADMULT: 1.25,
46181  _CTX_MIDDLE: 'middle',
46182
46183  // VERTICES
46184  LINEAR: 'linear',
46185  QUADRATIC: 'quadratic',
46186  BEZIER: 'bezier',
46187  CURVE: 'curve',
46188
46189  // WEBGL DRAWMODES
46190  STROKE: 'stroke',
46191  FILL: 'fill',
46192  TEXTURE: 'texture',
46193  IMMEDIATE: 'immediate',
46194
46195  // DEVICE-ORIENTATION
46196  /**
46197   * @property {String} LANDSCAPE
46198   * @final
46199   */
46200  LANDSCAPE: 'landscape',
46201  /**
46202   * @property {String} PORTRAIT
46203   * @final
46204   */
46205  PORTRAIT: 'portrait',
46206
46207  // DEFAULTS
46208  _DEFAULT_STROKE: '#000000',
46209  _DEFAULT_FILL: '#FFFFFF'
46210};
46211
46212},{}],22:[function(_dereq_,module,exports){
46213/**
46214 * @module Structure
46215 * @submodule Structure
46216 * @for p5
46217 * @requires constants
46218 */
46219
46220'use strict';
46221
46222_dereq_('./shim');
46223
46224// Core needs the PVariables object
46225var constants = _dereq_('./constants');
46226
46227/**
46228 * This is the p5 instance constructor.
46229 *
46230 * A p5 instance holds all the properties and methods related to
46231 * a p5 sketch.  It expects an incoming sketch closure and it can also
46232 * take an optional node parameter for attaching the generated p5 canvas
46233 * to a node.  The sketch closure takes the newly created p5 instance as
46234 * its sole argument and may optionally set preload(), setup(), and/or
46235 * draw() properties on it for running a sketch.
46236 *
46237 * A p5 sketch can run in "global" or "instance" mode:
46238 * "global"   - all properties and methods are attached to the window
46239 * "instance" - all properties and methods are bound to this p5 object
46240 *
46241 * @class p5
46242 * @constructor
46243 * @param  {function}    sketch a closure that can set optional preload(),
46244 *                              setup(), and/or draw() properties on the
46245 *                              given p5 instance
46246 * @param  {HTMLElement|Boolean} [node] element to attach canvas to, if a
46247 *                                      boolean is passed in use it as sync
46248 * @param  {Boolean}     [sync] start synchronously (optional)
46249 * @return {p5}                 a p5 instance
46250 */
46251var p5 = function(sketch, node, sync) {
46252  if (typeof node === 'boolean' && typeof sync === 'undefined') {
46253    sync = node;
46254    node = undefined;
46255  }
46256
46257  //////////////////////////////////////////////
46258  // PUBLIC p5 PROPERTIES AND METHODS
46259  //////////////////////////////////////////////
46260
46261  /**
46262   * Called directly before setup(), the preload() function is used to handle
46263   * asynchronous loading of external files in a blocking way. If a preload 
46264   * function is defined, setup() will wait until any load calls within have
46265   * finished. Nothing besides load calls (loadImage, loadJSON, loadFont,
46266   * loadStrings, etc.) should be inside preload function. If asynchronous
46267   * loading is preferred, the load methods can instead be called in setup()
46268   * or anywhere else with the use of a callback parameter.
46269   * <br><br>
46270   * By default the text "loading..." will be displayed. To make your own
46271   * loading page, include an HTML element with id "p5_loading" in your
46272   * page. More information <a href="http://bit.ly/2kQ6Nio">here</a>.
46273   *
46274   * @method preload
46275   * @example
46276   * <div><code>
46277   * var img;
46278   * var c;
46279   * function preload() {
46280  // preload() runs once
46281   *   img = loadImage('assets/laDefense.jpg');
46282   * }
46283   *
46284   * function setup() {
46285  // setup() waits until preload() is done
46286   *   img.loadPixels();
46287   *   // get color of middle pixel
46288   *   c = img.get(img.width / 2, img.height / 2);
46289   * }
46290   *
46291   * function draw() {
46292   *   background(c);
46293   *   image(img, 25, 25, 50, 50);
46294   * }
46295   * </code></div>
46296   *
46297   * @alt
46298   * nothing displayed
46299   *
46300   */
46301
46302  /**
46303   * The setup() function is called once when the program starts. It's used to
46304   * define initial environment properties such as screen size and background
46305   * color and to load media such as images and fonts as the program starts.
46306   * There can only be one setup() function for each program and it shouldn't
46307   * be called again after its initial execution.
46308   * <br><br>
46309   * Note: Variables declared within setup() are not accessible within other
46310   * functions, including draw().
46311   *
46312   * @method setup
46313   * @example
46314   * <div><code>
46315   * var a = 0;
46316   *
46317   * function setup() {
46318   *   background(0);
46319   *   noStroke();
46320   *   fill(102);
46321   * }
46322   *
46323   * function draw() {
46324   *   rect(a++ % width, 10, 2, 80);
46325   * }
46326   * </code></div>
46327   *
46328   * @alt
46329   * nothing displayed
46330   *
46331   */
46332
46333  /**
46334   * Called directly after setup(), the draw() function continuously executes
46335   * the lines of code contained inside its block until the program is stopped
46336   * or noLoop() is called. Note if noLoop() is called in setup(), draw() will
46337   * still be executed once before stopping. draw() is called automatically and
46338   * should never be called explicitly.
46339   * <br><br>
46340   * It should always be controlled with noLoop(), redraw() and loop(). After
46341   * noLoop() stops the code in draw() from executing, redraw() causes the
46342   * code inside draw() to execute once, and loop() will cause the code
46343   * inside draw() to resume executing continuously.
46344   * <br><br>
46345   * The number of times draw() executes in each second may be controlled with
46346   * the frameRate() function.
46347   * <br><br>
46348   * There can only be one draw() function for each sketch, and draw() must
46349   * exist if you want the code to run continuously, or to process events such
46350   * as mousePressed(). Sometimes, you might have an empty call to draw() in
46351   * your program, as shown in the above example.
46352   * <br><br>
46353   * It is important to note that the drawing coordinate system will be reset
46354   * at the beginning of each draw() call. If any transformations are performed
46355   * within draw() (ex: scale, rotate, translate), their effects will be
46356   * undone at the beginning of draw(), so transformations will not accumulate
46357   * over time. On the other hand, styling applied (ex: fill, stroke, etc) will
46358   * remain in effect.
46359   *
46360   * @method draw
46361   * @example
46362   * <div><code>
46363   * var yPos = 0;
46364   * function setup() {
46365  // setup() runs once
46366   *   frameRate(30);
46367   * }
46368   * function draw() {
46369  // draw() loops forever, until stopped
46370   *   background(204);
46371   *   yPos = yPos - 1;
46372   *   if (yPos < 0) {
46373   *     yPos = height;
46374   *   }
46375   *   line(0, yPos, width, yPos);
46376   * }
46377   * </code></div>
46378   *
46379   * @alt
46380   * nothing displayed
46381   *
46382   */
46383
46384  //////////////////////////////////////////////
46385  // PRIVATE p5 PROPERTIES AND METHODS
46386  //////////////////////////////////////////////
46387
46388  this._setupDone = false;
46389  // for handling hidpi
46390  this._pixelDensity = Math.ceil(window.devicePixelRatio) || 1;
46391  this._userNode = node;
46392  this._curElement = null;
46393  this._elements = [];
46394  this._requestAnimId = 0;
46395  this._preloadCount = 0;
46396  this._isGlobal = false;
46397  this._loop = true;
46398  this._initializeInstanceVariables();
46399  this._defaultCanvasSize = {
46400    width: 100,
46401    height: 100
46402  };
46403  this._events = {
46404    // keep track of user-events for unregistering later
46405    mousemove: null,
46406    mousedown: null,
46407    mouseup: null,
46408    dragend: null,
46409    dragover: null,
46410    click: null,
46411    dblclick: null,
46412    mouseover: null,
46413    mouseout: null,
46414    keydown: null,
46415    keyup: null,
46416    keypress: null,
46417    touchstart: null,
46418    touchmove: null,
46419    touchend: null,
46420    resize: null,
46421    blur: null
46422  };
46423
46424  this._events.wheel = null;
46425  this._loadingScreenId = 'p5_loading';
46426
46427  // Allows methods to be registered on an instance that
46428  // are instance-specific.
46429  this._registeredMethods = {};
46430  var methods = Object.getOwnPropertyNames(p5.prototype._registeredMethods);
46431  for (var i = 0; i < methods.length; i++) {
46432    var prop = methods[i];
46433    this._registeredMethods[prop] = p5.prototype._registeredMethods[
46434      prop
46435    ].slice();
46436  }
46437
46438  if (window.DeviceOrientationEvent) {
46439    this._events.deviceorientation = null;
46440  }
46441  if (window.DeviceMotionEvent && !window._isNodeWebkit) {
46442    this._events.devicemotion = null;
46443  }
46444
46445  this._start = function() {
46446    // Find node if id given
46447    if (this._userNode) {
46448      if (typeof this._userNode === 'string') {
46449        this._userNode = document.getElementById(this._userNode);
46450      }
46451    }
46452
46453    var userPreload = this.preload || window.preload; // look for "preload"
46454    if (userPreload) {
46455      // Setup loading screen
46456      // Set loading screen into dom if not present
46457      // Otherwise displays and removes user provided loading screen
46458      var loadingScreen = document.getElementById(this._loadingScreenId);
46459      if (!loadingScreen) {
46460        loadingScreen = document.createElement('div');
46461        loadingScreen.innerHTML = 'Loading...';
46462        loadingScreen.style.position = 'absolute';
46463        loadingScreen.id = this._loadingScreenId;
46464        var node = this._userNode || document.body;
46465        node.appendChild(loadingScreen);
46466      }
46467      // var methods = this._preloadMethods;
46468      for (var method in this._preloadMethods) {
46469        // default to p5 if no object defined
46470        this._preloadMethods[method] = this._preloadMethods[method] || p5;
46471        var obj = this._preloadMethods[method];
46472        //it's p5, check if it's global or instance
46473        if (obj === p5.prototype || obj === p5) {
46474          if (this._isGlobal) {
46475            window[method] = this._wrapPreload(this, method);
46476          }
46477          obj = this;
46478        }
46479        this._registeredPreloadMethods[method] = obj[method];
46480        obj[method] = this._wrapPreload(obj, method);
46481      }
46482
46483      userPreload();
46484      this._runIfPreloadsAreDone();
46485    } else {
46486      this._setup();
46487      this._runFrames();
46488      this._draw();
46489    }
46490  }.bind(this);
46491
46492  this._runIfPreloadsAreDone = function() {
46493    var context = this._isGlobal ? window : this;
46494    if (context._preloadCount === 0) {
46495      var loadingScreen = document.getElementById(context._loadingScreenId);
46496      if (loadingScreen) {
46497        loadingScreen.parentNode.removeChild(loadingScreen);
46498      }
46499      context._setup();
46500      context._runFrames();
46501      context._draw();
46502    }
46503  };
46504
46505  this._decrementPreload = function() {
46506    var context = this._isGlobal ? window : this;
46507    if (typeof context.preload === 'function') {
46508      context._setProperty('_preloadCount', context._preloadCount - 1);
46509      context._runIfPreloadsAreDone();
46510    }
46511  };
46512
46513  this._wrapPreload = function(obj, fnName) {
46514    return function() {
46515      //increment counter
46516      this._incrementPreload();
46517      //call original function
46518      return this._registeredPreloadMethods[fnName].apply(obj, arguments);
46519    }.bind(this);
46520  };
46521
46522  this._incrementPreload = function() {
46523    var context = this._isGlobal ? window : this;
46524    context._setProperty('_preloadCount', context._preloadCount + 1);
46525  };
46526
46527  this._setup = function() {
46528    // Always create a default canvas.
46529    // Later on if the user calls createCanvas, this default one
46530    // will be replaced
46531    this.createCanvas(
46532      this._defaultCanvasSize.width,
46533      this._defaultCanvasSize.height,
46534      'p2d'
46535    );
46536
46537    // return preload functions to their normal vals if switched by preload
46538    var context = this._isGlobal ? window : this;
46539    if (typeof context.preload === 'function') {
46540      for (var f in this._preloadMethods) {
46541        context[f] = this._preloadMethods[f][f];
46542        if (context[f] && this) {
46543          context[f] = context[f].bind(this);
46544        }
46545      }
46546    }
46547
46548    // Short-circuit on this, in case someone used the library in "global"
46549    // mode earlier
46550    if (typeof context.setup === 'function') {
46551      context.setup();
46552    }
46553
46554    // unhide any hidden canvases that were created
46555    var canvases = document.getElementsByTagName('canvas');
46556    for (var i = 0; i < canvases.length; i++) {
46557      var k = canvases[i];
46558      if (k.dataset.hidden === 'true') {
46559        k.style.visibility = '';
46560        delete k.dataset.hidden;
46561      }
46562    }
46563    this._setupDone = true;
46564  }.bind(this);
46565
46566  this._draw = function() {
46567    var now = window.performance.now();
46568    var time_since_last = now - this._lastFrameTime;
46569    var target_time_between_frames = 1000 / this._targetFrameRate;
46570
46571    // only draw if we really need to; don't overextend the browser.
46572    // draw if we're within 5ms of when our next frame should paint
46573    // (this will prevent us from giving up opportunities to draw
46574    // again when it's really about time for us to do so). fixes an
46575    // issue where the frameRate is too low if our refresh loop isn't
46576    // in sync with the browser. note that we have to draw once even
46577    // if looping is off, so we bypass the time delay if that
46578    // is the case.
46579    var epsilon = 5;
46580    if (
46581      !this._loop ||
46582      time_since_last >= target_time_between_frames - epsilon
46583    ) {
46584      //mandatory update values(matrixs and stack)
46585
46586      this.redraw();
46587      this._frameRate = 1000.0 / (now - this._lastFrameTime);
46588      this._lastFrameTime = now;
46589
46590      // If the user is actually using mouse module, then update
46591      // coordinates, otherwise skip. We can test this by simply
46592      // checking if any of the mouse functions are available or not.
46593      // NOTE : This reflects only in complete build or modular build.
46594      if (typeof this._updateMouseCoords !== 'undefined') {
46595        this._updateMouseCoords();
46596      }
46597    }
46598
46599    // get notified the next time the browser gives us
46600    // an opportunity to draw.
46601    if (this._loop) {
46602      this._requestAnimId = window.requestAnimationFrame(this._draw);
46603    }
46604  }.bind(this);
46605
46606  this._runFrames = function() {
46607    if (this._updateInterval) {
46608      clearInterval(this._updateInterval);
46609    }
46610  }.bind(this);
46611
46612  this._setProperty = function(prop, value) {
46613    this[prop] = value;
46614    if (this._isGlobal) {
46615      window[prop] = value;
46616    }
46617  }.bind(this);
46618
46619  /**
46620   * Removes the entire p5 sketch. This will remove the canvas and any
46621   * elements created by p5.js. It will also stop the draw loop and unbind
46622   * any properties or methods from the window global scope. It will
46623   * leave a variable p5 in case you wanted to create a new p5 sketch.
46624   * If you like, you can set p5 = null to erase it. While all functions and
46625   * variables and objects created by the p5 library will be removed, any
46626   * other global variables created by your code will remain.
46627   *
46628   * @method remove
46629   * @example
46630   * <div class='norender'><code>
46631   * function draw() {
46632   *   ellipse(50, 50, 10, 10);
46633   * }
46634   *
46635   * function mousePressed() {
46636   *   remove(); // remove whole sketch on mouse press
46637   * }
46638   * </code></div>
46639   *
46640   * @alt
46641   * nothing displayed
46642   *
46643   */
46644  this.remove = function() {
46645    var loadingScreen = document.getElementById(this._loadingScreenId);
46646    if (loadingScreen) {
46647      loadingScreen.parentNode.removeChild(loadingScreen);
46648      // Add 1 to preload counter to prevent the sketch ever executing setup()
46649      this._incrementPreload();
46650    }
46651    if (this._curElement) {
46652      // stop draw
46653      this._loop = false;
46654      if (this._requestAnimId) {
46655        window.cancelAnimationFrame(this._requestAnimId);
46656      }
46657
46658      // unregister events sketch-wide
46659      for (var ev in this._events) {
46660        window.removeEventListener(ev, this._events[ev]);
46661      }
46662
46663      // remove DOM elements created by p5, and listeners
46664      for (var i = 0; i < this._elements.length; i++) {
46665        var e = this._elements[i];
46666        if (e.elt.parentNode) {
46667          e.elt.parentNode.removeChild(e.elt);
46668        }
46669        for (var elt_ev in e._events) {
46670          e.elt.removeEventListener(elt_ev, e._events[elt_ev]);
46671        }
46672      }
46673
46674      // call any registered remove functions
46675      var self = this;
46676      this._registeredMethods.remove.forEach(function(f) {
46677        if (typeof f !== 'undefined') {
46678          f.call(self);
46679        }
46680      });
46681    }
46682    // remove window bound properties and methods
46683    if (this._isGlobal) {
46684      for (var p in p5.prototype) {
46685        try {
46686          delete window[p];
46687        } catch (x) {
46688          window[p] = undefined;
46689        }
46690      }
46691      for (var p2 in this) {
46692        if (this.hasOwnProperty(p2)) {
46693          try {
46694            delete window[p2];
46695          } catch (x) {
46696            window[p2] = undefined;
46697          }
46698        }
46699      }
46700      p5.instance = null;
46701    }
46702  }.bind(this);
46703
46704  // call any registered init functions
46705  this._registeredMethods.init.forEach(function(f) {
46706    if (typeof f !== 'undefined') {
46707      f.call(this);
46708    }
46709  }, this);
46710
46711  var friendlyBindGlobal = this._createFriendlyGlobalFunctionBinder();
46712
46713  // If the user has created a global setup or draw function,
46714  // assume "global" mode and make everything global (i.e. on the window)
46715  if (!sketch) {
46716    this._isGlobal = true;
46717    p5.instance = this;
46718    // Loop through methods on the prototype and attach them to the window
46719    for (var p in p5.prototype) {
46720      if (typeof p5.prototype[p] === 'function') {
46721        var ev = p.substring(2);
46722        if (!this._events.hasOwnProperty(ev)) {
46723          if (Math.hasOwnProperty(p) && Math[p] === p5.prototype[p]) {
46724            // Multiple p5 methods are just native Math functions. These can be
46725            // called without any binding.
46726            friendlyBindGlobal(p, p5.prototype[p]);
46727          } else {
46728            friendlyBindGlobal(p, p5.prototype[p].bind(this));
46729          }
46730        }
46731      } else {
46732        friendlyBindGlobal(p, p5.prototype[p]);
46733      }
46734    }
46735    // Attach its properties to the window
46736    for (var p2 in this) {
46737      if (this.hasOwnProperty(p2)) {
46738        friendlyBindGlobal(p2, this[p2]);
46739      }
46740    }
46741  } else {
46742    // Else, the user has passed in a sketch closure that may set
46743    // user-provided 'setup', 'draw', etc. properties on this instance of p5
46744    sketch(this);
46745  }
46746
46747  // Bind events to window (not using container div bc key events don't work)
46748
46749  for (var e in this._events) {
46750    var f = this['_on' + e];
46751    if (f) {
46752      var m = f.bind(this);
46753      window.addEventListener(e, m, { passive: false });
46754      this._events[e] = m;
46755    }
46756  }
46757
46758  var focusHandler = function() {
46759    this._setProperty('focused', true);
46760  }.bind(this);
46761  var blurHandler = function() {
46762    this._setProperty('focused', false);
46763  }.bind(this);
46764  window.addEventListener('focus', focusHandler);
46765  window.addEventListener('blur', blurHandler);
46766  this.registerMethod('remove', function() {
46767    window.removeEventListener('focus', focusHandler);
46768    window.removeEventListener('blur', blurHandler);
46769  });
46770
46771  if (sync) {
46772    this._start();
46773  } else {
46774    if (document.readyState === 'complete') {
46775      this._start();
46776    } else {
46777      window.addEventListener('load', this._start.bind(this), false);
46778    }
46779  }
46780};
46781
46782p5.prototype._initializeInstanceVariables = function() {
46783  this._styles = [];
46784
46785  this._bezierDetail = 20;
46786  this._curveDetail = 20;
46787
46788  this._colorMode = constants.RGB;
46789  this._colorMaxes = {
46790    rgb: [255, 255, 255, 255],
46791    hsb: [360, 100, 100, 1],
46792    hsl: [360, 100, 100, 1]
46793  };
46794};
46795
46796// This is a pointer to our global mode p5 instance, if we're in
46797// global mode.
46798p5.instance = null;
46799
46800// Allows for the friendly error system to be turned off when creating a sketch,
46801// which can give a significant boost to performance when needed.
46802p5.disableFriendlyErrors = false;
46803
46804// attach constants to p5 prototype
46805for (var k in constants) {
46806  p5.prototype[k] = constants[k];
46807}
46808
46809// functions that cause preload to wait
46810// more can be added by using registerPreloadMethod(func)
46811p5.prototype._preloadMethods = {
46812  loadJSON: p5.prototype,
46813  loadImage: p5.prototype,
46814  loadStrings: p5.prototype,
46815  loadXML: p5.prototype,
46816  loadBytes: p5.prototype,
46817  loadShape: p5.prototype,
46818  loadTable: p5.prototype,
46819  loadFont: p5.prototype,
46820  loadModel: p5.prototype,
46821  loadShader: p5.prototype
46822};
46823
46824p5.prototype._registeredMethods = { init: [], pre: [], post: [], remove: [] };
46825
46826p5.prototype._registeredPreloadMethods = {};
46827
46828p5.prototype.registerPreloadMethod = function(fnString, obj) {
46829  // obj = obj || p5.prototype;
46830  if (!p5.prototype._preloadMethods.hasOwnProperty(fnString)) {
46831    p5.prototype._preloadMethods[fnString] = obj;
46832  }
46833};
46834
46835p5.prototype.registerMethod = function(name, m) {
46836  var target = this || p5.prototype;
46837  if (!target._registeredMethods.hasOwnProperty(name)) {
46838    target._registeredMethods[name] = [];
46839  }
46840  target._registeredMethods[name].push(m);
46841};
46842
46843p5.prototype._createFriendlyGlobalFunctionBinder = function(options) {
46844  options = options || {};
46845
46846  var globalObject = options.globalObject || window;
46847  var log = options.log || console.log.bind(console);
46848  var propsToForciblyOverwrite = {
46849    // p5.print actually always overwrites an existing global function,
46850    // albeit one that is very unlikely to be used:
46851    //
46852    //   https://developer.mozilla.org/en-US/docs/Web/API/Window/print
46853    print: true
46854  };
46855
46856  return function(prop, value) {
46857    if (
46858      !p5.disableFriendlyErrors &&
46859      typeof IS_MINIFIED === 'undefined' &&
46860      typeof value === 'function' &&
46861      !(prop in p5.prototype._preloadMethods)
46862    ) {
46863      try {
46864        // Because p5 has so many common function names, it's likely
46865        // that users may accidentally overwrite global p5 functions with
46866        // their own variables. Let's allow this but log a warning to
46867        // help users who may be doing this unintentionally.
46868        //
46869        // For more information, see:
46870        //
46871        //   https://github.com/processing/p5.js/issues/1317
46872
46873        if (prop in globalObject && !(prop in propsToForciblyOverwrite)) {
46874          throw new Error('global "' + prop + '" already exists');
46875        }
46876
46877        // It's possible that this might throw an error because there
46878        // are a lot of edge-cases in which `Object.defineProperty` might
46879        // not succeed; since this functionality is only intended to
46880        // help beginners anyways, we'll just catch such an exception
46881        // if it occurs, and fall back to legacy behavior.
46882        Object.defineProperty(globalObject, prop, {
46883          configurable: true,
46884          enumerable: true,
46885          get: function() {
46886            return value;
46887          },
46888          set: function(newValue) {
46889            Object.defineProperty(globalObject, prop, {
46890              configurable: true,
46891              enumerable: true,
46892              value: newValue,
46893              writable: true
46894            });
46895            log(
46896              'You just changed the value of "' +
46897                prop +
46898                '", which was ' +
46899                "a p5 function. This could cause problems later if you're " +
46900                'not careful.'
46901            );
46902          }
46903        });
46904      } catch (e) {
46905        log(
46906          'p5 had problems creating the global function "' +
46907            prop +
46908            '", ' +
46909            'possibly because your code is already using that name as ' +
46910            'a variable. You may want to rename your variable to something ' +
46911            'else.'
46912        );
46913        globalObject[prop] = value;
46914      }
46915    } else {
46916      globalObject[prop] = value;
46917    }
46918  };
46919};
46920
46921module.exports = p5;
46922
46923},{"./constants":21,"./shim":32}],23:[function(_dereq_,module,exports){
46924/**
46925 * @module Shape
46926 * @submodule Curves
46927 * @for p5
46928 * @requires core
46929 */
46930
46931'use strict';
46932
46933var p5 = _dereq_('./core');
46934_dereq_('./error_helpers');
46935
46936/**
46937 * Draws a cubic Bezier curve on the screen. These curves are defined by a
46938 * series of anchor and control points. The first two parameters specify
46939 * the first anchor point and the last two parameters specify the other
46940 * anchor point, which become the first and last points on the curve. The
46941 * middle parameters specify the two control points which define the shape
46942 * of the curve. Approximately speaking, control points "pull" the curve
46943 * towards them.<br /><br />Bezier curves were developed by French
46944 * automotive engineer Pierre Bezier, and are commonly used in computer
46945 * graphics to define gently sloping curves. See also curve().
46946 *
46947 * @method bezier
46948 * @param  {Number} x1 x-coordinate for the first anchor point
46949 * @param  {Number} y1 y-coordinate for the first anchor point
46950 * @param  {Number} x2 x-coordinate for the first control point
46951 * @param  {Number} y2 y-coordinate for the first control point
46952 * @param  {Number} x3 x-coordinate for the second control point
46953 * @param  {Number} y3 y-coordinate for the second control point
46954 * @param  {Number} x4 x-coordinate for the second anchor point
46955 * @param  {Number} y4 y-coordinate for the second anchor point
46956 * @chainable
46957 * @example
46958 * <div>
46959 * <code>
46960 * noFill();
46961 * stroke(255, 102, 0);
46962 * line(85, 20, 10, 10);
46963 * line(90, 90, 15, 80);
46964 * stroke(0, 0, 0);
46965 * bezier(85, 20, 10, 10, 90, 90, 15, 80);
46966 * </code>
46967 * </div>
46968 *
46969 * <div>
46970 * <code>
46971 * background(0, 0, 0);
46972 * noFill();
46973 * stroke(255);
46974 * bezier(250, 250, 0, 100, 100, 0, 100, 0, 0, 0, 100, 0);
46975 * </code>
46976 * </div>
46977 *
46978 * @alt
46979 * stretched black s-shape in center with orange lines extending from end points.
46980 * stretched black s-shape with 10 5x5 white ellipses along the shape.
46981 * stretched black s-shape with 7 5x5 ellipses and orange lines along the shape.
46982 * stretched black s-shape with 17 small orange lines extending from under shape.
46983 * horseshoe shape with orange ends facing left and black curved center.
46984 * horseshoe shape with orange ends facing left and black curved center.
46985 * Line shaped like right-facing arrow,points move with mouse-x and warp shape.
46986 * horizontal line that hooks downward on the right and 13 5x5 ellipses along it.
46987 * right curving line mid-right of canvas with 7 short lines radiating from it.
46988 */
46989/**
46990 * @method bezier
46991 * @param  {Number} x1
46992 * @param  {Number} y1
46993 * @param  {Number} z1 z-coordinate for the first anchor point
46994 * @param  {Number} x2
46995 * @param  {Number} y2
46996 * @param  {Number} z2 z-coordinate for the first control point
46997 * @param  {Number} x3
46998 * @param  {Number} y3
46999 * @param  {Number} z3 z-coordinate for the second control point
47000 * @param  {Number} x4
47001 * @param  {Number} y4
47002 * @param  {Number} z4 z-coordinate for the second anchor point
47003 * @chainable
47004 */
47005p5.prototype.bezier = function() {
47006  p5._validateParameters('bezier', arguments);
47007
47008  if (this._renderer._doStroke || this._renderer._doFill) {
47009    this._renderer.bezier.apply(this._renderer, arguments);
47010  }
47011
47012  return this;
47013};
47014
47015/**
47016 * Sets the resolution at which Beziers display.
47017 *
47018 * The default value is 20.
47019 *
47020 * This function is only useful when using the WEBGL renderer
47021 * as the default canvas renderer does not use this information.
47022 *
47023 * @method bezierDetail
47024 * @param {Number} detail resolution of the curves
47025 * @chainable
47026 * @example
47027 * <div modernizr='webgl'>
47028 * <code>
47029 * function setup() {
47030 *   createCanvas(100, 100, WEBGL);
47031 *   noFill();
47032 *
47033 *   bezierDetail(5);
47034 * }
47035 *
47036 * function draw() {
47037 *   background(200);
47038 *
47039 *   // prettier-ignore
47040 *   bezier(-40, -40, 0,
47041 *           90, -40, 0,
47042 *          -90,  40, 0,
47043 *           40,  40, 0);
47044 * }
47045 * </code>
47046 * </div>
47047 *
47048 * @alt
47049 * stretched black s-shape with a low level of bezier detail
47050 *
47051 */
47052p5.prototype.bezierDetail = function(d) {
47053  p5._validateParameters('bezierDetail', arguments);
47054  this._bezierDetail = d;
47055  return this;
47056};
47057
47058/**
47059 * Evaluates the Bezier at position t for points a, b, c, d.
47060 * The parameters a and d are the first and last points
47061 * on the curve, and b and c are the control points.
47062 * The final parameter t varies between 0 and 1.
47063 * This can be done once with the x coordinates and a second time
47064 * with the y coordinates to get the location of a bezier curve at t.
47065 *
47066 * @method bezierPoint
47067 * @param {Number} a coordinate of first point on the curve
47068 * @param {Number} b coordinate of first control point
47069 * @param {Number} c coordinate of second control point
47070 * @param {Number} d coordinate of second point on the curve
47071 * @param {Number} t value between 0 and 1
47072 * @return {Number} the value of the Bezier at position t
47073 * @example
47074 * <div>
47075 * <code>
47076 * noFill();
47077 * var x1 = 85,
47078  x2 = 10,
47079  x3 = 90,
47080  x4 = 15;
47081 * var y1 = 20,
47082  y2 = 10,
47083  y3 = 90,
47084  y4 = 80;
47085 * bezier(x1, y1, x2, y2, x3, y3, x4, y4);
47086 * fill(255);
47087 * var steps = 10;
47088 * for (var i = 0; i <= steps; i++) {
47089 *   var t = i / steps;
47090 *   var x = bezierPoint(x1, x2, x3, x4, t);
47091 *   var y = bezierPoint(y1, y2, y3, y4, t);
47092 *   ellipse(x, y, 5, 5);
47093 * }
47094 * </code>
47095 * </div>
47096 *
47097 * @alt
47098 * stretched black s-shape with 17 small orange lines extending from under shape.
47099 *
47100 */
47101p5.prototype.bezierPoint = function(a, b, c, d, t) {
47102  p5._validateParameters('bezierPoint', arguments);
47103
47104  var adjustedT = 1 - t;
47105  return (
47106    Math.pow(adjustedT, 3) * a +
47107    3 * Math.pow(adjustedT, 2) * t * b +
47108    3 * adjustedT * Math.pow(t, 2) * c +
47109    Math.pow(t, 3) * d
47110  );
47111};
47112
47113/**
47114 * Evaluates the tangent to the Bezier at position t for points a, b, c, d.
47115 * The parameters a and d are the first and last points
47116 * on the curve, and b and c are the control points.
47117 * The final parameter t varies between 0 and 1.
47118 *
47119 * @method bezierTangent
47120 * @param {Number} a coordinate of first point on the curve
47121 * @param {Number} b coordinate of first control point
47122 * @param {Number} c coordinate of second control point
47123 * @param {Number} d coordinate of second point on the curve
47124 * @param {Number} t value between 0 and 1
47125 * @return {Number} the tangent at position t
47126 * @example
47127 * <div>
47128 * <code>
47129 * noFill();
47130 * bezier(85, 20, 10, 10, 90, 90, 15, 80);
47131 * var steps = 6;
47132 * fill(255);
47133 * for (var i = 0; i <= steps; i++) {
47134 *   var t = i / steps;
47135 *   // Get the location of the point
47136 *   var x = bezierPoint(85, 10, 90, 15, t);
47137 *   var y = bezierPoint(20, 10, 90, 80, t);
47138 *   // Get the tangent points
47139 *   var tx = bezierTangent(85, 10, 90, 15, t);
47140 *   var ty = bezierTangent(20, 10, 90, 80, t);
47141 *   // Calculate an angle from the tangent points
47142 *   var a = atan2(ty, tx);
47143 *   a += PI;
47144 *   stroke(255, 102, 0);
47145 *   line(x, y, cos(a) * 30 + x, sin(a) * 30 + y);
47146 *   // The following line of code makes a line
47147 *   // inverse of the above line
47148 *   //line(x, y, cos(a)*-30 + x, sin(a)*-30 + y);
47149 *   stroke(0);
47150 *   ellipse(x, y, 5, 5);
47151 * }
47152 * </code>
47153 * </div>
47154 *
47155 * <div>
47156 * <code>
47157 * noFill();
47158 * bezier(85, 20, 10, 10, 90, 90, 15, 80);
47159 * stroke(255, 102, 0);
47160 * var steps = 16;
47161 * for (var i = 0; i <= steps; i++) {
47162 *   var t = i / steps;
47163 *   var x = bezierPoint(85, 10, 90, 15, t);
47164 *   var y = bezierPoint(20, 10, 90, 80, t);
47165 *   var tx = bezierTangent(85, 10, 90, 15, t);
47166 *   var ty = bezierTangent(20, 10, 90, 80, t);
47167 *   var a = atan2(ty, tx);
47168 *   a -= HALF_PI;
47169 *   line(x, y, cos(a) * 8 + x, sin(a) * 8 + y);
47170 * }
47171 * </code>
47172 * </div>
47173 *
47174 * @alt
47175 * s-shaped line with 17 short orange lines extending from underside of shape
47176 *
47177 */
47178p5.prototype.bezierTangent = function(a, b, c, d, t) {
47179  p5._validateParameters('bezierTangent', arguments);
47180
47181  var adjustedT = 1 - t;
47182  return (
47183    3 * d * Math.pow(t, 2) -
47184    3 * c * Math.pow(t, 2) +
47185    6 * c * adjustedT * t -
47186    6 * b * adjustedT * t +
47187    3 * b * Math.pow(adjustedT, 2) -
47188    3 * a * Math.pow(adjustedT, 2)
47189  );
47190};
47191
47192/**
47193 * Draws a curved line on the screen between two points, given as the
47194 * middle four parameters. The first two parameters are a control point, as
47195 * if the curve came from this point even though it's not drawn. The last
47196 * two parameters similarly describe the other control point. <br /><br />
47197 * Longer curves can be created by putting a series of curve() functions
47198 * together or using curveVertex(). An additional function called
47199 * curveTightness() provides control for the visual quality of the curve.
47200 * The curve() function is an implementation of Catmull-Rom splines.
47201 *
47202 * @method curve
47203 * @param  {Number} x1 x-coordinate for the beginning control point
47204 * @param  {Number} y1 y-coordinate for the beginning control point
47205 * @param  {Number} x2 x-coordinate for the first point
47206 * @param  {Number} y2 y-coordinate for the first point
47207 * @param  {Number} x3 x-coordinate for the second point
47208 * @param  {Number} y3 y-coordinate for the second point
47209 * @param  {Number} x4 x-coordinate for the ending control point
47210 * @param  {Number} y4 y-coordinate for the ending control point
47211 * @chainable
47212 * @example
47213 * <div>
47214 * <code>
47215 * noFill();
47216 * stroke(255, 102, 0);
47217 * curve(5, 26, 5, 26, 73, 24, 73, 61);
47218 * stroke(0);
47219 * curve(5, 26, 73, 24, 73, 61, 15, 65);
47220 * stroke(255, 102, 0);
47221 * curve(73, 24, 73, 61, 15, 65, 15, 65);
47222 * </code>
47223 * </div>
47224 * <div>
47225 * <code>
47226 * // Define the curve points as JavaScript objects
47227 * var p1 = { x: 5, y: 26 },
47228  p2 = { x: 73, y: 24 };
47229 * var p3 = { x: 73, y: 61 },
47230  p4 = { x: 15, y: 65 };
47231 * noFill();
47232 * stroke(255, 102, 0);
47233 * curve(p1.x, p1.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y);
47234 * stroke(0);
47235 * curve(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y);
47236 * stroke(255, 102, 0);
47237 * curve(p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, p4.x, p4.y);
47238 * </code>
47239 * </div>
47240 * <div>
47241 * <code>
47242 * noFill();
47243 * stroke(255, 102, 0);
47244 * curve(5, 26, 0, 5, 26, 0, 73, 24, 0, 73, 61, 0);
47245 * stroke(0);
47246 * curve(5, 26, 0, 73, 24, 0, 73, 61, 0, 15, 65, 0);
47247 * stroke(255, 102, 0);
47248 * curve(73, 24, 0, 73, 61, 0, 15, 65, 0, 15, 65, 0);
47249 * </code>
47250 * </div>
47251 *
47252 * @alt
47253 * horseshoe shape with orange ends facing left and black curved center.
47254 * horseshoe shape with orange ends facing left and black curved center.
47255 * curving black and orange lines.
47256 */
47257/**
47258 * @method curve
47259 * @param  {Number} x1
47260 * @param  {Number} y1
47261 * @param  {Number} z1 z-coordinate for the beginning control point
47262 * @param  {Number} x2
47263 * @param  {Number} y2
47264 * @param  {Number} z2 z-coordinate for the first point
47265 * @param  {Number} x3
47266 * @param  {Number} y3
47267 * @param  {Number} z3 z-coordinate for the second point
47268 * @param  {Number} x4
47269 * @param  {Number} y4
47270 * @param  {Number} z4 z-coordinate for the ending control point
47271 * @chainable
47272 */
47273p5.prototype.curve = function() {
47274  p5._validateParameters('curve', arguments);
47275
47276  if (this._renderer._doStroke) {
47277    this._renderer.curve.apply(this._renderer, arguments);
47278  }
47279
47280  return this;
47281};
47282
47283/**
47284 * Sets the resolution at which curves display.
47285 *
47286 * The default value is 20.
47287 *
47288 * This function is only useful when using the WEBGL renderer
47289 * as the default canvas renderer does not use this
47290 * information.
47291 *
47292 * @method curveDetail
47293 * @param {Number} resolution of the curves
47294 * @chainable
47295 * @example
47296 * <div modernizr='webgl'>
47297 * <code>
47298 * function setup() {
47299 *   createCanvas(100, 100, WEBGL);
47300 *
47301 *   curveDetail(5);
47302 * }
47303 * function draw() {
47304 *   background(200);
47305 *
47306 *   // prettier-ignore
47307 *   curve( 250, 600, 0,
47308 *          -30,  40, 0,
47309 *           30,  30, 0,
47310 *         -250, 600, 0);
47311 * }
47312 * </code>
47313 * </div>
47314 *
47315 * @alt
47316 * white arch shape with a low level of curve detail.
47317 *
47318 */
47319p5.prototype.curveDetail = function(d) {
47320  p5._validateParameters('curveDetail', arguments);
47321  this._curveDetail = d;
47322  return this;
47323};
47324
47325/**
47326 * Modifies the quality of forms created with curve() and curveVertex().
47327 * The parameter tightness determines how the curve fits to the vertex
47328 * points. The value 0.0 is the default value for tightness (this value
47329 * defines the curves to be Catmull-Rom splines) and the value 1.0 connects
47330 * all the points with straight lines. Values within the range -5.0 and 5.0
47331 * will deform the curves but will leave them recognizable and as values
47332 * increase in magnitude, they will continue to deform.
47333 *
47334 * @method curveTightness
47335 * @param {Number} amount of deformation from the original vertices
47336 * @chainable
47337 * @example
47338 * <div>
47339 * <code>
47340 * // Move the mouse left and right to see the curve change
47341 *
47342 * function setup() {
47343 *   createCanvas(100, 100);
47344 *   noFill();
47345 * }
47346 *
47347 * function draw() {
47348 *   background(204);
47349 *   var t = map(mouseX, 0, width, -5, 5);
47350 *   curveTightness(t);
47351 *   beginShape();
47352 *   curveVertex(10, 26);
47353 *   curveVertex(10, 26);
47354 *   curveVertex(83, 24);
47355 *   curveVertex(83, 61);
47356 *   curveVertex(25, 65);
47357 *   curveVertex(25, 65);
47358 *   endShape();
47359 * }
47360 * </code>
47361 * </div>
47362 *
47363 * @alt
47364 * Line shaped like right-facing arrow,points move with mouse-x and warp shape.
47365 */
47366p5.prototype.curveTightness = function(t) {
47367  p5._validateParameters('curveTightness', arguments);
47368  this._renderer._curveTightness = t;
47369};
47370
47371/**
47372 * Evaluates the curve at position t for points a, b, c, d.
47373 * The parameter t varies between 0 and 1, a and d are points
47374 * on the curve, and b and c are the control points.
47375 * This can be done once with the x coordinates and a second time
47376 * with the y coordinates to get the location of a curve at t.
47377 *
47378 * @method curvePoint
47379 * @param {Number} a coordinate of first point on the curve
47380 * @param {Number} b coordinate of first control point
47381 * @param {Number} c coordinate of second control point
47382 * @param {Number} d coordinate of second point on the curve
47383 * @param {Number} t value between 0 and 1
47384 * @return {Number} bezier value at position t
47385 * @example
47386 * <div>
47387 * <code>
47388 * noFill();
47389 * curve(5, 26, 5, 26, 73, 24, 73, 61);
47390 * curve(5, 26, 73, 24, 73, 61, 15, 65);
47391 * fill(255);
47392 * ellipseMode(CENTER);
47393 * var steps = 6;
47394 * for (var i = 0; i <= steps; i++) {
47395 *   var t = i / steps;
47396 *   var x = curvePoint(5, 5, 73, 73, t);
47397 *   var y = curvePoint(26, 26, 24, 61, t);
47398 *   ellipse(x, y, 5, 5);
47399 *   x = curvePoint(5, 73, 73, 15, t);
47400 *   y = curvePoint(26, 24, 61, 65, t);
47401 *   ellipse(x, y, 5, 5);
47402 * }
47403 * </code>
47404 * </div>
47405 *
47406 *line hooking down to right-bottom with 13 5x5 white ellipse points
47407 */
47408p5.prototype.curvePoint = function(a, b, c, d, t) {
47409  p5._validateParameters('curvePoint', arguments);
47410
47411  var t3 = t * t * t,
47412    t2 = t * t,
47413    f1 = -0.5 * t3 + t2 - 0.5 * t,
47414    f2 = 1.5 * t3 - 2.5 * t2 + 1.0,
47415    f3 = -1.5 * t3 + 2.0 * t2 + 0.5 * t,
47416    f4 = 0.5 * t3 - 0.5 * t2;
47417  return a * f1 + b * f2 + c * f3 + d * f4;
47418};
47419
47420/**
47421 * Evaluates the tangent to the curve at position t for points a, b, c, d.
47422 * The parameter t varies between 0 and 1, a and d are points on the curve,
47423 * and b and c are the control points.
47424 *
47425 * @method curveTangent
47426 * @param {Number} a coordinate of first point on the curve
47427 * @param {Number} b coordinate of first control point
47428 * @param {Number} c coordinate of second control point
47429 * @param {Number} d coordinate of second point on the curve
47430 * @param {Number} t value between 0 and 1
47431 * @return {Number} the tangent at position t
47432 * @example
47433 * <div>
47434 * <code>
47435 * noFill();
47436 * curve(5, 26, 73, 24, 73, 61, 15, 65);
47437 * var steps = 6;
47438 * for (var i = 0; i <= steps; i++) {
47439 *   var t = i / steps;
47440 *   var x = curvePoint(5, 73, 73, 15, t);
47441 *   var y = curvePoint(26, 24, 61, 65, t);
47442 *   //ellipse(x, y, 5, 5);
47443 *   var tx = curveTangent(5, 73, 73, 15, t);
47444 *   var ty = curveTangent(26, 24, 61, 65, t);
47445 *   var a = atan2(ty, tx);
47446 *   a -= PI / 2.0;
47447 *   line(x, y, cos(a) * 8 + x, sin(a) * 8 + y);
47448 * }
47449 * </code>
47450 * </div>
47451 *
47452 * @alt
47453 *right curving line mid-right of canvas with 7 short lines radiating from it.
47454 */
47455p5.prototype.curveTangent = function(a, b, c, d, t) {
47456  p5._validateParameters('curveTangent', arguments);
47457
47458  var t2 = t * t,
47459    f1 = -3 * t2 / 2 + 2 * t - 0.5,
47460    f2 = 9 * t2 / 2 - 5 * t,
47461    f3 = -9 * t2 / 2 + 4 * t + 0.5,
47462    f4 = 3 * t2 / 2 - t;
47463  return a * f1 + b * f2 + c * f3 + d * f4;
47464};
47465
47466module.exports = p5;
47467
47468},{"./core":22,"./error_helpers":25}],24:[function(_dereq_,module,exports){
47469/**
47470 * @module Environment
47471 * @submodule Environment
47472 * @for p5
47473 * @requires core
47474 * @requires constants
47475 */
47476
47477'use strict';
47478
47479var p5 = _dereq_('./core');
47480var C = _dereq_('./constants');
47481
47482var standardCursors = [C.ARROW, C.CROSS, C.HAND, C.MOVE, C.TEXT, C.WAIT];
47483
47484p5.prototype._frameRate = 0;
47485p5.prototype._lastFrameTime = window.performance.now();
47486p5.prototype._targetFrameRate = 60;
47487
47488var _windowPrint = window.print;
47489
47490/**
47491 * The print() function writes to the console area of your browser.
47492 * This function is often helpful for looking at the data a program is
47493 * producing. This function creates a new line of text for each call to
47494 * the function. Individual elements can be
47495 * separated with quotes ("") and joined with the addition operator (+).
47496 *
47497 * @method print
47498 * @param {Any} contents any combination of Number, String, Object, Boolean,
47499 *                       Array to print
47500 * @example
47501 * <div><code class='norender'>
47502 * var x = 10;
47503 * print('The value of x is ' + x);
47504 * // prints "The value of x is 10"
47505 * </code></div>
47506 * @alt
47507 * default grey canvas
47508 */
47509p5.prototype.print = function() {
47510  if (!arguments.length) {
47511    _windowPrint();
47512  } else {
47513    console.log.apply(console, arguments);
47514  }
47515};
47516
47517/**
47518 * The system variable frameCount contains the number of frames that have
47519 * been displayed since the program started. Inside setup() the value is 0,
47520 * after the first iteration of draw it is 1, etc.
47521 *
47522 * @property {Integer} frameCount
47523 * @readOnly
47524 * @example
47525 *   <div><code>
47526 * function setup() {
47527 *   frameRate(30);
47528 *   textSize(20);
47529 *   textSize(30);
47530 *   textAlign(CENTER);
47531 * }
47532 *
47533 * function draw() {
47534 *   background(200);
47535 *   text(frameCount, width / 2, height / 2);
47536 * }
47537</code></div>
47538 *
47539 * @alt
47540 * numbers rapidly counting upward with frame count set to 30.
47541 *
47542 */
47543p5.prototype.frameCount = 0;
47544
47545/**
47546 * Confirms if the window a p5.js program is in is "focused," meaning that
47547 * the sketch will accept mouse or keyboard input. This variable is
47548 * "true" if the window is focused and "false" if not.
47549 *
47550 * @property {Boolean}
47550 focused
47551 * @readOnly
47552 * @example
47553 * <div><code>
47554 * // To demonstrate, put two windows side by side.
47555 * // Click on the window that the p5 sketch isn't in!
47556 * function draw() {
47557 *   background(200);
47558 *   noStroke();
47559 *   fill(0, 200, 0);
47560 *   ellipse(25, 25, 50, 50);
47561 *
47562 *   if (!focused) {
47563    // or "if (focused === false)"
47564 *     stroke(200, 0, 0);
47565 *     line(0, 0, 100, 100);
47566 *     line(100, 0, 0, 100);
47567 *   }
47568 * }
47569 * </code></div>
47570 *
47571 * @alt
47572 * green 50x50 ellipse at top left. Red X covers canvas when page focus changes
47573 *
47574 */
47575p5.prototype.focused = document.hasFocus();
47576
47577/**
47578 * Sets the cursor to a predefined symbol or an image, or makes it visible
47579 * if already hidden. If you are trying to set an image as the cursor, the
47580 * recommended size is 16x16 or 32x32 pixels. It is not possible to load an
47581 * image as the cursor if you are exporting your program for the Web, and not
47582 * all MODES work with all browsers. The values for parameters x and y must
47583 * be less than the dimensions of the image.
47584 *
47585 * @method cursor
47586 * @param {String|Constant} type either ARROW, CROSS, HAND, MOVE, TEXT, or
47587 *                               WAIT, or path for image
47588 * @param {Number}          [x]  the horizontal active spot of the cursor
47589 * @param {Number}          [y]  the vertical active spot of the cursor
47590 * @example
47591 * <div><code>
47592 * // Move the mouse left and right across the image
47593 * // to see the cursor change from a cross to a hand
47594 * function draw() {
47595 *   line(width / 2, 0, width / 2, height);
47596 *   if (mouseX < 50) {
47597 *     cursor(CROSS);
47598 *   } else {
47599 *     cursor(HAND);
47600 *   }
47601 * }
47602 * </code></div>
47603 *
47604 * @alt
47605 * horizontal line divides canvas. cursor on left is a cross, right is hand.
47606 *
47607 */
47608p5.prototype.cursor = function(type, x, y) {
47609  var cursor = 'auto';
47610  var canvas = this._curElement.elt;
47611  if (standardCursors.indexOf(type) > -1) {
47612    // Standard css cursor
47613    cursor = type;
47614  } else if (typeof type === 'string') {
47615    var coords = '';
47616    if (x && y && (typeof x === 'number' && typeof y === 'number')) {
47617      // Note that x and y values must be unit-less positive integers < 32
47618      // https://developer.mozilla.org/en-US/docs/Web/CSS/cursor
47619      coords = x + ' ' + y;
47620    }
47621    if (
47622      type.substring(0, 7) === 'http://' ||
47623      type.substring(0, 8) === 'https://'
47624    ) {
47625      // Image (absolute url)
47626      cursor = 'url(' + type + ') ' + coords + ', auto';
47627    } else if (/\.(cur|jpg|jpeg|gif|png|CUR|JPG|JPEG|GIF|PNG)$/.test(type)) {
47628      // Image file (relative path) - Separated for performance reasons
47629      cursor = 'url(' + type + ') ' + coords + ', auto';
47630    } else {
47631      // Any valid string for the css cursor property
47632      cursor = type;
47633    }
47634  }
47635  canvas.style.cursor = cursor;
47636};
47637
47638/**
47639 * Specifies the number of frames to be displayed every second. For example,
47640 * the function call frameRate(30) will attempt to refresh 30 times a second.
47641 * If the processor is not fast enough to maintain the specified rate, the
47642 * frame rate will not be achieved. Setting the frame rate within setup() is
47643 * recommended. The default rate is 60 frames per second. This is the same as
47644 * setFrameRate(val).
47645 * <br><br>
47646 * Calling frameRate() with no arguments returns the current framerate. The
47647 * draw function must run at least once before it will return a value. This
47648 * is the same as getFrameRate().
47649 * <br><br>
47650 * Calling frameRate() with arguments that are not of the type numbers
47651 * or are non positive also returns current framerate.
47652 *
47653 * @method frameRate
47654 * @param  {Number} fps number of frames to be displayed every second
47655 * @chainable
47656 *
47657 * @example
47658 *
47659 * <div><code>
47660 * var rectX = 0;
47661 * var fr = 30; //starting FPS
47662 * var clr;
47663 *
47664 * function setup() {
47665 *   background(200);
47666 *   frameRate(fr); // Attempt to refresh at starting FPS
47667 *   clr = color(255, 0, 0);
47668 * }
47669 *
47670 * function draw() {
47671 *   background(200);
47672 *   rectX = rectX += 1; // Move Rectangle
47673 *
47674 *   if (rectX >= width) {
47675    // If you go off screen.
47676 *     if (fr === 30) {
47677 *       clr = color(0, 0, 255);
47678 *       fr = 10;
47679 *       frameRate(fr); // make frameRate 10 FPS
47680 *     } else {
47681 *       clr = color(255, 0, 0);
47682 *       fr = 30;
47683 *       frameRate(fr); // make frameRate 30 FPS
47684 *     }
47685 *     rectX = 0;
47686 *   }
47687 *   fill(clr);
47688 *   rect(rectX, 40, 20, 20);
47689 * }
47690 * </code></div>
47691 *
47692 * @alt
47693 * blue rect moves left to right, followed by red rect moving faster. Loops.
47694 *
47695 */
47696/**
47697 * @method frameRate
47698 * @return {Number}       current frameRate
47699 */
47700p5.prototype.frameRate = function(fps) {
47701  p5._validateParameters('frameRate', arguments);
47702  if (typeof fps !== 'number' || fps < 0) {
47703    return this._frameRate;
47704  } else {
47705    this._setProperty('_targetFrameRate', fps);
47706    this._runFrames();
47707    return this;
47708  }
47709};
47710/**
47711 * Returns the current framerate.
47712 *
47713 * @private
47714 * @return {Number} current frameRate
47715 */
47716p5.prototype.getFrameRate = function() {
47717  return this.frameRate();
47718};
47719
47720/**
47721 * Specifies the number of frames to be displayed every second. For example,
47722 * the function call frameRate(30) will attempt to refresh 30 times a second.
47723 * If the processor is not fast enough to maintain the specified rate, the
47724 * frame rate will not be achieved. Setting the frame rate within setup() is
47725 * recommended. The default rate is 60 frames per second.
47726 *
47727 * Calling frameRate() with no arguments returns the current framerate.
47728 *
47729 * @private
47730 * @param {Number} [fps] number of frames to be displayed every second
47731 */
47732p5.prototype.setFrameRate = function(fps) {
47733  return this.frameRate(fps);
47734};
47735
47736/**
47737 * Hides the cursor from view.
47738 *
47739 * @method noCursor
47740 * @example
47741 * <div><code>
47742 * function setup() {
47743 *   noCursor();
47744 * }
47745 *
47746 * function draw() {
47747 *   background(200);
47748 *   ellipse(mouseX, mouseY, 10, 10);
47749 * }
47750 * </code></div>
47751 *
47752 *
47753 * @alt
47754 * cursor becomes 10x 10 white ellipse the moves with mouse x and y.
47755 *
47756 */
47757p5.prototype.noCursor = function() {
47758  this._curElement.elt.style.cursor = 'none';
47759};
47760
47761/**
47762 * System variable that stores the width of the entire screen display. This
47763 * is used to run a full-screen program on any display size.
47764 *
47765 * @property {Number} displayWidth
47766 * @readOnly
47767 * @example
47768 * <div class="norender"><code>
47769 * createCanvas(displayWidth, displayHeight);
47770 * </code></div>
47771 *
47772 * @alt
47773 * cursor becomes 10x 10 white ellipse the moves with mouse x and y.
47774 *
47775 */
47776p5.prototype.displayWidth = screen.width;
47777
47778/**
47779 * System variable that stores the height of the entire screen display. This
47780 * is used to run a full-screen program on any display size.
47781 *
47782 * @property {Number} displayHeight
47783 * @readOnly
47784 * @example
47785 * <div class="norender"><code>
47786 * createCanvas(displayWidth, displayHeight);
47787 * </code></div>
47788 *
47789 * @alt
47790 * no display.
47791 *
47792 */
47793p5.prototype.displayHeight = screen.height;
47794
47795/**
47796 * System variable that stores the width of the inner window, it maps to
47797 * window.innerWidth.
47798 *
47799 * @property {Number} windowWidth
47800 * @readOnly
47801 * @example
47802 * <div class="norender"><code>
47803 * createCanvas(windowWidth, windowHeight);
47804 * </code></div>
47805 *
47806 * @alt
47807 * no display.
47808 *
47809 */
47810p5.prototype.windowWidth = getWindowWidth();
47811/**
47812 * System variable that stores the height of the inner window, it maps to
47813 * window.innerHeight.
47814 *
47815 * @property {Number} windowHeight
47816 * @readOnly
47817 * @example
47818 * <div class="norender"><code>
47819 * createCanvas(windowWidth, windowHeight);
47820 * </code></div>
47821 *@alt
47822 * no display.
47823 *
47824 */
47825p5.prototype.windowHeight = getWindowHeight();
47826
47827/**
47828 * The windowResized() function is called once every time the browser window
47829 * is resized. This is a good place to resize the canvas or do any other
47830 * adjustments to accommodate the new window size.
47831 *
47832 * @method windowResized
47833 * @example
47834 * <div class="norender"><code>
47835 * function setup() {
47836 *   createCanvas(windowWidth, windowHeight);
47837 * }
47838 *
47839 * function draw() {
47840 *   background(0, 100, 200);
47841 * }
47842 *
47843 * function windowResized() {
47844 *   resizeCanvas(windowWidth, windowHeight);
47845 * }
47846 * </code></div>
47847 * @alt
47848 * no display.
47849 */
47850p5.prototype._onresize = function(e) {
47851  this._setProperty('windowWidth', getWindowWidth());
47852  this._setProperty('windowHeight', getWindowHeight());
47853  var context = this._isGlobal ? window : this;
47854  var executeDefault;
47855  if (typeof context.windowResized === 'function') {
47856    executeDefault = context.windowResized(e);
47857    if (executeDefault !== undefined && !executeDefault) {
47858      e.preventDefault();
47859    }
47860  }
47861};
47862
47863function getWindowWidth() {
47864  return (
47865    window.innerWidth ||
47866    (document.documentElement && document.documentElement.clientWidth) ||
47867    (document.body && document.body.clientWidth) ||
47868    0
47869  );
47870}
47871
47872function getWindowHeight() {
47873  return (
47874    window.innerHeight ||
47875    (document.documentElement && document.documentElement.clientHeight) ||
47876    (document.body && document.body.clientHeight) ||
47877    0
47878  );
47879}
47880
47881/**
47882 * System variable that stores the width of the drawing canvas. This value
47883 * is set by the first parameter of the createCanvas() function.
47884 * For example, the function call createCanvas(320, 240) sets the width
47885 * variable to the value 320. The value of width defaults to 100 if
47886 * createCanvas() is not used in a program.
47887 *
47888 * @property {Number} width
47889 * @readOnly
47890 */
47891p5.prototype.width = 0;
47892
47893/**
47894 * System variable that stores the height of the drawing canvas. This value
47895 * is set by the second parameter of the createCanvas() function. For
47896 * example, the function call createCanvas(320, 240) sets the height
47897 * variable to the value 240. The value of height defaults to 100 if
47898 * createCanvas() is not used in a program.
47899 *
47900 * @property {Number} height
47901 * @readOnly
47902 */
47903p5.prototype.height = 0;
47904
47905/**
47906 * If argument is given, sets the sketch to fullscreen or not based on the
47907 * value of the argument. If no argument is given, returns the current
47908 * fullscreen state. Note that due to browser restrictions this can only
47909 * be called on user input, for example, on mouse press like the example
47910 * below.
47911 *
47912 * @method fullscreen
47913 * @param  {Boolean} [val] whether the sketch should be in fullscreen mode
47914 * or not
47915 * @return {Boolean} current fullscreen state
47916 * @example
47917 * <div>
47918 * <code>
47919 * // Clicking in the box toggles fullscreen on and off.
47920 * function setup() {
47921 *   background(200);
47922 * }
47923 * function mousePressed() {
47924 *   if (mouseX > 0 && mouseX < 100 && mouseY > 0 && mouseY < 100) {
47925 *     var fs = fullscreen();
47926 *     fullscreen(!fs);
47927 *   }
47928 * }
47929 * </code>
47930 * </div>
47931 *
47932 * @alt
47933 * no display.
47934 *
47935 */
47936p5.prototype.fullscreen = function(val) {
47937  p5._validateParameters('fullscreen', arguments);
47938  // no arguments, return fullscreen or not
47939  if (typeof val === 'undefined') {
47940    return (
47941      document.fullscreenElement ||
47942      document.webkitFullscreenElement ||
47943      document.mozFullScreenElement ||
47944      document.msFullscreenElement
47945    );
47946  } else {
47947    // otherwise set to fullscreen or not
47948    if (val) {
47949      launchFullscreen(document.documentElement);
47950    } else {
47951      exitFullscreen();
47952    }
47953  }
47954};
47955
47956/**
47957 * Sets the pixel scaling for high pixel density displays. By default
47958 * pixel density is set to match display density, call pixelDensity(1)
47959 * to turn this off. Calling pixelDensity() with no arguments returns
47960 * the current pixel density of the sketch.
47961 *
47962 *
47963 * @method pixelDensity
47964 * @param  {Number} [val] whether or how much the sketch should scale
47965 * @returns {Number} current pixel density of the sketch
47966 * @example
47967 * <div>
47968 * <code>
47969 * function setup() {
47970 *   pixelDensity(1);
47971 *   createCanvas(100, 100);
47972 *   background(200);
47973 *   ellipse(width / 2, height / 2, 50, 50);
47974 * }
47975 * </code>
47976 * </div>
47977 * <div>
47978 * <code>
47979 * function setup() {
47980 *   pixelDensity(3.0);
47981 *   createCanvas(100, 100);
47982 *   background(200);
47983 *   ellipse(width / 2, height / 2, 50, 50);
47984 * }
47985 * </code>
47986 * </div>
47987 *
47988 * @alt
47989 * fuzzy 50x50 white ellipse with black outline in center of canvas.
47990 * sharp 50x50 white ellipse with black outline in center of canvas.
47991 */
47992p5.prototype.pixelDensity = function(val) {
47993  p5._validateParameters('pixelDensity', arguments);
47994  if (typeof val === 'number') {
47995    this._pixelDensity = val;
47996  } else {
47997    return this._pixelDensity;
47998  }
47999  this.resizeCanvas(this.width, this.height, true);
48000};
48001
48002/**
48003 * Returns the pixel density of the current display the sketch is running on.
48004 *
48005 * @method displayDensity
48006 * @returns {Number} current pixel density of the display
48007 * @example
48008 * <div>
48009 * <code>
48010 * function setup() {
48011 *   var density = displayDensity();
48012 *   pixelDensity(density);
48013 *   createCanvas(100, 100);
48014 *   background(200);
48015 *   ellipse(width / 2, height / 2, 50, 50);
48016 * }
48017 * </code>
48018 * </div>
48019 *
48020 * @alt
48021 * 50x50 white ellipse with black outline in center of canvas.
48022 */
48023p5.prototype.displayDensity = function() {
48024  return window.devicePixelRatio;
48025};
48026
48027function launchFullscreen(element) {
48028  var enabled =
48029    document.fullscreenEnabled ||
48030    document.webkitFullscreenEnabled ||
48031    document.mozFullScreenEnabled ||
48032    document.msFullscreenEnabled;
48033  if (!enabled) {
48034    throw new Error('Fullscreen not enabled in this browser.');
48035  }
48036  if (element.requestFullscreen) {
48037    element.requestFullscreen();
48038  } else if (element.mozRequestFullScreen) {
48039    element.mozRequestFullScreen();
48040  } else if (element.webkitRequestFullscreen) {
48041    element.webkitRequestFullscreen();
48042  } else if (element.msRequestFullscreen) {
48043    element.msRequestFullscreen();
48044  }
48045}
48046
48047function exitFullscreen() {
48048  if (document.exitFullscreen) {
48049    document.exitFullscreen();
48050  } else if (document.mozCancelFullScreen) {
48051    document.mozCancelFullScreen();
48052  } else if (document.webkitExitFullscreen) {
48053    document.webkitExitFullscreen();
48054  } else if (document.msExitFullscreen) {
48055    document.msExitFullscreen();
48056  }
48057}
48058
48059/**
48060 * Gets the current URL.
48061 * @method getURL
48062 * @return {String} url
48063 * @example
48064 * <div>
48065 * <code>
48066 * var url;
48067 * var x = 100;
48068 *
48069 * function setup() {
48070 *   fill(0);
48071 *   noStroke();
48072 *   url = getURL();
48073 * }
48074 *
48075 * function draw() {
48076 *   background(200);
48077 *   text(url, x, height / 2);
48078 *   x--;
48079 * }
48080 * </code>
48081 * </div>
48082 *
48083 * @alt
48084 * current url (http://p5js.org/reference/#/p5/getURL) moves right to left.
48085 *
48086 */
48087p5.prototype.getURL = function() {
48088  return location.href;
48089};
48090/**
48091 * Gets the current URL path as an array.
48092 * @method getURLPath
48093 * @return {String[]} path components
48094 * @example
48095 * <div class='norender'><code>
48096 * function setup() {
48097 *   var urlPath = getURLPath();
48098 *   for (var i = 0; i < urlPath.length; i++) {
48099 *     text(urlPath[i], 10, i * 20 + 20);
48100 *   }
48101 * }
48102 * </code></div>
48103 *
48104 * @alt
48105 *no display
48106 *
48107 */
48108p5.prototype.getURLPath = function() {
48109  return location.pathname.split('/').filter(function(v) {
48110    return v !== '';
48111  });
48112};
48113/**
48114 * Gets the current URL params as an Object.
48115 * @method getURLParams
48116 * @return {Object} URL params
48117 * @example
48118 * <div class='norender notest'>
48119 * <code>
48120 * // Example: http://p5js.org?year=2014&month=May&day=15
48121 *
48122 * function setup() {
48123 *   var params = getURLParams();
48124 *   text(params.day, 10, 20);
48125 *   text(params.month, 10, 40);
48126 *   text(params.year, 10, 60);
48127 * }
48128 * </code>
48129 * </div>
48130 * @alt
48131 * no display.
48132 *
48133 */
48134p5.prototype.getURLParams = function() {
48135  var re = /[?&]([^&=]+)(?:[&=])([^&=]+)/gim;
48136  var m;
48137  var v = {};
48138  while ((m = re.exec(location.search)) != null) {
48139    if (m.index === re.lastIndex) {
48140      re.lastIndex++;
48141    }
48142    v[m[1]] = m[2];
48143  }
48144  return v;
48145};
48146
48147module.exports = p5;
48148
48149},{"./constants":21,"./core":22}],25:[function(_dereq_,module,exports){
48150/**
48151 * @for p5
48152 * @requires core
48153 */
48154
48155'use strict';
48156
48157var p5 = _dereq_('./core');
48158var constants = _dereq_('./constants');
48159
48160if (typeof IS_MINIFIED !== 'undefined') {
48161  p5._validateParameters = p5._friendlyFileLoadError = function() {};
48162} else {
48163  var doFriendlyWelcome = false; // TEMP until we get it all working LM
48164  // for parameter validation
48165  var dataDoc = _dereq_('../../docs/reference/data.json');
48166  var arrDoc = JSON.parse(JSON.stringify(dataDoc));
48167
48168  // -- Borrowed from jQuery 1.11.3 --
48169  var class2type = {};
48170  var toString = class2type.toString;
48171  var names = [
48172    'Boolean',
48173    'Number',
48174    'String',
48175    'Function',
48176    'Array',
48177    'Date',
48178    'RegExp',
48179    'Object',
48180    'Error'
48181  ];
48182  for (var n = 0; n < names.length; n++) {
48183    class2type['[object ' + names[n] + ']'] = names[n].toLowerCase();
48184  }
48185  var getType = function(obj) {
48186    if (obj == null) {
48187      return obj + '';
48188    }
48189    return typeof obj === 'object' || typeof obj === 'function'
48190      ? class2type[toString.call(obj)] || 'object'
48191      : typeof obj;
48192  };
48193
48194  // -- End borrow --
48195
48196  var friendlyWelcome = function() {
48197    // p5.js brand - magenta: #ED225D
48198    //var astrixBgColor = 'transparent';
48199    //var astrixTxtColor = '#ED225D';
48200    //var welcomeBgColor = '#ED225D';
48201    //var welcomeTextColor = 'white';
48202    console.log(
48203      '    _ \n' +
48204        ' /\\| |/\\ \n' +
48205        " \\ ` ' /  \n" +
48206        ' / , . \\  \n' +
48207        ' \\/|_|\\/ ' +
48208        '\n\n> p5.js says: Welcome! ' +
48209        'This is your friendly debugger. ' +
48210        'To turn me off switch to using “p5.min.js”.'
48211    );
48212  };
48213
48214  /**
48215   * Prints out a fancy, colorful message to the console log
48216   *
48217   * @private
48218   * @param  {String}               message the words to be said
48219   * @param  {String}               func    the name of the function to link
48220   * @param  {Number|String} color   CSS color string or error type
48221   *
48222   * @return console logs
48223   */
48224  // Wrong number of params, undefined param, wrong type
48225  var FILE_LOAD = 3;
48226  var ERR_PARAMS = 3;
48227  // p5.js blue, p5.js orange, auto dark green; fallback p5.js darkened magenta
48228  // See testColors below for all the color codes and names
48229  var typeColors = ['#2D7BB6', '#EE9900', '#4DB200', '#C83C00'];
48230  var report = function(message, func, color) {
48231    if (doFriendlyWelcome) {
48232      friendlyWelcome();
48233      doFriendlyWelcome = false;
48234    }
48235    if ('undefined' === getType(color)) {
48236      color = '#B40033'; // dark magenta
48237    } else if (getType(color) === 'number') {
48238      // Type to color
48239      color = typeColors[color];
48240    }
48241    if (func.substring(0, 4) === 'load') {
48242      console.log(
48243        '> p5.js says: ' +
48244          message +
48245          '[https://github.com/processing/p5.js/wiki/Local-server]'
48246      );
48247    } else {
48248      console.log(
48249        '> p5.js says: ' +
48250          message +
48251          ' [http://p5js.org/reference/#p5/' +
48252          func +
48253          ']'
48254      );
48255    }
48256  };
48257
48258  var errorCases = {
48259    '0': {
48260      fileType: 'image',
48261      method: 'loadImage',
48262      message: ' hosting the image online,'
48263    },
48264    '1': {
48265      fileType: 'XML file',
48266      method: 'loadXML'
48267    },
48268    '2': {
48269      fileType: 'table file',
48270      method: 'loadTable'
48271    },
48272    '3': {
48273      fileType: 'text file',
48274      method: 'loadStrings'
48275    },
48276    '4': {
48277      fileType: 'font',
48278      method: 'loadFont',
48279      message: ' hosting the font online,'
48280    }
48281  };
48282  p5._friendlyFileLoadError = function(errorType, filePath) {
48283    var errorInfo = errorCases[errorType];
48284    var message =
48285      'It looks like there was a problem' +
48286      ' loading your ' +
48287      errorInfo.fileType +
48288      '.' +
48289      ' Try checking if the file path [' +
48290      filePath +
48291      '] is correct,' +
48292      (errorInfo.message || '') +
48293      ' or running a local server.';
48294    report(message, errorInfo.method, FILE_LOAD);
48295  };
48296
48297  var docCache = {};
48298  var builtinTypes = [
48299    'number',
48300    'string',
48301    'boolean',
48302    'constant',
48303    'function',
48304    'any',
48305    'integer'
48306  ];
48307
48308  // validateParameters() helper functions:
48309  // lookupParamDoc() for querying data.json
48310  var lookupParamDoc = function(func) {
48311    var queryResult = arrDoc.classitems.filter(function(x) {
48312      return x.name === func;
48313    });
48314    // different JSON structure for funct with multi-format
48315    var overloads = [];
48316    if (queryResult[0].hasOwnProperty('overloads')) {
48317      for (var i = 0; i < queryResult[0].overloads.length; i++) {
48318        overloads.push(queryResult[0].overloads[i].params);
48319      }
48320    } else {
48321      overloads.push(queryResult[0].params || []);
48322    }
48323
48324    var mapConstants = {};
48325    var maxParams = 0;
48326    overloads.forEach(function(formats) {
48327      if (maxParams < formats.length) {
48328        maxParams = formats.length;
48329      }
48330      formats.forEach(function(format) {
48331        format.types = format.type.split('|').map(function ct(type) {
48332          // array
48333          if (type.substr(type.length - 2, 2) === '[]') {
48334            return {
48335              name: type,
48336              array: ct(type.substr(0, type.length - 2))
48337            };
48338          }
48339
48340          var lowerType = type.toLowerCase();
48341
48342          // contant
48343          if (lowerType === 'constant') {
48344            var constant;
48345            if (mapConstants.hasOwnProperty(format.name)) {
48346              constant = mapConstants[format.name];
48347            } else {
48348              // parse possible constant values from description
48349              var myRe = /either\s+(?:[A-Z0-9_]+\s*,?\s*(?:or)?\s*)+/g;
48350              var values = {};
48351              var names = [];
48352
48353              constant = mapConstants[format.name] = {
48354                values: values,
48355                names: names
48356              };
48357
48358              var myArray = myRe.exec(format.description);
48359              if (func === 'endShape' && format.name === 'mode') {
48360                values[constants.CLOSE] = true;
48361                names.push('CLOSE');
48362              } else {
48363                var match = myArray[0];
48364                var reConst = /[A-Z0-9_]+/g;
48365                var matchConst;
48366                while ((matchConst = reConst.exec(match)) !== null) {
48367                  var name = matchConst[0];
48368                  if (constants.hasOwnProperty(name)) {
48369                    values[constants[name]] = true;
48370                    names.push(name);
48371                  }
48372                }
48373              }
48374            }
48375            return {
48376              name: type,
48377              builtin: lowerType,
48378              names: constant.names,
48379              values: constant.values
48380            };
48381          }
48382
48383          // function
48384          if (lowerType.substr(0, 'function'.length) === 'function') {
48385            lowerType = 'function';
48386          }
48387          // builtin
48388          if (builtinTypes.indexOf(lowerType) >= 0) {
48389            return { name: type, builtin: lowerType };
48390          }
48391
48392          // find type's prototype
48393          var t = window;
48394          var typeParts = type.split('.');
48395
48396          // special-case 'p5' since it may be non-global
48397          if (typeParts[0] === 'p5') {
48398            t = p5;
48399            typeParts.shift();
48400          }
48401
48402          typeParts.forEach(function(p) {
48403            t = t && t[p];
48404          });
48405          if (t) {
48406            return { name: type, prototype: t };
48407          }
48408
48409          return { name: type, type: lowerType };
48410        });
48411      });
48412    });
48413    return {
48414      overloads: overloads,
48415      maxParams: maxParams
48416    };
48417  };
48418
48419  var testParamType = function(param, type) {
48420    var isArray = param instanceof Array;
48421    if (type.array && isArray) {
48422      for (var i = 0; i < param.length; i++) {
48423        if (!testParamType(param[i], type.array)) {
48424          return false;
48425        }
48426      }
48427      return true;
48428    } else if (type.prototype) {
48429      return param instanceof type.prototype;
48430    } else if (type.builtin) {
48431      switch (type.builtin) {
48432        case 'number':
48433          return typeof param === 'number' || (!!param && !isNaN(param));
48434        case 'integer':
48435          return (
48436            (typeof param === 'number' || (!!param && !isNaN(param))) &&
48437            Number(param) === Math.floor(param)
48438          );
48439        case 'boolean':
48440        case 'any':
48441          return true;
48442        case 'array':
48443          return isArray;
48444        case 'string':
48445          return typeof param === 'number' || typeof param === 'string';
48446        case 'constant':
48447          return type.values.hasOwnProperty(param);
48448        case 'function':
48449          return param instanceof Function;
48450      }
48451    }
48452
48453    return typeof param === type.t;
48454  };
48455
48456  // testType() for non-object type parameter validation
48457  // Returns true if PASS, false if FAIL
48458  var testParamTypes = function(param, types) {
48459    for (var i = 0; i < types.length; i++) {
48460      if (testParamType(param, types[i])) {
48461        return true;
48462      }
48463    }
48464    return false;
48465  };
48466
48467  var testParamFormat = function(args, formats) {
48468    var errorArray = [];
48469    for (var p = 0; p < formats.length; p++) {
48470      var arg = args[p];
48471      var format = formats[p];
48472      var argType = typeof arg;
48473      if ('undefined' === argType || null === arg) {
48474        if (format.optional !== true) {
48475          errorArray.push({
48476            type: 'EMPTY_VAR',
48477            position: p,
48478            format: format
48479          });
48480        }
48481      } else if (!testParamTypes(arg, format.types)) {
48482        errorArray.push({
48483          type: 'WRONG_TYPE',
48484          position: p,
48485          format: format,
48486          arg: arg
48487        });
48488      }
48489    }
48490    return errorArray;
48491  };
48492
48493  // function for generating console.log() msg
48494  p5._friendlyParamError = function(errorObj, func) {
48495    var message;
48496
48497    function formatType() {
48498      var format = errorObj.format;
48499      return format.types
48500        .map(function(type) {
48501          return type.names ? type.names.join('|') : type.name;
48502        })
48503        .join('|');
48504    }
48505
48506    switch (errorObj.type) {
48507      case 'EMPTY_VAR':
48508        message =
48509          func +
48510          '() was expecting ' +
48511          formatType() +
48512          ' for parameter #' +
48513          errorObj.position +
48514          ' (zero-based index), received an empty variable instead.' +
48515          ' If not intentional, this is often a problem with scope:' +
48516          ' [https://p5js.org/examples/data-variable-scope.html]';
48517        break;
48518      case 'WRONG_TYPE':
48519        var arg = errorObj.arg;
48520        var argType = arg instanceof Array ? 'array' : arg.name || typeof arg;
48521        message =
48522          func +
48523          '() was expecting ' +
48524          formatType() +
48525          ' for parameter #' +
48526          errorObj.position +
48527          ' (zero-based index), received ' +
48528          argType +
48529          ' instead';
48530        break;
48531      case 'WRONG_ARGUMENT_COUNT':
48532        message =
48533          func +
48534          '() was expecting ' +
48535          errorObj.maxParams +
48536          ' arguments, but received ' +
48537          errorObj.argCount;
48538        break;
48539    }
48540
48541    if (message) {
48542      try {
48543        var re = /Function\.validateParameters.*[\r\n].*[\r\n].*\(([^)]*)/;
48544        var location = re.exec(new Error().stack)[1];
48545        if (location) {
48546          message += ' at ' + location;
48547        }
48548      } catch (err) {}
48549
48550      report(message + '.', func, ERR_PARAMS);
48551    }
48552  };
48553
48554  /**
48555   * Validates parameters
48556   * param  {String}               func    the name of the function
48557   * param  {Array}                args    user input arguments
48558   *
48559   * example:
48560   *  var a;
48561   *  ellipse(10,10,a,5);
48562   * console ouput:
48563   *  "It looks like ellipse received an empty variable in spot #2."
48564   *
48565   * example:
48566   *  ellipse(10,"foo",5,5);
48567   * console output:
48568   *  "ellipse was expecting a number for parameter #1,
48569   *           received "foo" instead."
48570   */
48571  p5._validateParameters = function validateParameters(func, args) {
48572    if (p5.disableFriendlyErrors) {
48573      return; // skip FES
48574    }
48575
48576    var docs = docCache[func] || (docCache[func] = lookupParamDoc(func));
48577    var errorArray = [];
48578    var minErrCount = 999999;
48579    var overloads = docs.overloads;
48580    for (var i = 0; i < overloads.length; i++) {
48581      var arrError = testParamFormat(args, overloads[i]);
48582      // see if this is the format with min number of err
48583      if (minErrCount > arrError.length) {
48584        minErrCount = arrError.length;
48585        errorArray = arrError;
48586      }
48587      if (arrError.length === 0) {
48588        break; // no error
48589      }
48590    }
48591
48592    if (!errorArray.length && args.length > docs.maxParams) {
48593      errorArray.push({
48594        type: 'WRONG_ARGUMENT_COUNT',
48595        argCount: args.length,
48596        maxParams: docs.maxParams
48597      });
48598    }
48599
48600    // generate err msg
48601    for (var n = 0; n < errorArray.length; n++) {
48602      p5._friendlyParamError(errorArray[n], func);
48603    }
48604  };
48605
48606  /**
48607   * Prints out all the colors in the color pallete with white text.
48608   * For color blindness testing.
48609   */
48610  /* function testColors() {
48611    var str = 'A box of biscuits, a box of mixed biscuits and a biscuit mixer';
48612    report(str, 'print', '#ED225D'); // p5.js magenta
48613    report(str, 'print', '#2D7BB6'); // p5.js blue
48614    report(str, 'print', '#EE9900'); // p5.js orange
48615    report(str, 'print', '#A67F59'); // p5.js light brown
48616    report(str, 'print', '#704F21'); // p5.js gold
48617    report(str, 'print', '#1CC581'); // auto cyan
48618    report(str, 'print', '#FF6625'); // auto orange
48619    report(str, 'print', '#79EB22'); // auto green
48620    report(str, 'print', '#B40033'); // p5.js darkened magenta
48621    report(str, 'print', '#084B7F'); // p5.js darkened blue
48622    report(str, 'print', '#945F00'); // p5.js darkened orange
48623    report(str, 'print', '#6B441D'); // p5.js darkened brown
48624    report(str, 'print', '#2E1B00'); // p5.js darkened gold
48625    report(str, 'print', '#008851'); // auto dark cyan
48626    report(str, 'print', '#C83C00'); // auto dark orange
48627    report(str, 'print', '#4DB200'); // auto dark green
48628  } */
48629
48630  p5.prototype._validateParameters = p5.validateParameters;
48631}
48632
48633// This is a lazily-defined list of p5 symbols that may be
48634// misused by beginners at top-level code, outside of setup/draw. We'd like
48635// to detect these errors and help the user by suggesting they move them
48636// into setup/draw.
48637//
48638// For more details, see https://github.com/processing/p5.js/issues/1121.
48639var misusedAtTopLevelCode = null;
48640var FAQ_URL =
48641  'https://github.com/processing/p5.js/wiki/' +
48642  'Frequently-Asked-Questions' +
48643  '#why-cant-i-assign-variables-using-p5-functions-and-' +
48644  'variables-before-setup';
48645
48646var defineMisusedAtTopLevelCode = function() {
48647  var uniqueNamesFound = {};
48648
48649  var getSymbols = function(obj) {
48650    return Object.getOwnPropertyNames(obj)
48651      .filter(function(name) {
48652        if (name[0] === '_') {
48653          return false;
48654        }
48655        if (name in uniqueNamesFound) {
48656          return false;
48657        }
48658
48659        uniqueNamesFound[name] = true;
48660
48661        return true;
48662      })
48663      .map(function(name) {
48664        var type;
48665
48666        if (typeof obj[name] === 'function') {
48667          type = 'function';
48668        } else if (name === name.toUpperCase()) {
48669          type = 'constant';
48670        } else {
48671          type = 'variable';
48672        }
48673
48674        return { name: name, type: type };
48675      });
48676  };
48677
48678  misusedAtTopLevelCode = [].concat(
48679    getSymbols(p5.prototype),
48680    // At present, p5 only adds its constants to p5.prototype during
48681    // construction, which may not have happened at the time a
48682    // ReferenceError is thrown, so we'll manually add them to our list.
48683    getSymbols(_dereq_('./constants'))
48684  );
48685
48686  // This will ultimately ensure that we report the most specific error
48687  // possible to the user, e.g. advising them about HALF_PI instead of PI
48688  // when their code misuses the former.
48689  misusedAtTopLevelCode.sort(function(a, b) {
48690    return b.name.length - a.name.length;
48691  });
48692};
48693
48694var helpForMisusedAtTopLevelCode = function(e, log) {
48695  if (!log) {
48696    log = console.log.bind(console);
48697  }
48698
48699  if (!misusedAtTopLevelCode) {
48700    defineMisusedAtTopLevelCode();
48701  }
48702
48703  // If we find that we're logging lots of false positives, we can
48704  // uncomment the following code to avoid displaying anything if the
48705  // user's code isn't likely to be using p5's global mode. (Note that
48706  // setup/draw are more likely to be defined due to JS function hoisting.)
48707  //
48708  //if (!('setup' in window || 'draw' in window)) {
48709  //  return;
48710  //}
48711
48712  misusedAtTopLevelCode.some(function(symbol) {
48713    // Note that while just checking for the occurrence of the
48714    // symbol name in the error message could result in false positives,
48715    // a more rigorous test is difficult because different browsers
48716    // log different messages, and the format of those messages may
48717    // change over time.
48718    //
48719    // For example, if the user uses 'PI' in their code, it may result
48720    // in any one of the following messages:
48721    //
48722    //   * 'PI' is undefined                           (Microsoft Edge)
48723    //   * ReferenceError: PI is undefined             (Firefox)
48724    //   * Uncaught ReferenceError: PI is not defined  (Chrome)
48725
48726    if (e.message && e.message.match('\\W?' + symbol.name + '\\W') !== null) {
48727      log(
48728        "Did you just try to use p5.js's " +
48729          symbol.name +
48730          (symbol.type === 'function' ? '() ' : ' ') +
48731          symbol.type +
48732          '? If so, you may want to ' +
48733          "move it into your sketch's setup() function.\n\n" +
48734          'For more details, see: ' +
48735          FAQ_URL
48736      );
48737      return true;
48738    }
48739  });
48740};
48741
48742// Exposing this primarily for unit testing.
48743p5.prototype._helpForMisusedAtTopLevelCode = helpForMisusedAtTopLevelCode;
48744
48745if (document.readyState !== 'complete') {
48746  window.addEventListener('error', helpForMisusedAtTopLevelCode, false);
48747
48748  // Our job is only to catch ReferenceErrors that are thrown when
48749  // global (non-instance mode) p5 APIs are used at the top-level
48750  // scope of a file, so we'll unbind our error listener now to make
48751  // sure we don't log false positives later.
48752  window.addEventListener('load', function() {
48753    window.removeEventListener('error', helpForMisusedAtTopLevelCode, false);
48754  });
48755}
48756
48757module.exports = p5;
48758
48759},{"../../docs/reference/data.json":1,"./constants":21,"./core":22}],26:[function(_dereq_,module,exports){
48760'use strict';
48761
48762var p5 = _dereq_('../core/core');
48763
48764/**
48765 * _globalInit
48766 *
48767 * TODO: ???
48768 * if sketch is on window
48769 * assume "global" mode
48770 * and instantiate p5 automatically
48771 * otherwise do nothing
48772 *
48773 * @private
48774 * @return {Undefined}
48775 */
48776var _globalInit = function() {
48777  if (!window.PHANTOMJS && !window.mocha) {
48778    // If there is a setup or draw function on the window
48779    // then instantiate p5 in "global" mode
48780    if (
48781      ((window.setup && typeof window.setup === 'function') ||
48782        (window.draw && typeof window.draw === 'function')) &&
48783      !p5.instance
48784    ) {
48785      new p5();
48786    }
48787  }
48788};
48789
48790// TODO: ???
48791if (document.readyState === 'complete') {
48792  _globalInit();
48793} else {
48794  window.addEventListener('load', _globalInit, false);
48795}
48796
48797},{"../core/core":22}],27:[function(_dereq_,module,exports){
48798/**
48799 * @module DOM
48800 * @submodule DOM
48801 * @for p5.Element
48802 */
48803
48804'use strict';
48805
48806var p5 = _dereq_('./core');
48807
48808/**
48809 * Base class for all elements added to a sketch, including canvas,
48810 * graphics buffers, and other HTML elements. Methods in blue are
48811 * included in the core functionality, methods in brown are added
48812 * with the <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom
48813 * library</a>.
48814 * It is not called directly, but p5.Element
48815 * objects are created by calling createCanvas, createGraphics,
48816 * or in the p5.dom library, createDiv, createImg, createInput, etc.
48817 *
48818 * @class p5.Element
48819 * @param {String} elt DOM node that is wrapped
48820 * @param {p5} [pInst] pointer to p5 instance
48821 */
48822p5.Element = function(elt, pInst) {
48823  /**
48824   * Underlying HTML element. All normal HTML methods can be called on this.
48825   * @example
48826   * <div>
48827   * <code>
48828   * createCanvas(300, 500);
48829   * background(0, 0, 0, 0);
48830   * var input = createInput();
48831   * input.position(20, 225);
48832   * var inputElem = new p5.Element(input.elt);
48833   * inputElem.style('width:450px;');
48834   * inputElem.value('some string');
48835   * </code>
48836   * </div>
48837   *
48838   * @property elt
48839   * @readOnly
48840   */
48841  this.elt = elt;
48842  this._pInst = pInst;
48843  this._events = {};
48844  this.width = this.elt.offsetWidth;
48845  this.height = this.elt.offsetHeight;
48846};
48847
48848/**
48849 *
48850 * Attaches the element to the parent specified. A way of setting
48851 * the container for the element. Accepts either a string ID, DOM
48852 * node, or p5.Element. If no arguments given, parent node is returned.
48853 * For more ways to position the canvas, see the
48854 * <a href='https://github.com/processing/p5.js/wiki/Positioning-your-canvas'>
48855 * positioning the canvas</a> wiki page.
48856 *
48857 * @method parent
48858 * @param  {String|p5.Element|Object} parent the ID, DOM node, or p5.Element
48859 *                         of desired parent element
48860 * @chainable
48861 *
48862 * @example
48863 * <div class="norender notest"><code>
48864 * // in the html file:
48865 * // &lt;div id="myContainer">&lt;/div>
48866 *
48867 * // in the js file:
48868 * var cnv = createCanvas(100, 100);
48869 * cnv.parent('myContainer');
48870 * </code></div>
48871 * <div class='norender'><code>
48872 * var div0 = createDiv('this is the parent');
48873 * var div1 = createDiv('this is the child');
48874 * div1.parent(div0); // use p5.Element
48875 * </code></div>
48876 * <div class='norender'><code>
48877 * var div0 = createDiv('this is the parent');
48878 * div0.id('apples');
48879 * var div1 = createDiv('this is the child');
48880 * div1.parent('apples'); // use id
48881 * </code></div>
48882 * <div class='norender notest'><code>
48883 * var elt = document.getElementById('myParentDiv');
48884 * var div1 = createDiv('this is the child');
48885 * div1.parent(elt); // use element from page
48886 * </code></div>
48887 *
48888 * @alt
48889 * no display.
48890 */
48891/**
48892 * @method parent
48893 * @return {p5.Element}
48894 *
48895 */
48896p5.Element.prototype.parent = function(p) {
48897  if (typeof p === 'undefined') {
48898    return this.elt.parentNode;
48899  }
48900
48901  if (typeof p === 'string') {
48902    if (p[0] === '#') {
48903      p = p.substring(1);
48904    }
48905    p = document.getElementById(p);
48906  } else if (p instanceof p5.Element) {
48907    p = p.elt;
48908  }
48909  p.appendChild(this.elt);
48910  return this;
48911};
48912
48913/**
48914 *
48915 * Sets the ID of the element. If no ID argument is passed in, it instead
48916 * returns the current ID of the element.
48917 *
48918 * @method id
48919 * @param  {String} id ID of the element
48920 * @chainable
48921 *
48922 * @example
48923 * <div class='norender'><code>
48924 * function setup() {
48925 *   var cnv = createCanvas(100, 100);
48926 *   // Assigns a CSS selector ID to
48927 *   // the canvas element.
48928 *   cnv.id('mycanvas');
48929 * }
48930 * </code></div>
48931 *
48932 * @alt
48933 * no display.
48934 */
48935/**
48936 * @method id
48937 * @return {String} the id of the element
48938 */
48939p5.Element.prototype.id = function(id) {
48940  if (typeof id === 'undefined') {
48941    return this.elt.id;
48942  }
48943
48944  this.elt.id = id;
48945  this.width = this.elt.offsetWidth;
48946  this.height = this.elt.offsetHeight;
48947  return this;
48948};
48949
48950/**
48951 *
48952 * Adds given class to the element. If no class argument is passed in, it
48953 * instead returns a string containing the current class(es) of the element.
48954 *
48955 * @method class
48956 * @param  {String} class class to add
48957 * @chainable
48958 *
48959 * @example
48960 * <div class='norender'><code>
48961 * function setup() {
48962 *   var cnv = createCanvas(100, 100);
48963 *   // Assigns a CSS selector class 'small'
48964 *   // to the canvas element.
48965 *   cnv.class('small');
48966 * }
48967 * </code></div>
48968 *
48969 * @alt
48970 * no display.
48971 */
48972/**
48973 * @method class
48974 * @return {String} the class of the element
48975 */
48976p5.Element.prototype.class = function(c) {
48977  if (typeof c === 'undefined') {
48978    return this.elt.className;
48979  }
48980
48981  this.elt.className = c;
48982  return this;
48983};
48984
48985/**
48986 * The .mousePressed() function is called once after every time a
48987 * mouse button is pressed over the element. This can be used to
48988 * attach element specific event listeners.
48989 *
48990 * @method mousePressed
48991 * @param  {Function|Boolean} fxn function to be fired when mouse is
48992 *                                pressed over the element.
48993 *                                if `false` is passed instead, the previously
48994 *                                firing function will no longer fire.
48995 * @chainable
48996 * @example
48997 * <div class='norender'><code>
48998 * var cnv;
48999 * var d;
49000 * var g;
49001 * function setup() {
49002 *   cnv = createCanvas(100, 100);
49003 *   cnv.mousePressed(changeGray); // attach listener for
49004 *   // canvas click only
49005 *   d = 10;
49006 *   g = 100;
49007 * }
49008 *
49009 * function draw() {
49010 *   background(g);
49011 *   ellipse(width / 2, height / 2, d, d);
49012 * }
49013 *
49014 * // this function fires with any click anywhere
49015 * function mousePressed() {
49016 *   d = d + 10;
49017 * }
49018 *
49019 * // this function fires only when cnv is clicked
49020 * function changeGray() {
49021 *   g = random(0, 255);
49022 * }
49023 * </code></div>
49024 *
49025 * @alt
49026 * no display.
49027 *
49028 */
49029p5.Element.prototype.mousePressed = function(fxn) {
49030  adjustListener('mousedown', fxn, this);
49031  adjustListener('touchstart', fxn, this);
49032  return this;
49033};
49034
49035/**
49036 * The .doubleClicked() function is called once after every time a
49037 * mouse button is pressed twice over the element. This can be used to
49038 * attach element and action specific event listeners.
49039 *
49040 * @method doubleClicked
49041 * @param  {Function|Boolean} fxn function to be fired when mouse is
49042 *                                double clicked over the element.
49043 *                                if `false` is passed instead, the previously
49044 *                                firing function will no longer fire.
49045 * @return {p5.Element}
49046 * @example
49047 * <div class='norender'><code>
49048 * var cnv;
49049 * var d;
49050 * var g;
49051 * function setup() {
49052 *   cnv = createCanvas(100, 100);
49053 *   cnv.doubleClicked(changeGray); // attach listener for
49054 *   // canvas double click only
49055 *   d = 10;
49056 *   g = 100;
49057 * }
49058 *
49059 * function draw() {
49060 *   background(g);
49061 *   ellipse(width / 2, height / 2, d, d);
49062 * }
49063 *
49064 * // this function fires with any double click anywhere
49065 * function doubleClicked() {
49066 *   d = d + 10;
49067 * }
49068 *
49069 * // this function fires only when cnv is double clicked
49070 * function changeGray() {
49071 *   g = random(0, 255);
49072 * }
49073 * </code></div>
49074 *
49075 * @alt
49076 * no display.
49077 *
49078 */
49079p5.Element.prototype.doubleClicked = function(fxn) {
49080  adjustListener('dblclick', fxn, this);
49081  return this;
49082};
49083
49084/**
49085 * The .mouseWheel() function is called once after every time a
49086 * mouse wheel is scrolled over the element. This can be used to
49087 * attach element specific event listeners.
49088 * <br><br>
49089 * The function accepts a callback function as argument which will be executed
49090 * when the `wheel` event is triggered on the element, the callback function is
49091 * passed one argument `event`. The `event.deltaY` property returns negative
49092 * values if the mouse wheel is rotated up or away from the user and positive
49093 * in the other direction. The `event.deltaX` does the same as `event.deltaY`
49094 * except it reads the horizontal wheel scroll of the mouse wheel.
49095 * <br><br>
49096 * On OS X with "natural" scrolling enabled, the `event.deltaY` values are
49097 * reversed.
49098 *
49099 * @method mouseWheel
49100 * @param  {Function|Boolean} fxn function to be fired when mouse is
49101 *                                scrolled over the element.
49102 *                                if `false` is passed instead, the previously
49103 *                                firing function will no longer fire.
49104 * @chainable
49105 * @example
49106 * <div class='norender'><code>
49107 * var cnv;
49108 * var d;
49109 * var g;
49110 * function setup() {
49111 *   cnv = createCanvas(100, 100);
49112 *   cnv.mouseWheel(changeSize); // attach listener for
49113 *   // activity on canvas only
49114 *   d = 10;
49115 *   g = 100;
49116 * }
49117 *
49118 * function draw() {
49119 *   background(g);
49120 *   ellipse(width / 2, height / 2, d, d);
49121 * }
49122 *
49123 * // this function fires with mousewheel movement
49124 * // anywhere on screen
49125 * function mouseWheel() {
49126 *   g = g + 10;
49127 * }
49128 *
49129 * // this function fires with mousewheel movement
49130 * // over canvas only
49131 * function changeSize(event) {
49132 *   if (event.deltaY > 0) {
49133 *     d = d + 10;
49134 *   } else {
49135 *     d = d - 10;
49136 *   }
49137 * }
49138 * </code></div>
49139 *
49140 *
49141 * @alt
49142 * no display.
49143 *
49144 */
49145p5.Element.prototype.mouseWheel = function(fxn) {
49146  adjustListener('wheel', fxn, this);
49147  return this;
49148};
49149
49150/**
49151 * The .mouseReleased() function is called once after every time a
49152 * mouse button is released over the element. This can be used to
49153 * attach element specific event listeners.
49154 *
49155 * @method mouseReleased
49156 * @param  {Function|Boolean} fxn function to be fired when mouse is
49157 *                                released over the element.
49158 *                                if `false` is passed instead, the previously
49159 *                                firing function will no longer fire.
49160 * @chainable
49161 * @example
49162 * <div class='norender'><code>
49163 * var cnv;
49164 * var d;
49165 * var g;
49166 * function setup() {
49167 *   cnv = createCanvas(100, 100);
49168 *   cnv.mouseReleased(changeGray); // attach listener for
49169 *   // activity on canvas only
49170 *   d = 10;
49171 *   g = 100;
49172 * }
49173 *
49174 * function draw() {
49175 *   background(g);
49176 *   ellipse(width / 2, height / 2, d, d);
49177 * }
49178 *
49179 * // this function fires after the mouse has been
49180 * // released
49181 * function mouseReleased() {
49182 *   d = d + 10;
49183 * }
49184 *
49185 * // this function fires after the mouse has been
49186 * // released while on canvas
49187 * function changeGray() {
49188 *   g = random(0, 255);
49189 * }
49190 * </code></div>
49191 *
49192 *
49193 * @alt
49194 * no display.
49195 *
49196 */
49197p5.Element.prototype.mouseReleased = function(fxn) {
49198  adjustListener('mouseup', fxn, this);
49199  adjustListener('touchend', fxn, this);
49200  return this;
49201};
49202
49203/**
49204 * The .mouseClicked() function is called once after a mouse button is
49205 * pressed and released over the element. This can be used to
49206 * attach element specific event listeners.
49207 *
49208 * @method mouseClicked
49209 * @param  {Function|Boolean} fxn function to be fired when mouse is
49210 *                                clicked over the element.
49211 *                                if `false` is passed instead, the previously
49212 *                                firing function will no longer fire.
49213 * @chainable
49214 * @example
49215 * <div class="norender">
49216 * <code>
49217 * var cnv;
49218 * var d;
49219 * var g;
49220 *
49221 * function setup() {
49222 *   cnv = createCanvas(100, 100);
49223 *   cnv.mouseClicked(changeGray); // attach listener for
49224 *   // activity on canvas only
49225 *   d = 10;
49226 *   g = 100;
49227 * }
49228 *
49229 * function draw() {
49230 *   background(g);
49231 *   ellipse(width / 2, height / 2, d, d);
49232 * }
49233 *
49234 * // this function fires after the mouse has been
49235 * // clicked anywhere
49236 * function mouseClicked() {
49237 *   d = d + 10;
49238 * }
49239 *
49240 * // this function fires after the mouse has been
49241 * // clicked on canvas
49242 * function changeGray() {
49243 *   g = random(0, 255);
49244 * }
49245 * </code>
49246 * </div>
49247 *
49248 * @alt
49249 * no display.
49250 *
49251 */
49252p5.Element.prototype.mouseClicked = function(fxn) {
49253  adjustListener('click', fxn, this);
49254  return this;
49255};
49256
49257/**
49258 * The .mouseMoved() function is called once every time a
49259 * mouse moves over the element. This can be used to attach an
49260 * element specific event listener.
49261 *
49262 * @method mouseMoved
49263 * @param  {Function|Boolean} fxn function to be fired when a mouse moves
49264 *                                over the element.
49265 *                                if `false` is passed instead, the previously
49266 *                                firing function will no longer fire.
49267 * @chainable
49268 * @example
49269 * <div class='norender'><code>
49270 * var cnv;
49271 * var d = 30;
49272 * var g;
49273 * function setup() {
49274 *   cnv = createCanvas(100, 100);
49275 *   cnv.mouseMoved(changeSize); // attach listener for
49276 *   // activity on canvas only
49277 *   d = 10;
49278 *   g = 100;
49279 * }
49280 *
49281 * function draw() {
49282 *   background(g);
49283 *   fill(200);
49284 *   ellipse(width / 2, height / 2, d, d);
49285 * }
49286 *
49287 * // this function fires when mouse moves anywhere on
49288 * // page
49289 * function mouseMoved() {
49290 *   g = g + 5;
49291 *   if (g > 255) {
49292 *     g = 0;
49293 *   }
49294 * }
49295 *
49296 * // this function fires when mouse moves over canvas
49297 * function changeSize() {
49298 *   d = d + 2;
49299 *   if (d > 100) {
49300 *     d = 0;
49301 *   }
49302 * }
49303 * </code></div>
49304 *
49305 *
49306 * @alt
49307 * no display.
49308 *
49309 */
49310p5.Element.prototype.mouseMoved = function(fxn) {
49311  adjustListener('mousemove', fxn, this);
49312  adjustListener('touchmove', fxn, this);
49313  return this;
49314};
49315
49316/**
49317 * The .mouseOver() function is called once after every time a
49318 * mouse moves onto the element. This can be used to attach an
49319 * element specific event listener.
49320 *
49321 * @method mouseOver
49322 * @param  {Function|Boolean} fxn function to be fired when a mouse moves
49323 *                                onto the element.
49324 *                                if `false` is passed instead, the previously
49325 *                                firing function will no longer fire.
49326 * @chainable
49327 * @example
49328 * <div class='norender'><code>
49329 * var cnv;
49330 * var d;
49331 * function setup() {
49332 *   cnv = createCanvas(100, 100);
49333 *   cnv.mouseOver(changeGray);
49334 *   d = 10;
49335 * }
49336 *
49337 * function draw() {
49338 *   ellipse(width / 2, height / 2, d, d);
49339 * }
49340 *
49341 * function changeGray() {
49342 *   d = d + 10;
49343 *   if (d > 100) {
49344 *     d = 0;
49345 *   }
49346 * }
49347 * </code></div>
49348 *
49349 *
49350 * @alt
49351 * no display.
49352 *
49353 */
49354p5.Element.prototype.mouseOver = function(fxn) {
49355  adjustListener('mouseover', fxn, this);
49356  return this;
49357};
49358
49359/**
49360 * The .changed() function is called when the value of an
49361 * element changes.
49362 * This can be used to attach an element specific event listener.
49363 *
49364 * @method changed
49365 * @param  {Function|Boolean} fxn function to be fired when the value of
49366 *                                an element changes.
49367 *                                if `false` is passed instead, the previously
49368 *                                firing function will no longer fire.
49369 * @chainable
49370 * @example
49371 * <div><code>
49372 * var sel;
49373 *
49374 * function setup() {
49375 *   textAlign(CENTER);
49376 *   background(200);
49377 *   sel = createSelect();
49378 *   sel.position(10, 10);
49379 *   sel.option('pear');
49380 *   sel.option('kiwi');
49381 *   sel.option('grape');
49382 *   sel.changed(mySelectEvent);
49383 * }
49384 *
49385 * function mySelectEvent() {
49386 *   var item = sel.value();
49387 *   background(200);
49388 *   text("it's a " + item + '!', 50, 50);
49389 * }
49390 * </code></div>
49391 * <div><code>
49392 * var checkbox;
49393 * var cnv;
49394 *
49395 * function setup() {
49396 *   checkbox = createCheckbox(' fill');
49397 *   checkbox.changed(changeFill);
49398 *   cnv = createCanvas(100, 100);
49399 *   cnv.position(0, 30);
49400 *   noFill();
49401 * }
49402 *
49403 * function draw() {
49404 *   background(200);
49405 *   ellipse(50, 50, 50, 50);
49406 * }
49407 *
49408 * function changeFill() {
49409 *   if (checkbox.checked()) {
49410 *     fill(0);
49411 *   } else {
49412 *     noFill();
49413 *   }
49414 * }
49415 * </code></div>
49416 *
49417 * @alt
49418 * dropdown: pear, kiwi, grape. When selected text "its a" + selection shown.
49419 *
49420 */
49421p5.Element.prototype.changed = function(fxn) {
49422  adjustListener('change', fxn, this);
49423  return this;
49424};
49425
49426/**
49427 * The .input() function is called when any user input is
49428 * detected with an element. The input event is often used
49429 * to detect keystrokes in a input element, or changes on a
49430 * slider element. This can be used to attach an element specific
49431 * event listener.
49432 *
49433 * @method input
49434 * @param  {Function|Boolean} fxn function to be fired when any user input is
49435 *                                detected within the element.
49436 *                                if `false` is passed instead, the previously
49437 *                                firing function will no longer fire.
49438 * @chainable
49439 * @example
49440 * <div class='norender'><code>
49441 * // Open your console to see the output
49442 * function setup() {
49443 *   var inp = createInput('');
49444 *   inp.input(myInputEvent);
49445 * }
49446 *
49447 * function myInputEvent() {
49448 *   console.log('you are typing: ', this.value());
49449 * }
49450 * </code></div>
49451 *
49452 * @alt
49453 * no display.
49454 *
49455 */
49456p5.Element.prototype.input = function(fxn) {
49457  adjustListener('input', fxn, this);
49458  return this;
49459};
49460
49461/**
49462 * The .mouseOut() function is called once after every time a
49463 * mouse moves off the element. This can be used to attach an
49464 * element specific event listener.
49465 *
49466 * @method mouseOut
49467 * @param  {Function|Boolean} fxn function to be fired when a mouse
49468 *                                moves off of an element.
49469 *                                if `false` is passed instead, the previously
49470 *                                firing function will no longer fire.
49471 * @chainable
49472 * @example
49473 * <div class='norender'><code>
49474 * var cnv;
49475 * var d;
49476 * function setup() {
49477 *   cnv = createCanvas(100, 100);
49478 *   cnv.mouseOut(changeGray);
49479 *   d = 10;
49480 * }
49481 *
49482 * function draw() {
49483 *   ellipse(width / 2, height / 2, d, d);
49484 * }
49485 *
49486 * function changeGray() {
49487 *   d = d + 10;
49488 *   if (d > 100) {
49489 *     d = 0;
49490 *   }
49491 * }
49492 * </code></div>
49493 *
49494 * @alt
49495 * no display.
49496 *
49497 */
49498p5.Element.prototype.mouseOut = function(fxn) {
49499  adjustListener('mouseout', fxn, this);
49500  return this;
49501};
49502
49503/**
49504 * The .touchStarted() function is called once after every time a touch is
49505 * registered. This can be used to attach element specific event listeners.
49506 *
49507 * @method touchStarted
49508 * @param  {Function|Boolean} fxn function to be fired when a touch
49509 *                                starts over the element.
49510 *                                if `false` is passed instead, the previously
49511 *                                firing function will no longer fire.
49512 * @chainable
49513 * @example
49514 * <div class='norender'><code>
49515 * var cnv;
49516 * var d;
49517 * var g;
49518 * function setup() {
49519 *   cnv = createCanvas(100, 100);
49520 *   cnv.touchStarted(changeGray); // attach listener for
49521 *   // canvas click only
49522 *   d = 10;
49523 *   g = 100;
49524 * }
49525 *
49526 * function draw() {
49527 *   background(g);
49528 *   ellipse(width / 2, height / 2, d, d);
49529 * }
49530 *
49531 * // this function fires with any touch anywhere
49532 * function touchStarted() {
49533 *   d = d + 10;
49534 * }
49535 *
49536 * // this function fires only when cnv is clicked
49537 * function changeGray() {
49538 *   g = random(0, 255);
49539 * }
49540 * </code></div>
49541 *
49542 * @alt
49543 * no display.
49544 *
49545 */
49546p5.Element.prototype.touchStarted = function(fxn) {
49547  adjustListener('touchstart', fxn, this);
49548  adjustListener('mousedown', fxn, this);
49549  return this;
49550};
49551
49552/**
49553 * The .touchMoved() function is called once after every time a touch move is
49554 * registered. This can be used to attach element specific event listeners.
49555 *
49556 * @method touchMoved
49557 * @param  {Function|Boolean} fxn function to be fired when a touch moves over
49558 *                                the element.
49559 *                                if `false` is passed instead, the previously
49560 *                                firing function will no longer fire.
49561 * @chainable
49562 * @example
49563 * <div class='norender'><code>
49564 * var cnv;
49565 * var g;
49566 * function setup() {
49567 *   cnv = createCanvas(100, 100);
49568 *   cnv.touchMoved(changeGray); // attach listener for
49569 *   // canvas click only
49570 *   g = 100;
49571 * }
49572 *
49573 * function draw() {
49574 *   background(g);
49575 * }
49576 *
49577 * // this function fires only when cnv is clicked
49578 * function changeGray() {
49579 *   g = random(0, 255);
49580 * }
49581 * </code></div>
49582 *
49583 * @alt
49584 * no display.
49585 *
49586 */
49587p5.Element.prototype.touchMoved = function(fxn) {
49588  adjustListener('touchmove', fxn, this);
49589  adjustListener('mousemove', fxn, this);
49590  return this;
49591};
49592
49593/**
49594 * The .touchEnded() function is called once after every time a touch is
49595 * registered. This can be used to attach element specific event listeners.
49596 *
49597 * @method touchEnded
49598 * @param  {Function|Boolean} fxn function to be fired when a touch ends
49599 *                                over the element.
49600 *                                if `false` is passed instead, the previously
49601 *                                firing function will no longer fire.
49602 * @chainable
49603 * @example
49604 * <div class='norender'><code>
49605 * var cnv;
49606 * var d;
49607 * var g;
49608 * function setup() {
49609 *   cnv = createCanvas(100, 100);
49610 *   cnv.touchEnded(changeGray); // attach listener for
49611 *   // canvas click only
49612 *   d = 10;
49613 *   g = 100;
49614 * }
49615 *
49616 * function draw() {
49617 *   background(g);
49618 *   ellipse(width / 2, height / 2, d, d);
49619 * }
49620 *
49621 * // this function fires with any touch anywhere
49622 * function touchEnded() {
49623 *   d = d + 10;
49624 * }
49625 *
49626 * // this function fires only when cnv is clicked
49627 * function changeGray() {
49628 *   g = random(0, 255);
49629 * }
49630 * </code></div>
49631 *
49632 *
49633 * @alt
49634 * no display.
49635 *
49636 */
49637p5.Element.prototype.touchEnded = function(fxn) {
49638  adjustListener('touchend', fxn, this);
49639  adjustListener('mouseup', fxn, this);
49640  return this;
49641};
49642
49643/**
49644 * The .dragOver() function is called once after every time a
49645 * file is dragged over the element. This can be used to attach an
49646 * element specific event listener.
49647 *
49648 * @method dragOver
49649 * @param  {Function|Boolean} fxn function to be fired when a file is
49650 *                                dragged over the element.
49651 *                                if `false` is passed instead, the previously
49652 *                                firing function will no longer fire.
49653 * @chainable
49654 * @example
49655 * <div><code>
49656 * // To test this sketch, simply drag a
49657 * // file over the canvas
49658 * function setup() {
49659 *   var c = createCanvas(100, 100);
49660 *   background(200);
49661 *   textAlign(CENTER);
49662 *   text('Drag file', width / 2, height / 2);
49663 *   c.dragOver(dragOverCallback);
49664 * }
49665 *
49666 * // This function will be called whenever
49667 * // a file is dragged over the canvas
49668 * function dragOverCallback() {
49669 *   background(240);
49670 *   text('Dragged over', width / 2, height / 2);
49671 * }
49672 * </code></div>
49673 * @alt
49674 * nothing displayed
49675 */
49676p5.Element.prototype.dragOver = function(fxn) {
49677  adjustListener('dragover', fxn, this);
49678  return this;
49679};
49680
49681/**
49682 * The .dragLeave() function is called once after every time a
49683 * dragged file leaves the element area. This can be used to attach an
49684 * element specific event listener.
49685 *
49686 * @method dragLeave
49687 * @param  {Function|Boolean} fxn function to be fired when a file is
49688 *                                dragged off the element.
49689 *                                if `false` is passed instead, the previously
49690 *                                firing function will no longer fire.
49691 * @chainable
49692 * @example
49693 * <div><code>
49694 * // To test this sketch, simply drag a file
49695 * // over and then out of the canvas area
49696 * function setup() {
49697 *   var c = createCanvas(100, 100);
49698 *   background(200);
49699 *   textAlign(CENTER);
49700 *   text('Drag file', width / 2, height / 2);
49701 *   c.dragLeave(dragLeaveCallback);
49702 * }
49703 *
49704 * // This function will be called whenever
49705 * // a file is dragged out of the canvas
49706 * function dragLeaveCallback() {
49707 *   background(240);
49708 *   text('Dragged off', width / 2, height / 2);
49709 * }
49710 * </code></div>
49711 * @alt
49712 * nothing displayed
49713 */
49714p5.Element.prototype.dragLeave = function(fxn) {
49715  adjustListener('dragleave', fxn, this);
49716  return this;
49717};
49718
49719/**
49720 * The .drop() function is called for each file dropped on the element.
49721 * It requires a callback that is passed a p5.File object.  You can
49722 * optionally pass two callbacks, the first one (required) is triggered
49723 * for each file dropped when the file is loaded.  The second (optional)
49724 * is triggered just once when a file (or files) are dropped.
49725 *
49726 * @method drop
49727 * @param  {Function} callback  callback triggered when files are dropped.
49728 * @param  {Function} [fxn]       callback to receive loaded file.
49729 * @chainable
49730 * @example
49731 * <div><code>
49732 * function setup() {
49733 *   var c = createCanvas(100, 100);
49734 *   background(200);
49735 *   textAlign(CENTER);
49736 *   text('drop image', width / 2, height / 2);
49737 *   c.drop(gotFile);
49738 * }
49739 *
49740 * function gotFile(file) {
49741 *   var img = createImg(file.data).hide();
49742 *   // Draw the image onto the canvas
49743 *   image(img, 0, 0, width, height);
49744 * }
49745 * </code></div>
49746 *
49747 * @alt
49748 * Canvas turns into whatever image is dragged/dropped onto it.
49749 *
49750 */
49751p5.Element.prototype.drop = function(callback, fxn) {
49752  // Make a file loader callback and trigger user's callback
49753  function makeLoader(theFile) {
49754    // Making a p5.File object
49755    var p5file = new p5.File(theFile);
49756    return function(e) {
49757      p5file.data = e.target.result;
49758      callback(p5file);
49759    };
49760  }
49761
49762  // Is the file stuff supported?
49763  if (window.File && window.FileReader && window.FileList && window.Blob) {
49764    // If you want to be able to drop you've got to turn off
49765    // a lot of default behavior
49766    attachListener(
49767      'dragover',
49768      function(evt) {
49769        evt.stopPropagation();
49770        evt.preventDefault();
49771      },
49772      this
49773    );
49774
49775    // If this is a drag area we need to turn off the default behavior
49776    attachListener(
49777      'dragleave',
49778      function(evt) {
49779        evt.stopPropagation();
49780        evt.preventDefault();
49781      },
49782      this
49783    );
49784
49785    // If just one argument it's the callback for the files
49786    if (typeof fxn !== 'undefined') {
49787      attachListener('drop', fxn, this);
49788    }
49789
49790    // Deal with the files
49791    attachListener(
49792      'drop',
49793      function(evt) {
49794        evt.stopPropagation();
49795        evt.preventDefault();
49796
49797        // A FileList
49798        var files = evt.dataTransfer.files;
49799
49800        // Load each one and trigger the callback
49801        for (var i = 0; i < files.length; i++) {
49802          var f = files[i];
49803          var reader = new FileReader();
49804          reader.onload = makeLoader(f);
49805
49806          // Text or data?
49807          // This should likely be improved
49808          if (f.type.indexOf('text') > -1) {
49809            reader.readAsText(f);
49810          } else {
49811            reader.readAsDataURL(f);
49812          }
49813        }
49814      },
49815      this
49816    );
49817  } else {
49818    console.log('The File APIs are not fully supported in this browser.');
49819  }
49820
49821  return this;
49822};
49823
49824// General handler for event attaching and detaching
49825function adjustListener(ev, fxn, ctx) {
49826  if (fxn === false) {
49827    detachListener(ev, ctx);
49828  } else {
49829    attachListener(ev, fxn, ctx);
49830  }
49831  return this;
49832}
49833
49834function attachListener(ev, fxn, ctx) {
49835  // LM removing, not sure why we had this?
49836  // var _this = ctx;
49837  // var f = function (e) { fxn(e, _this); };
49838
49839  // detach the old listener if there was one
49840  if (ctx._events[ev]) {
49841    detachListener(ev, ctx);
49842  }
49843  var f = fxn.bind(ctx);
49844  ctx.elt.addEventListener(ev, f, false);
49845  ctx._events[ev] = f;
49846}
49847
49848function detachListener(ev, ctx) {
49849  var f = ctx._events[ev];
49850  ctx.elt.removeEventListener(ev, f, false);
49851  ctx._events[ev] = null;
49852}
49853
49854/**
49855 * Helper fxn for sharing pixel methods
49856 *
49857 */
49858p5.Element.prototype._setProperty = function(prop, value) {
49859  this[prop] = value;
49860};
49861
49862module.exports = p5.Element;
49863
49864},{"./core":22}],28:[function(_dereq_,module,exports){
49865/**
49866 * @module Rendering
49867 * @submodule Rendering
49868 * @for p5
49869 */
49870
49871'use strict';
49872
49873var p5 = _dereq_('./core');
49874var constants = _dereq_('./constants');
49875
49876/**
49877 * Thin wrapper around a renderer, to be used for creating a
49878 * graphics buffer object. Use this class if you need
49879 * to draw into an off-screen graphics buffer. The two parameters define the
49880 * width and height in pixels. The fields and methods for this class are
49881 * extensive, but mirror the normal drawing API for p5.
49882 *
49883 * @class p5.Graphics
49884 * @extends p5.Element
49885 * @param {Number} w            width
49886 * @param {Number} h            height
49887 * @param {Constant} renderer   the renderer to use, either P2D or WEBGL
49888 * @param {p5} [pInst]          pointer to p5 instance
49889 */
49890p5.Graphics = function(w, h, renderer, pInst) {
49891  var r = renderer || constants.P2D;
49892
49893  this.canvas = document.createElement('canvas');
49894  var node = pInst._userNode || document.body;
49895  node.appendChild(this.canvas);
49896
49897  p5.Element.call(this, this.canvas, pInst, false);
49898
49899  // bind methods and props of p5 to the new object
49900  for (var p in p5.prototype) {
49901    if (!this[p]) {
49902      if (typeof p5.prototype[p] === 'function') {
49903        this[p] = p5.prototype[p].bind(this);
49904      } else {
49905        this[p] = p5.prototype[p];
49906      }
49907    }
49908  }
49909
49910  p5.prototype._initializeInstanceVariables.apply(this);
49911  this.width = w;
49912  this.height = h;
49913  this._pixelDensity = pInst._pixelDensity;
49914
49915  if (r === constants.WEBGL) {
49916    this._renderer = new p5.RendererGL(this.canvas, this, false);
49917  } else {
49918    this._renderer = new p5.Renderer2D(this.canvas, this, false);
49919  }
49920  pInst._elements.push(this);
49921
49922  this._renderer.resize(w, h);
49923  this._renderer._applyDefaults();
49924  return this;
49925};
49926
49927p5.Graphics.prototype = Object.create(p5.Element.prototype);
49928
49929/**
49930 * Removes a Graphics object from the page and frees any resources
49931 * associated with it.
49932 *
49933 * @method remove
49934 *
49935 * @example
49936 * <div class='norender'><code>
49937 * var bg;
49938 * function setup() {
49939 *   bg = createCanvas(100, 100);
49940 *   bg.background(0);
49941 *   image(bg, 0, 0);
49942 *   bg.remove();
49943 * }
49944 * </code></div>
49945 *
49946 * <div><code>
49947 * var bg;
49948 * function setup() {
49949 *   pixelDensity(1);
49950 *   createCanvas(100, 100);
49951 *   stroke(255);
49952 *   fill(0);
49953 *
49954 *   // create and draw the background image
49955 *   bg = createGraphics(100, 100);
49956 *   bg.background(200);
49957 *   bg.ellipse(50, 50, 80, 80);
49958 * }
49959 * function draw() {
49960 *   var t = millis() / 1000;
49961 *   // draw the background
49962 *   if (bg) {
49963 *     image(bg, frameCount % 100, 0);
49964 *     image(bg, frameCount % 100 - 100, 0);
49965 *   }
49966 *   // draw the foreground
49967 *   var p = p5.Vector.fromAngle(t, 35).add(50, 50);
49968 *   ellipse(p.x, p.y, 30);
49969 * }
49970 * function mouseClicked() {
49971 *   // remove the background
49972 *   if (bg) {
49973 *     bg.remove();
49974 *     bg = null;
49975 *   }
49976 * }
49977 * </code></div>
49978 *
49979 * @alt
49980 * no image
49981 * a multi-colored circle moving back and forth over a scrolling background.
49982 *
49983 */
49984p5.Graphics.prototype.remove = function() {
49985  if (this.elt.parentNode) {
49986    this.elt.parentNode.removeChild(this.elt);
49987  }
49988  var idx = this._pInst._elements.indexOf(this);
49989  if (idx !== -1) {
49990    this._pInst._elements.splice(idx, 1);
49991  }
49992  for (var elt_ev in this._events) {
49993    this.elt.removeEventListener(elt_ev, this._events[elt_ev]);
49994  }
49995};
49996
49997module.exports = p5.Graphics;
49998
49999},{"./constants":21,"./core":22}],29:[function(_dereq_,module,exports){
50000/**
50001 * @module Rendering
50002 * @submodule Rendering
50003 * @for p5
50004 */
50005
50006'use strict';
50007
50008var p5 = _dereq_('./core');
50009var constants = _dereq_('../core/constants');
50010
50011/**
50012 * Main graphics and rendering context, as well as the base API
50013 * implementation for p5.js "core". To be used as the superclass for
50014 * Renderer2D and Renderer3D classes, respecitvely.
50015 *
50016 * @class p5.Renderer
50017 * @constructor
50018 * @extends p5.Element
50019 * @param {String} elt DOM node that is wrapped
50020 * @param {p5} [pInst] pointer to p5 instance
50021 * @param {Boolean} [isMainCanvas] whether we're using it as main canvas
50022 */
50023p5.Renderer = function(elt, pInst, isMainCanvas) {
50024  p5.Element.call(this, elt, pInst);
50025  this.canvas = elt;
50026  this._pInst = pInst;
50027  if (isMainCanvas) {
50028    this._isMainCanvas = true;
50029    // for pixel method sharing with pimage
50030    this._pInst._setProperty('_curElement', this);
50031    this._pInst._setProperty('canvas', this.canvas);
50032    this._pInst._setProperty('width', this.width);
50033    this._pInst._setProperty('height', this.height);
50034  } else {
50035    // hide if offscreen buffer by default
50036    this.canvas.style.display = 'none';
50037    this._styles = []; // non-main elt styles stored in p5.Renderer
50038  }
50039
50040  this._textSize = 12;
50041  this._textLeading = 15;
50042  this._textFont = 'sans-serif';
50043  this._textStyle = constants.NORMAL;
50044  this._textAscent = null;
50045  this._textDescent = null;
50046
50047  this._rectMode = constants.CORNER;
50048  this._ellipseMode = constants.CENTER;
50049  this._curveTightness = 0;
50050  this._imageMode = constants.CORNER;
50051
50052  this._tint = null;
50053  this._doStroke = true;
50054  this._doFill = true;
50055  this._strokeSet = false;
50056  this._fillSet = false;
50057};
50058
50059p5.Renderer.prototype = Object.create(p5.Element.prototype);
50060
50061// the renderer should return a 'style' object that it wishes to
50062// store on the push stack.
50063p5.Renderer.prototype.push = function() {
50064  return {
50065    properties: {
50066      _doStroke: this._doStroke,
50067      _strokeSet: this._strokeSet,
50068      _doFill: this._doFill,
50069      _fillSet: this._fillSet,
50070      _tint: this._tint,
50071      _imageMode: this._imageMode,
50072      _rectMode: this._rectMode,
50073      _ellipseMode: this._ellipseMode,
50074      _textFont: this._textFont,
50075      _textLeading: this._textLeading,
50076      _textSize: this._textSize,
50077      _textStyle: this._textStyle
50078    }
50079  };
50080};
50081
50082// this is implementation of Object.assign() which is unavailable in
50083// IE11 and (non-Chrome) Android browsers.
50084// The assign() method is used to copy the values of all enumerable
50085// own properties from one or more source objects to a target object.
50086// It will return the target object.
50087function assign(to, firstSource) {
50088  for (var i = 1; i < arguments.length; i++) {
50089    var nextSource = arguments[i];
50090    if (nextSource === undefined || nextSource === null) {
50091      continue;
50092    }
50093
50094    for (var nextKey in nextSource)
50095      if (nextSource.hasOwnProperty(nextKey)) {
50096        to[nextKey] = nextSource[nextKey];
50097      }
50098  }
50099  return to;
50100}
50101
50102// a pop() operation is in progress
50103// the renderer is passed the 'style' object that it returned
50104// from its push() method.
50105p5.Renderer.prototype.pop = function(style) {
50106  if (style.properties) {
50107    // copy the style properties back into the renderer
50108    assign(this, style.properties);
50109  }
50110};
50111
50112/**
50113 * Resize our canvas element.
50114 */
50115p5.Renderer.prototype.resize = function(w, h) {
50116  this.width = w;
50117  this.height = h;
50118  this.elt.width = w * this._pInst._pixelDensity;
50119  this.elt.height = h * this._pInst._pixelDensity;
50120  this.elt.style.width = w + 'px';
50121  this.elt.style.height = h + 'px';
50122  if (this._isMainCanvas) {
50123    this._pInst._setProperty('width', this.width);
50124    this._pInst._setProperty('height', this.height);
50125  }
50126};
50127
50128p5.Renderer.prototype.textLeading = function(l) {
50129  if (typeof l === 'number') {
50130    this._setProperty('_textLeading', l);
50131    return this;
50132  }
50133
50134  return this._textLeading;
50135};
50136
50137p5.Renderer.prototype.textSize = function(s) {
50138  if (typeof s === 'number') {
50139    this._setProperty('_textSize', s);
50140    this._setProperty('_textLeading', s * constants._DEFAULT_LEADMULT);
50141    return this._applyTextProperties();
50142  }
50143
50144  return this._textSize;
50145};
50146
50147p5.Renderer.prototype.textStyle = function(s) {
50148  if (s) {
50149    if (
50150      s === constants.NORMAL ||
50151      s === constants.ITALIC ||
50152      s === constants.BOLD
50153    ) {
50154      this._setProperty('_textStyle', s);
50155    }
50156
50157    return this._applyTextProperties();
50158  }
50159
50160  return this._textStyle;
50161};
50162
50163p5.Renderer.prototype.textAscent = function() {
50164  if (this._textAscent === null) {
50165    this._updateTextMetrics();
50166  }
50167  return this._textAscent;
50168};
50169
50170p5.Renderer.prototype.textDescent = function() {
50171  if (this._textDescent === null) {
50172    this._updateTextMetrics();
50173  }
50174  return this._textDescent;
50175};
50176
50177p5.Renderer.prototype._applyDefaults = function() {
50178  return this;
50179};
50180
50181/**
50182 * Helper fxn to check font type (system or otf)
50183 */
50184p5.Renderer.prototype._isOpenType = function(f) {
50185  f = f || this._textFont;
50186  return typeof f === 'object' && f.font && f.font.supported;
50187};
50188
50189p5.Renderer.prototype._updateTextMetrics = function() {
50190  if (this._isOpenType()) {
50191    this._setProperty('_textAscent', this._textFont._textAscent());
50192    this._setProperty('_textDescent', this._textFont._textDescent());
50193    return this;
50194  }
50195
50196  // Adapted from http://stackoverflow.com/a/25355178
50197  var text = document.createElement('span');
50198  text.style.fontFamily = this._textFont;
50199  text.style.fontSize = this._textSize + 'px';
50200  text.innerHTML = 'ABCjgq|';
50201
50202  var block = document.createElement('div');
50203  block.style.display = 'inline-block';
50204  block.style.width = '1px';
50205  block.style.height = '0px';
50206
50207  var container = document.createElement('div');
50208  container.appendChild(text);
50209  container.appendChild(block);
50210
50211  container.style.height = '0px';
50212  container.style.overflow = 'hidden';
50213  document.body.appendChild(container);
50214
50215  block.style.verticalAlign = 'baseline';
50216  var blockOffset = calculateOffset(block);
50217  var textOffset = calculateOffset(text);
50218  var ascent = blockOffset[1] - textOffset[1];
50219
50220  block.style.verticalAlign = 'bottom';
50221  blockOffset = calculateOffset(block);
50222  textOffset = calculateOffset(text);
50223  var height = blockOffset[1] - textOffset[1];
50224  var descent = height - ascent;
50225
50226  document.body.removeChild(container);
50227
50228  this._setProperty('_textAscent', ascent);
50229  this._setProperty('_textDescent', descent);
50230
50231  return this;
50232};
50233
50234/**
50235 * Helper fxn to measure ascent and descent.
50236 * Adapted from http://stackoverflow.com/a/25355178
50237 */
50238function calculateOffset(object) {
50239  var currentLeft = 0,
50240    currentTop = 0;
50241  if (object.offsetParent) {
50242    do {
50243      currentLeft += object.offsetLeft;
50244      currentTop += object.offsetTop;
50245    } while ((object = object.offsetParent));
50246  } else {
50247    currentLeft += object.offsetLeft;
50248    currentTop += object.offsetTop;
50249  }
50250  return [currentLeft, currentTop];
50251}
50252
50253module.exports = p5.Renderer;
50254
50255},{"../core/constants":21,"./core":22}],30:[function(_dereq_,module,exports){
50256'use strict';
50257
50258var p5 = _dereq_('./core');
50259var canvas = _dereq_('./canvas');
50260var constants = _dereq_('./constants');
50261var filters = _dereq_('../image/filters');
50262
50263_dereq_('./p5.Renderer');
50264
50265/**
50266 * p5.Renderer2D
50267 * The 2D graphics canvas renderer class.
50268 * extends p5.Renderer
50269 */
50270var styleEmpty = 'rgba(0,0,0,0)';
50271// var alphaThreshold = 0.00125; // minimum visible
50272
50273p5.Renderer2D = function(elt, pInst, isMainCanvas) {
50274  p5.Renderer.call(this, elt, pInst, isMainCanvas);
50275  this.drawingContext = this.canvas.getContext('2d');
50276  this._pInst._setProperty('drawingContext', this.drawingContext);
50277  return this;
50278};
50279
50280p5.Renderer2D.prototype = Object.create(p5.Renderer.prototype);
50281
50282p5.Renderer2D.prototype._applyDefaults = function() {
50283  this._cachedFillStyle = this._cachedStrokeStyle = undefined;
50284  this._setFill(constants._DEFAULT_FILL);
50285  this._setStroke(constants._DEFAULT_STROKE);
50286  this.drawingContext.lineCap = constants.ROUND;
50287  this.drawingContext.font = 'normal 12px sans-serif';
50288};
50289
50290p5.Renderer2D.prototype.resize = function(w, h) {
50291  p5.Renderer.prototype.resize.call(this, w, h);
50292  this.drawingContext.scale(
50293    this._pInst._pixelDensity,
50294    this._pInst._pixelDensity
50295  );
50296};
50297
50298//////////////////////////////////////////////
50299// COLOR | Setting
50300//////////////////////////////////////////////
50301
50302p5.Renderer2D.prototype.background = function() {
50303  this.drawingContext.save();
50304  this.drawingContext.setTransform(1, 0, 0, 1, 0, 0);
50305  this.drawingContext.scale(
50306    this._pInst._pixelDensity,
50307    this._pInst._pixelDensity
50308  );
50309
50310  if (arguments[0] instanceof p5.Image) {
50311    this._pInst.image(arguments[0], 0, 0, this.width, this.height);
50312  } else {
50313    var curFill = this._getFill();
50314    // create background rect
50315    var color = this._pInst.color.apply(this._pInst, arguments);
50316    var newFill = color.toString();
50317    this._setFill(newFill);
50318    this.drawingContext.fillRect(0, 0, this.width, this.height);
50319    // reset fill
50320    this._setFill(curFill);
50321  }
50322  this.drawingContext.restore();
50323};
50324
50325p5.Renderer2D.prototype.clear = function() {
50326  this.drawingContext.save();
50327  this.drawingContext.setTransform(1, 0, 0, 1, 0, 0);
50328  this.drawingContext.clearRect(0, 0, this.width, this.height);
50329  this.drawingContext.restore();
50330};
50331
50332p5.Renderer2D.prototype.fill = function() {
50333  var color = this._pInst.color.apply(this._pInst, arguments);
50334  this._setFill(color.toString());
50335};
50336
50337p5.Renderer2D.prototype.stroke = function() {
50338  var color = this._pInst.color.apply(this._pInst, arguments);
50339  this._setStroke(color.toString());
50340};
50341
50342//////////////////////////////////////////////
50343// IMAGE | Loading & Displaying
50344//////////////////////////////////////////////
50345
50346p5.Renderer2D.prototype.image = function(
50347  img,
50348  sx,
50349  sy,
50350  sWidth,
50351  sHeight,
50352  dx,
50353  dy,
50354  dWidth,
50355  dHeight
50356) {
50357  var cnv;
50358  try {
50359    if (this._tint) {
50360      if (p5.MediaElement && img instanceof p5.MediaElement) {
50361        img.loadPixels();
50362      }
50363      if (img.canvas) {
50364        cnv = this._getTintedImageCanvas(img);
50365      }
50366    }
50367    if (!cnv) {
50368      cnv = img.canvas || img.elt;
50369    }
50370    this.drawingContext.drawImage(
50371      cnv,
50372      sx,
50373      sy,
50374      sWidth,
50375      sHeight,
50376      dx,
50377      dy,
50378      dWidth,
50379      dHeight
50380    );
50381  } catch (e) {
50382    if (e.name !== 'NS_ERROR_NOT_AVAILABLE') {
50383      throw e;
50384    }
50385  }
50386};
50387
50388p5.Renderer2D.prototype._getTintedImageCanvas = function(img) {
50389  if (!img.canvas) {
50390    return img;
50391  }
50392  var pixels = filters._toPixels(img.canvas);
50393  var tmpCanvas = document.createElement('canvas');
50394  tmpCanvas.width = img.canvas.width;
50395  tmpCanvas.height = img.canvas.height;
50396  var tmpCtx = tmpCanvas.getContext('2d');
50397  var id = tmpCtx.createImageData(img.canvas.width, img.canvas.height);
50398  var newPixels = id.data;
50399  for (var i = 0; i < pixels.length; i += 4) {
50400    var r = pixels[i];
50401    var g = pixels[i + 1];
50402    var b = pixels[i + 2];
50403    var a = pixels[i + 3];
50404    newPixels[i] = r * this._tint[0] / 255;
50405    newPixels[i + 1] = g * this._tint[1] / 255;
50406    newPixels[i + 2] = b * this._tint[2] / 255;
50407    newPixels[i + 3] = a * this._tint[3] / 255;
50408  }
50409  tmpCtx.putImageData(id, 0, 0);
50410  return tmpCanvas;
50411};
50412
50413//////////////////////////////////////////////
50414// IMAGE | Pixels
50415//////////////////////////////////////////////
50416
50417p5.Renderer2D.prototype.blendMode = function(mode) {
50418  this.drawingContext.globalCompositeOperation = mode;
50419};
50420p5.Renderer2D.prototype.blend = function() {
50421  var currBlend = this.drawingContext.globalCompositeOperation;
50422  var blendMode = arguments[arguments.length - 1];
50423
50424  var copyArgs = Array.prototype.slice.call(arguments, 0, arguments.length - 1);
50425
50426  this.drawingContext.globalCompositeOperation = blendMode;
50427  if (this._pInst) {
50428    this._pInst.copy.apply(this._pInst, copyArgs);
50429  } else {
50430    this.copy.apply(this, copyArgs);
50431  }
50432  this.drawingContext.globalCompositeOperation = currBlend;
50433};
50434
50435p5.Renderer2D.prototype.copy = function() {
50436  var srcImage, sx, sy, sw, sh, dx, dy, dw, dh;
50437  if (arguments.length === 9) {
50438    srcImage = arguments[0];
50439    sx = arguments[1];
50440    sy = arguments[2];
50441    sw = arguments[3];
50442    sh = arguments[4];
50443    dx = arguments[5];
50444    dy = arguments[6];
50445    dw = arguments[7];
50446    dh = arguments[8];
50447  } else if (arguments.length === 8) {
50448    srcImage = this._pInst;
50449    sx = arguments[0];
50450    sy = arguments[1];
50451    sw = arguments[2];
50452    sh = arguments[3];
50453    dx = arguments[4];
50454    dy = arguments[5];
50455    dw = arguments[6];
50456    dh = arguments[7];
50457  } else {
50458    throw new Error('Signature not supported');
50459  }
50460  p5.Renderer2D._copyHelper(this, srcImage, sx, sy, sw, sh, dx, dy, dw, dh);
50461};
50462
50463p5.Renderer2D._copyHelper = function(
50464  dstImage,
50465  srcImage,
50466  sx,
50467  sy,
50468  sw,
50469  sh,
50470  dx,
50471  dy,
50472  dw,
50473  dh
50474) {
50475  srcImage.loadPixels();
50476  var s = srcImage.canvas.width / srcImage.width;
50477  dstImage.drawingContext.drawImage(
50478    srcImage.canvas,
50479    s * sx,
50480    s * sy,
50481    s * sw,
50482    s * sh,
50483    dx,
50484    dy,
50485    dw,
50486    dh
50487  );
50488};
50489
50490p5.Renderer2D.prototype.get = function(x, y, w, h) {
50491  if (
50492    x === undefined &&
50493    y === undefined &&
50494    w === undefined &&
50495    h === undefined
50496  ) {
50497    x = 0;
50498    y = 0;
50499    w = this.width;
50500    h = this.height;
50501  } else if (w === undefined && h === undefined) {
50502    w = 1;
50503    h = 1;
50504  }
50505
50506  // if the section does not overlap the canvas
50507  if (x + w < 0 || y + h < 0 || x > this.width || y > this.height) {
50508    return [0, 0, 0, 255];
50509  }
50510
50511  var ctx = this._pInst || this;
50512  ctx.loadPixels();
50513
50514  var pd = ctx._pixelDensity;
50515
50516  // round down to get integer numbers
50517  x = Math.floor(x);
50518  y = Math.floor(y);
50519  w = Math.floor(w);
50520  h = Math.floor(h);
50521
50522  var sx = x * pd;
50523  var sy = y * pd;
50524  if (w === 1 && h === 1 && !(this instanceof p5.RendererGL)) {
50525    var imageData = this.drawingContext.getImageData(sx, sy, 1, 1).data;
50526    //imageData = [0,0,0,0];
50527    return [imageData[0], imageData[1], imageData[2], imageData[3]];
50528  } else {
50529    //auto constrain the width and height to
50530    //dimensions of the source image
50531    var dw = Math.min(w, ctx.width);
50532    var dh = Math.min(h, ctx.height);
50533    var sw = dw * pd;
50534    var sh = dh * pd;
50535
50536    var region = new p5.Image(dw, dh);
50537    region.canvas
50538      .getContext('2d')
50539      .drawImage(this.canvas, sx, sy, sw, sh, 0, 0, dw, dh);
50540
50541    return region;
50542  }
50543};
50544
50545p5.Renderer2D.prototype.loadPixels = function() {
50546  var ctx = this._pInst || this; // if called by p5.Image
50547  var pd = ctx._pixelDensity;
50548  var w = this.width * pd;
50549  var h = this.height * pd;
50550  var imageData = this.drawingContext.getImageData(0, 0, w, h);
50551  // @todo this should actually set pixels per object, so diff buffers can
50552  // have diff pixel arrays.
50553  ctx._setProperty('imageData', imageData);
50554  ctx._setProperty('pixels', imageData.data);
50555};
50556
50557p5.Renderer2D.prototype.set = function(x, y, imgOrCol) {
50558  // round down to get integer numbers
50559  x = Math.floor(x);
50560  y = Math.floor(y);
50561  var ctx = this._pInst || this;
50562  if (imgOrCol instanceof p5.Image) {
50563    this.drawingContext.save();
50564    this.drawingContext.setTransform(1, 0, 0, 1, 0, 0);
50565    this.drawingContext.scale(ctx._pixelDensity, ctx._pixelDensity);
50566    this.drawingContext.drawImage(imgOrCol.canvas, x, y);
50567    this.loadPixels.call(ctx);
50568    this.drawingContext.restore();
50569  } else {
50570    var r = 0,
50571      g = 0,
50572      b = 0,
50573      a = 0;
50574    var idx =
50575      4 *
50576      (y * ctx._pixelDensity * (this.width * ctx._pixelDensity) +
50577        x * ctx._pixelDensity);
50578    if (!ctx.imageData) {
50579      ctx.loadPixels.call(ctx);
50580    }
50581    if (typeof imgOrCol === 'number') {
50582      if (idx < ctx.pixels.length) {
50583        r = imgOrCol;
50584        g = imgOrCol;
50585        b = imgOrCol;
50586        a = 255;
50587        //this.updatePixels.call(this);
50588      }
50589    } else if (imgOrCol instanceof Array) {
50590      if (imgOrCol.length < 4) {
50591        throw new Error('pixel array must be of the form [R, G, B, A]');
50592      }
50593      if (idx < ctx.pixels.length) {
50594        r = imgOrCol[0];
50595        g = imgOrCol[1];
50596        b = imgOrCol[2];
50597        a = imgOrCol[3];
50598        //this.updatePixels.call(this);
50599      }
50600    } else if (imgOrCol instanceof p5.Color) {
50601      if (idx < ctx.pixels.length) {
50602        r = imgOrCol.levels[0];
50603        g = imgOrCol.levels[1];
50604        b = imgOrCol.levels[2];
50605        a = imgOrCol.levels[3];
50606        //this.updatePixels.call(this);
50607      }
50608    }
50609    // loop over pixelDensity * pixelDensity
50610    for (var i = 0; i < ctx._pixelDensity; i++) {
50611      for (var j = 0; j < ctx._pixelDensity; j++) {
50612        // loop over
50613        idx =
50614          4 *
50615          ((y * ctx._pixelDensity + j) * this.width * ctx._pixelDensity +
50616            (x * ctx._pixelDensity + i));
50617        ctx.pixels[idx] = r;
50618        ctx.pixels[idx + 1] = g;
50619        ctx.pixels[idx + 2] = b;
50620        ctx.pixels[idx + 3] = a;
50621      }
50622    }
50623  }
50624};
50625
50626p5.Renderer2D.prototype.updatePixels = function(x, y, w, h) {
50627  var ctx = this._pInst || this;
50628  var pd = ctx._pixelDensity;
50629  if (
50630    x === undefined &&
50631    y === undefined &&
50632    w === undefined &&
50633    h === undefined
50634  ) {
50635    x = 0;
50636    y = 0;
50637    w = this.width;
50638    h = this.height;
50639  }
50640  w *= pd;
50641  h *= pd;
50642
50643  this.drawingContext.putImageData(ctx.imageData, x, y, 0, 0, w, h);
50644};
50645
50646//////////////////////////////////////////////
50647// SHAPE | 2D Primitives
50648//////////////////////////////////////////////
50649
50650/**
50651 * Generate a cubic Bezier representing an arc on the unit circle of total
50652 * angle `size` radians, beginning `start` radians above the x-axis. Up to
50653 * four of these curves are combined to make a full arc.
50654 *
50655 * See www.joecridge.me/bezier.pdf for an explanation of the method.
50656 */
50657p5.Renderer2D.prototype._acuteArcToBezier = function _acuteArcToBezier(
50658  start,
50659  size
50660) {
50661  // Evauate constants.
50662  var alpha = size / 2.0,
50663    cos_alpha = Math.cos(alpha),
50664    sin_alpha = Math.sin(alpha),
50665    cot_alpha = 1.0 / Math.tan(alpha),
50666    phi = start + alpha, // This is how far the arc needs to be rotated.
50667    cos_phi = Math.cos(phi),
50668    sin_phi = Math.sin(phi),
50669    lambda = (4.0 - cos_alpha) / 3.0,
50670    mu = sin_alpha + (cos_alpha - lambda) * cot_alpha;
50671
50672  // Return rotated waypoints.
50673  return {
50674    ax: Math.cos(start),
50675    ay: Math.sin(start),
50676    bx: lambda * cos_phi + mu * sin_phi,
50677    by: lambda * sin_phi - mu * cos_phi,
50678    cx: lambda * cos_phi - mu * sin_phi,
50679    cy: lambda * sin_phi + mu * cos_phi,
50680    dx: Math.cos(start + size),
50681    dy: Math.sin(start + size)
50682  };
50683};
50684
50685p5.Renderer2D.prototype.arc = function(x, y, w, h, start, stop, mode) {
50686  var ctx = this.drawingContext;
50687  var vals = canvas.arcModeAdjust(x, y, w, h, this._ellipseMode);
50688  var rx = vals.w / 2.0;
50689  var ry = vals.h / 2.0;
50690  var epsilon = 0.00001; // Smallest visible angle on displays up to 4K.
50691  var arcToDraw = 0;
50692  var curves = [];
50693
50694  // Create curves
50695  while (stop - start > epsilon) {
50696    arcToDraw = Math.min(stop - start, constants.HALF_PI);
50697    curves.push(this._acuteArcToBezier(start, arcToDraw));
50698    start += arcToDraw;
50699  }
50700
50701  // Fill curves
50702  if (this._doFill) {
50703    ctx.beginPath();
50704    curves.forEach(function(curve, index) {
50705      if (index === 0) {
50706        ctx.moveTo(vals.x + curve.ax * rx, vals.y + curve.ay * ry);
50707      }
50708      // prettier-ignore
50709      ctx.bezierCurveTo(vals.x + curve.bx * rx, vals.y + curve.by * ry,
50710                          vals.x + curve.cx * rx, vals.y + curve.cy * ry,
50711                          vals.x + curve.dx * rx, vals.y + curve.dy * ry);
50712    });
50713    if (mode === constants.PIE || mode == null) {
50714      ctx.lineTo(vals.x, vals.y);
50715    }
50716    ctx.closePath();
50717    ctx.fill();
50718  }
50719
50720  // Stroke curves
50721  if (this._doStroke) {
50722    ctx.beginPath();
50723    curves.forEach(function(curve, index) {
50724      if (index === 0) {
50725        ctx.moveTo(vals.x + curve.ax * rx, vals.y + curve.ay * ry);
50726      }
50727      // prettier-ignore
50728      ctx.bezierCurveTo(vals.x + curve.bx * rx, vals.y + curve.by * ry,
50729                          vals.x + curve.cx * rx, vals.y + curve.cy * ry,
50730                          vals.x + curve.dx * rx, vals.y + curve.dy * ry);
50731    });
50732    if (mode === constants.PIE) {
50733      ctx.lineTo(vals.x, vals.y);
50734      ctx.closePath();
50735    } else if (mode === constants.CHORD) {
50736      ctx.closePath();
50737    }
50738    ctx.stroke();
50739  }
50740  return this;
50741};
50742
50743p5.Renderer2D.prototype.ellipse = function(args) {
50744  var ctx = this.drawingContext;
50745  var doFill = this._doFill,
50746    doStroke = this._doStroke;
50747  var x = args[0],
50748    y = args[1],
50749    w = args[2],
50750    h = args[3];
50751  if (doFill && !doStroke) {
50752    if (this._getFill() === styleEmpty) {
50753      return this;
50754    }
50755  } else if (!doFill && doStroke) {
50756    if (this._getStroke() === styleEmpty) {
50757      return this;
50758    }
50759  }
50760  var kappa = 0.5522847498,
50761    ox = w / 2 * kappa, // control point offset horizontal
50762    oy = h / 2 * kappa, // control point offset vertical
50763    xe = x + w, // x-end
50764    ye = y + h, // y-end
50765    xm = x + w / 2, // x-middle
50766    ym = y + h / 2; // y-middle
50767  ctx.beginPath();
50768  ctx.moveTo(x, ym);
50769  ctx.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y);
50770  ctx.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym);
50771  ctx.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye);
50772  ctx.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym);
50773  ctx.closePath();
50774  if (doFill) {
50775    ctx.fill();
50776  }
50777  if (doStroke) {
50778    ctx.stroke();
50779  }
50780};
50781
50782p5.Renderer2D.prototype.line = function(x1, y1, x2, y2) {
50783  var ctx = this.drawingContext;
50784  if (!this._doStroke) {
50785    return this;
50786  } else if (this._getStroke() === styleEmpty) {
50787    return this;
50788  }
50789  // Translate the line by (0.5, 0.5) to draw it crisp
50790  if (ctx.lineWidth % 2 === 1) {
50791    ctx.translate(0.5, 0.5);
50792  }
50793  ctx.beginPath();
50794  ctx.moveTo(x1, y1);
50795  ctx.lineTo(x2, y2);
50796  ctx.stroke();
50797  if (ctx.lineWidth % 2 === 1) {
50798    ctx.translate(-0.5, -0.5);
50799  }
50800  return this;
50801};
50802
50803p5.Renderer2D.prototype.point = function(x, y) {
50804  var ctx = this.drawingContext;
50805  if (!this._doStroke) {
50806    return this;
50807  } else if (this._getStroke() === styleEmpty) {
50808    return this;
50809  }
50810  var s = this._getStroke();
50811  var f = this._getFill();
50812  x = Math.round(x);
50813  y = Math.round(y);
50814  // swapping fill color to stroke and back after for correct point rendering
50815  this._setFill(s);
50816  if (ctx.lineWidth > 1) {
50817    ctx.beginPath();
50818    ctx.arc(x, y, ctx.lineWidth / 2, 0, constants.TWO_PI, false);
50819    ctx.fill();
50820  } else {
50821    ctx.fillRect(x, y, 1, 1);
50822  }
50823  this._setFill(f);
50824};
50825
50826p5.Renderer2D.prototype.quad = function(x1, y1, x2, y2, x3, y3, x4, y4) {
50827  var ctx = this.drawingContext;
50828  var doFill = this._doFill,
50829    doStroke = this._doStroke;
50830  if (doFill && !doStroke) {
50831    if (this._getFill() === styleEmpty) {
50832      return this;
50833    }
50834  } else if (!doFill && doStroke) {
50835    if (this._getStroke() === styleEmpty) {
50836      return this;
50837    }
50838  }
50839  ctx.beginPath();
50840  ctx.moveTo(x1, y1);
50841  ctx.lineTo(x2, y2);
50842  ctx.lineTo(x3, y3);
50843  ctx.lineTo(x4, y4);
50844  ctx.closePath();
50845  if (doFill) {
50846    ctx.fill();
50847  }
50848  if (doStroke) {
50849    ctx.stroke();
50850  }
50851  return this;
50852};
50853
50854p5.Renderer2D.prototype.rect = function(args) {
50855  var x = args[0],
50856    y = args[1],
50857    w = args[2],
50858    h = args[3],
50859    tl = args[4],
50860    tr = args[5],
50861    br = args[6],
50862    bl = args[7];
50863  var ctx = this.drawingContext;
50864  var doFill = this._doFill,
50865    doStroke = this._doStroke;
50866  if (doFill && !doStroke) {
50867    if (this._getFill() === styleEmpty) {
50868      return this;
50869    }
50870  } else if (!doFill && doStroke) {
50871    if (this._getStroke() === styleEmpty) {
50872      return this;
50873    }
50874  }
50875  // Translate the line by (0.5, 0.5) to draw a crisp rectangle border
50876  if (this._doStroke && ctx.lineWidth % 2 === 1) {
50877    ctx.translate(0.5, 0.5);
50878  }
50879  ctx.beginPath();
50880
50881  if (typeof tl === 'undefined') {
50882    // No rounded corners
50883    ctx.rect(x, y, w, h);
50884  } else {
50885    // At least one rounded corner
50886    // Set defaults when not specified
50887    if (typeof tr === 'undefined') {
50888      tr = tl;
50889    }
50890    if (typeof br === 'undefined') {
50891      br = tr;
50892    }
50893    if (typeof bl === 'undefined') {
50894      bl = br;
50895    }
50896
50897    var hw = w / 2;
50898    var hh = h / 2;
50899
50900    // Clip radii
50901    if (w < 2 * tl) {
50902      tl = hw;
50903    }
50904    if (h < 2 * tl) {
50905      tl = hh;
50906    }
50907    if (w < 2 * tr) {
50908      tr = hw;
50909    }
50910    if (h < 2 * tr) {
50911      tr = hh;
50912    }
50913    if (w < 2 * br) {
50914      br = hw;
50915    }
50916    if (h < 2 * br) {
50917      br = hh;
50918    }
50919    if (w < 2 * bl) {
50920      bl = hw;
50921    }
50922    if (h < 2 * bl) {
50923      bl = hh;
50924    }
50925
50926    // Draw shape
50927    ctx.beginPath();
50928    ctx.moveTo(x + tl, y);
50929    ctx.arcTo(x + w, y, x + w, y + h, tr);
50930    ctx.arcTo(x + w, y + h, x, y + h, br);
50931    ctx.arcTo(x, y + h, x, y, bl);
50932    ctx.arcTo(x, y, x + w, y, tl);
50933    ctx.closePath();
50934  }
50935  if (this._doFill) {
50936    ctx.fill();
50937  }
50938  if (this._doStroke) {
50939    ctx.stroke();
50940  }
50941  if (this._doStroke && ctx.lineWidth % 2 === 1) {
50942    ctx.translate(-0.5, -0.5);
50943  }
50944  return this;
50945};
50946
50947p5.Renderer2D.prototype.triangle = function(args) {
50948  var ctx = this.drawingContext;
50949  var doFill = this._doFill,
50950    doStroke = this._doStroke;
50951  var x1 = args[0],
50952    y1 = args[1];
50953  var x2 = args[2],
50954    y2 = args[3];
50955  var x3 = args[4],
50956    y3 = args[5];
50957  if (doFill && !doStroke) {
50958    if (this._getFill() === styleEmpty) {
50959      return this;
50960    }
50961  } else if (!doFill && doStroke) {
50962    if (this._getStroke() === styleEmpty) {
50963      return this;
50964    }
50965  }
50966  ctx.beginPath();
50967  ctx.moveTo(x1, y1);
50968  ctx.lineTo(x2, y2);
50969  ctx.lineTo(x3, y3);
50970  ctx.closePath();
50971  if (doFill) {
50972    ctx.fill();
50973  }
50974  if (doStroke) {
50975    ctx.stroke();
50976  }
50977};
50978
50979p5.Renderer2D.prototype.endShape = function(
50980  mode,
50981  vertices,
50982  isCurve,
50983  isBezier,
50984  isQuadratic,
50985  isContour,
50986  shapeKind
50987) {
50988  if (vertices.length === 0) {
50989    return this;
50990  }
50991  if (!this._doStroke && !this._doFill) {
50992    return this;
50993  }
50994  var closeShape = mode === constants.CLOSE;
50995  var v;
50996  if (closeShape && !isContour) {
50997    vertices.push(vertices[0]);
50998  }
50999  var i, j;
51000  var numVerts = vertices.length;
51001  if (isCurve && (shapeKind === constants.POLYGON || shapeKind === null)) {
51002    if (numVerts > 3) {
51003      var b = [],
51004        s = 1 - this._curveTightness;
51005      this.drawingContext.beginPath();
51006      this.drawingContext.moveTo(vertices[1][0], vertices[1][1]);
51007      for (i = 1; i + 2 < numVerts; i++) {
51008        v = vertices[i];
51009        b[0] = [v[0], v[1]];
51010        b[1] = [
51011          v[0] + (s * vertices[i + 1][0] - s * vertices[i - 1][0]) / 6,
51012          v[1] + (s * vertices[i + 1][1] - s * vertices[i - 1][1]) / 6
51013        ];
51014        b[2] = [
51015          vertices[i + 1][0] +
51016            (s * vertices[i][0] - s * vertices[i + 2][0]) / 6,
51017          vertices[i + 1][1] + (s * vertices[i][1] - s * vertices[i + 2][1]) / 6
51018        ];
51019        b[3] = [vertices[i + 1][0], vertices[i + 1][1]];
51020        this.drawingContext.bezierCurveTo(
51021          b[1][0],
51022          b[1][1],
51023          b[2][0],
51024          b[2][1],
51025          b[3][0],
51026          b[3][1]
51027        );
51028      }
51029      if (closeShape) {
51030        this.drawingContext.lineTo(vertices[i + 1][0], vertices[i + 1][1]);
51031      }
51032      this._doFillStrokeClose();
51033    }
51034  } else if (
51035    isBezier &&
51036    (shapeKind === constants.POLYGON || shapeKind === null)
51037  ) {
51038    this.drawingContext.beginPath();
51039    for (i = 0; i < numVerts; i++) {
51040      if (vertices[i].isVert) {
51041        if (vertices[i].moveTo) {
51042          this.drawingContext.moveTo(vertices[i][0], vertices[i][1]);
51043        } else {
51044          this.drawingContext.lineTo(vertices[i][0], vertices[i][1]);
51045        }
51046      } else {
51047        this.drawingContext.bezierCurveTo(
51048          vertices[i][0],
51049          vertices[i][1],
51050          vertices[i][2],
51051          vertices[i][3],
51052          vertices[i][4],
51053          vertices[i][5]
51054        );
51055      }
51056    }
51057    this._doFillStrokeClose();
51058  } else if (
51059    isQuadratic &&
51060    (shapeKind === constants.POLYGON || shapeKind === null)
51061  ) {
51062    this.drawingContext.beginPath();
51063    for (i = 0; i < numVerts; i++) {
51064      if (vertices[i].isVert) {
51065        if (vertices[i].moveTo) {
51066          this.drawingContext.moveTo([0], vertices[i][1]);
51067        } else {
51068          this.drawingContext.lineTo(vertices[i][0], vertices[i][1]);
51069        }
51070      } else {
51071        this.drawingContext.quadraticCurveTo(
51072          vertices[i][0],
51073          vertices[i][1],
51074          vertices[i][2],
51075          vertices[i][3]
51076        );
51077      }
51078    }
51079    this._doFillStrokeClose();
51080  } else {
51081    if (shapeKind === constants.POINTS) {
51082      for (i = 0; i < numVerts; i++) {
51083        v = vertices[i];
51084        if (this._doStroke) {
51085          this._pInst.stroke(v[6]);
51086        }
51087        this._pInst.point(v[0], v[1]);
51088      }
51089    } else if (shapeKind === constants.LINES) {
51090      for (i = 0; i + 1 < numVerts; i += 2) {
51091        v = vertices[i];
51092        if (this._doStroke) {
51093          this._pInst.stroke(vertices[i + 1][6]);
51094        }
51095        this._pInst.line(v[0], v[1], vertices[i + 1][0], vertices[i + 1][1]);
51096      }
51097    } else if (shapeKind === constants.TRIANGLES) {
51098      for (i = 0; i + 2 < numVerts; i += 3) {
51099        v = vertices[i];
51100        this.drawingContext.beginPath();
51101        this.drawingContext.moveTo(v[0], v[1]);
51102        this.drawingContext.lineTo(vertices[i + 1][0], vertices[i + 1][1]);
51103        this.drawingContext.lineTo(vertices[i + 2][0], vertices[i + 2][1]);
51104        this.drawingContext.lineTo(v[0], v[1]);
51105        if (this._doFill) {
51106          this._pInst.fill(vertices[i + 2][5]);
51107          this.drawingContext.fill();
51108        }
51109        if (this._doStroke) {
51110          this._pInst.stroke(vertices[i + 2][6]);
51111          this.drawingContext.stroke();
51112        }
51113        this.drawingContext.closePath();
51114      }
51115    } else if (shapeKind === constants.TRIANGLE_STRIP) {
51116      for (i = 0; i + 1 < numVerts; i++) {
51117        v = vertices[i];
51118        this.drawingContext.beginPath();
51119        this.drawingContext.moveTo(vertices[i + 1][0], vertices[i + 1][1]);
51120        this.drawingContext.lineTo(v[0], v[1]);
51121        if (this._doStroke) {
51122          this._pInst.stroke(vertices[i + 1][6]);
51123        }
51124        if (this._doFill) {
51125          this._pInst.fill(vertices[i + 1][5]);
51126        }
51127        if (i + 2 < numVerts) {
51128          this.drawingContext.lineTo(vertices[i + 2][0], vertices[i + 2][1]);
51129          if (this._doStroke) {
51130            this._pInst.stroke(vertices[i + 2][6]);
51131          }
51132          if (this._doFill) {
51133            this._pInst.fill(vertices[i + 2][5]);
51134          }
51135        }
51136        this._doFillStrokeClose();
51137      }
51138    } else if (shapeKind === constants.TRIANGLE_FAN) {
51139      if (numVerts > 2) {
51140        // For performance reasons, try to batch as many of the
51141        // fill and stroke calls as possible.
51142        this.drawingContext.beginPath();
51143        for (i = 2; i < numVerts; i++) {
51144          v = vertices[i];
51145          this.drawingContext.moveTo(vertices[0][0], vertices[0][1]);
51146          this.drawingContext.lineTo(vertices[i - 1][0], vertices[i - 1][1]);
51147          this.drawingContext.lineTo(v[0], v[1]);
51148          this.drawingContext.lineTo(vertices[0][0], vertices[0][1]);
51149          // If the next colour is going to be different, stroke / fill now
51150          if (i < numVerts - 1) {
51151            if (
51152              (this._doFill && v[5] !== vertices[i + 1][5]) ||
51153              (this._doStroke && v[6] !== vertices[i + 1][6])
51154            ) {
51155              if (this._doFill) {
51156                this._pInst.fill(v[5]);
51157                this.drawingContext.fill();
51158                this._pInst.fill(vertices[i + 1][5]);
51159              }
51160              if (this._doStroke) {
51161                this._pInst.stroke(v[6]);
51162                this.drawingContext.stroke();
51163                this._pInst.stroke(vertices[i + 1][6]);
51164              }
51165              this.drawingContext.closePath();
51166              this.drawingContext.beginPath(); // Begin the next one
51167            }
51168          }
51169        }
51170        this._doFillStrokeClose();
51171      }
51172    } else if (shapeKind === constants.QUADS) {
51173      for (i = 0; i + 3 < numVerts; i += 4) {
51174        v = vertices[i];
51175        this.drawingContext.beginPath();
51176        this.drawingContext.moveTo(v[0], v[1]);
51177        for (j = 1; j < 4; j++) {
51178          this.drawingContext.lineTo(vertices[i + j][0], vertices[i + j][1]);
51179        }
51180        this.drawingContext.lineTo(v[0], v[1]);
51181        if (this._doFill) {
51182          this._pInst.fill(vertices[i + 3][5]);
51183        }
51184        if (this._doStroke) {
51185          this._pInst.stroke(vertices[i + 3][6]);
51186        }
51187        this._doFillStrokeClose();
51188      }
51189    } else if (shapeKind === constants.QUAD_STRIP) {
51190      if (numVerts > 3) {
51191        for (i = 0; i + 1 < numVerts; i += 2) {
51192          v = vertices[i];
51193          this.drawingContext.beginPath();
51194          if (i + 3 < numVerts) {
51195            this.drawingContext.moveTo(vertices[i + 2][0], vertices[i + 2][1]);
51196            this.drawingContext.lineTo(v[0], v[1]);
51197            this.drawingContext.lineTo(vertices[i + 1][0], vertices[i + 1][1]);
51198            this.drawingContext.lineTo(vertices[i + 3][0], vertices[i + 3][1]);
51199            if (this._doFill) {
51200              this._pInst.fill(vertices[i + 3][5]);
51201            }
51202            if (this._doStroke) {
51203              this._pInst.stroke(vertices[i + 3][6]);
51204            }
51205          } else {
51206            this.drawingContext.moveTo(v[0], v[1]);
51207            this.drawingContext.lineTo(vertices[i + 1][0], vertices[i + 1][1]);
51208          }
51209          this._doFillStrokeClose();
51210        }
51211      }
51212    } else {
51213      this.drawingContext.beginPath();
51214      this.drawingContext.moveTo(vertices[0][0], vertices[0][1]);
51215      for (i = 1; i < numVerts; i++) {
51216        v = vertices[i];
51217        if (v.isVert) {
51218          if (v.moveTo) {
51219            this.drawingContext.moveTo(v[0], v[1]);
51220          } else {
51221            this.drawingContext.lineTo(v[0], v[1]);
51222          }
51223        }
51224      }
51225      this._doFillStrokeClose();
51226    }
51227  }
51228  isCurve = false;
51229  isBezier = false;
51230  isQuadratic = false;
51231  isContour = false;
51232  if (closeShape) {
51233    vertices.pop();
51234  }
51235  return this;
51236};
51237//////////////////////////////////////////////
51238// SHAPE | Attributes
51239//////////////////////////////////////////////
51240
51241p5.Renderer2D.prototype.noSmooth = function() {
51242  if ('imageSmoothingEnabled' in this.drawingContext) {
51243    this.drawingContext.imageSmoothingEnabled = false;
51244  }
51245  return this;
51246};
51247
51248p5.Renderer2D.prototype.smooth = function() {
51249  if ('imageSmoothingEnabled' in this.drawingContext) {
51250    this.drawingContext.imageSmoothingEnabled = true;
51251  }
51252  return this;
51253};
51254
51255p5.Renderer2D.prototype.strokeCap = function(cap) {
51256  if (
51257    cap === constants.ROUND ||
51258    cap === constants.SQUARE ||
51259    cap === constants.PROJECT
51260  ) {
51261    this.drawingContext.lineCap = cap;
51262  }
51263  return this;
51264};
51265
51266p5.Renderer2D.prototype.strokeJoin = function(join) {
51267  if (
51268    join === constants.ROUND ||
51269    join === constants.BEVEL ||
51270    join === constants.MITER
51271  ) {
51272    this.drawingContext.lineJoin = join;
51273  }
51274  return this;
51275};
51276
51277p5.Renderer2D.prototype.strokeWeight = function(w) {
51278  if (typeof w === 'undefined' || w === 0) {
51279    // hack because lineWidth 0 doesn't work
51280    this.drawingContext.lineWidth = 0.0001;
51281  } else {
51282    this.drawingContext.lineWidth = w;
51283  }
51284  return this;
51285};
51286
51287p5.Renderer2D.prototype._getFill = function() {
51288  if (!this._cachedFillStyle) {
51289    this._cachedFillStyle = this.drawingContext.fillStyle;
51290  }
51291  return this._cachedFillStyle;
51292};
51293
51294p5.Renderer2D.prototype._setFill = function(fillStyle) {
51295  if (fillStyle !== this._cachedFillStyle) {
51296    this.drawingContext.fillStyle = fillStyle;
51297    this._cachedFillStyle = fillStyle;
51298  }
51299};
51300
51301p5.Renderer2D.prototype._getStroke = function() {
51302  if (!this._cachedStrokeStyle) {
51303    this._cachedStrokeStyle = this.drawingContext.strokeStyle;
51304  }
51305  return this._cachedStrokeStyle;
51306};
51307
51308p5.Renderer2D.prototype._setStroke = function(strokeStyle) {
51309  if (strokeStyle !== this._cachedStrokeStyle) {
51310    this.drawingContext.strokeStyle = strokeStyle;
51311    this._cachedStrokeStyle = strokeStyle;
51312  }
51313};
51314
51315//////////////////////////////////////////////
51316// SHAPE | Curves
51317//////////////////////////////////////////////
51318p5.Renderer2D.prototype.bezier = function(x1, y1, x2, y2, x3, y3, x4, y4) {
51319  this._pInst.beginShape();
51320  this._pInst.vertex(x1, y1);
51321  this._pInst.bezierVertex(x2, y2, x3, y3, x4, y4);
51322  this._pInst.endShape();
51323  return this;
51324};
51325
51326p5.Renderer2D.prototype.curve = function(x1, y1, x2, y2, x3, y3, x4, y4) {
51327  this._pInst.beginShape();
51328  this._pInst.curveVertex(x1, y1);
51329  this._pInst.curveVertex(x2, y2);
51330  this._pInst.curveVertex(x3, y3);
51331  this._pInst.curveVertex(x4, y4);
51332  this._pInst.endShape();
51333  return this;
51334};
51335
51336//////////////////////////////////////////////
51337// SHAPE | Vertex
51338//////////////////////////////////////////////
51339
51340p5.Renderer2D.prototype._doFillStrokeClose = function() {
51341  if (this._doFill) {
51342    this.drawingContext.fill();
51343  }
51344  if (this._doStroke) {
51345    this.drawingContext.stroke();
51346  }
51347  this.drawingContext.closePath();
51348};
51349
51350//////////////////////////////////////////////
51351// TRANSFORM
51352//////////////////////////////////////////////
51353
51354p5.Renderer2D.prototype.applyMatrix = function(a, b, c, d, e, f) {
51355  this.drawingContext.transform(a, b, c, d, e, f);
51356};
51357
51358p5.Renderer2D.prototype.resetMatrix = function() {
51359  this.drawingContext.setTransform(1, 0, 0, 1, 0, 0);
51360  this.drawingContext.scale(
51361    this._pInst._pixelDensity,
51362    this._pInst._pixelDensity
51363  );
51364  return this;
51365};
51366
51367p5.Renderer2D.prototype.rotate = function(rad) {
51368  this.drawingContext.rotate(rad);
51369};
51370
51371p5.Renderer2D.prototype.scale = function(x, y) {
51372  this.drawingContext.scale(x, y);
51373  return this;
51374};
51375
51376p5.Renderer2D.prototype.shearX = function(rad) {
51377  this.drawingContext.transform(1, 0, Math.tan(rad), 1, 0, 0);
51378  return this;
51379};
51380
51381p5.Renderer2D.prototype.shearY = function(rad) {
51382  this.drawingContext.transform(1, Math.tan(rad), 0, 1, 0, 0);
51383  return this;
51384};
51385
51386p5.Renderer2D.prototype.translate = function(x, y) {
51387  // support passing a vector as the 1st parameter
51388  if (x instanceof p5.Vector) {
51389    y = x.y;
51390    x = x.x;
51391  }
51392  this.drawingContext.translate(x, y);
51393  return this;
51394};
51395
51396//////////////////////////////////////////////
51397// TYPOGRAPHY
51398//
51399//////////////////////////////////////////////
51400
51401p5.Renderer2D.prototype.text = function(str, x, y, maxWidth, maxHeight) {
51402  var p = this._pInst,
51403    cars,
51404    n,
51405    ii,
51406    jj,
51407    line,
51408    testLine,
51409    testWidth,
51410    words,
51411    totalHeight,
51412    baselineHacked,
51413    finalMaxHeight = Number.MAX_VALUE;
51414
51415  // baselineHacked: (HACK)
51416  // A temporary fix to conform to Processing's implementation
51417  // of BASELINE vertical alignment in a bounding box
51418
51419  if (!(this._doFill || this._doStroke)) {
51420    return;
51421  }
51422
51423  if (typeof str === 'undefined') {
51424    return;
51425  } else if (typeof str !== 'string') {
51426    str = str.toString();
51427  }
51428
51429  str = str.replace(/(\t)/g, '  ');
51430  cars = str.split('\n');
51431
51432  if (typeof maxWidth !== 'undefined') {
51433    totalHeight = 0;
51434    for (ii = 0; ii < cars.length; ii++) {
51435      line = '';
51436      words = cars[ii].split(' ');
51437      for (n = 0; n < words.length; n++) {
51438        testLine = line + words[n] + ' ';
51439        testWidth = this.textWidth(testLine);
51440        if (testWidth > maxWidth) {
51441          line = words[n] + ' ';
51442          totalHeight += p.textLeading();
51443        } else {
51444          line = testLine;
51445        }
51446      }
51447    }
51448
51449    if (this._rectMode === constants.CENTER) {
51450      x -= maxWidth / 2;
51451      y -= maxHeight / 2;
51452    }
51453
51454    switch (this.drawingContext.textAlign) {
51455      case constants.CENTER:
51456        x += maxWidth / 2;
51457        break;
51458      case constants.RIGHT:
51459        x += maxWidth;
51460        break;
51461    }
51462
51463    if (typeof maxHeight !== 'undefined') {
51464      switch (this.drawingContext.textBaseline) {
51465        case constants.BOTTOM:
51466          y += maxHeight - totalHeight;
51467          break;
51468        case constants._CTX_MIDDLE: // CENTER?
51469          y += (maxHeight - totalHeight) / 2;
51470          break;
51471        case constants.BASELINE:
51472          baselineHacked = true;
51473          this.drawingContext.textBaseline = constants.TOP;
51474          break;
51475      }
51476
51477      // remember the max-allowed y-position for any line (fix to #928)
51478      finalMaxHeight = y + maxHeight - p.textAscent();
51479    }
51480
51481    for (ii = 0; ii < cars.length; ii++) {
51482      line = '';
51483      words = cars[ii].split(' ');
51484      for (n = 0; n < words.length; n++) {
51485        testLine = line + words[n] + ' ';
51486        testWidth = this.textWidth(testLine);
51487        if (testWidth > maxWidth && line.length > 0) {
51488          this._renderText(p, line, x, y, finalMaxHeight);
51489          line = words[n] + ' ';
51490          y += p.textLeading();
51491        } else {
51492          line = testLine;
51493        }
51494      }
51495
51496      this._renderText(p, line, x, y, finalMaxHeight);
51497      y += p.textLeading();
51498    }
51499  } else {
51500    // Offset to account for vertically centering multiple lines of text - no
51501    // need to adjust anything for vertical align top or baseline
51502    var offset = 0,
51503      vAlign = p.textAlign().vertical;
51504    if (vAlign === constants.CENTER) {
51505      offset = (cars.length - 1) * p.textLeading() / 2;
51506    } else if (vAlign === constants.BOTTOM) {
51507      offset = (cars.length - 1) * p.textLeading();
51508    }
51509
51510    for (jj = 0; jj < cars.length; jj++) {
51511      this._renderText(p, cars[jj], x, y - offset, finalMaxHeight);
51512      y += p.textLeading();
51513    }
51514  }
51515
51516  if (baselineHacked) {
51517    this.drawingContext.textBaseline = constants.BASELINE;
51518  }
51519
51520  return p;
51521};
51522
51523p5.Renderer2D.prototype._renderText = function(p, line, x, y, maxY) {
51524  if (y >= maxY) {
51525    return; // don't render lines beyond our maxY position
51526  }
51527
51528  p.push(); // fix to #803
51529
51530  if (!this._isOpenType()) {
51531    // a system/browser font
51532
51533    // no stroke unless specified by user
51534    if (this._doStroke && this._strokeSet) {
51535      this.drawingContext.strokeText(line, x, y);
51536    }
51537
51538    if (this._doFill) {
51539      // if fill hasn't been set by user, use default text fill
51540      if (!this._fillSet) {
51541        this._setFill(constants._DEFAULT_TEXT_FILL);
51542      }
51543
51544      this.drawingContext.fillText(line, x, y);
51545    }
51546  } else {
51547    // an opentype font, let it handle the rendering
51548
51549    this._textFont._renderPath(line, x, y, { renderer: this });
51550  }
51551
51552  p.pop();
51553
51554  return p;
51555};
51556
51557p5.Renderer2D.prototype.textWidth = function(s) {
51558  if (this._isOpenType()) {
51559    return this._textFont._textWidth(s, this._textSize);
51560  }
51561
51562  return this.drawingContext.measureText(s).width;
51563};
51564
51565p5.Renderer2D.prototype.textAlign = function(h, v) {
51566  if (typeof h !== 'undefined') {
51567    if (
51568      h === constants.LEFT ||
51569      h === constants.RIGHT ||
51570      h === constants.CENTER
51571    ) {
51572      this.drawingContext.textAlign = h;
51573    }
51574
51575    if (
51576      v === constants.TOP ||
51577      v === constants.BOTTOM ||
51578      v === constants.CENTER ||
51579      v === constants.BASELINE
51580    ) {
51581      if (v === constants.CENTER) {
51582        this.drawingContext.textBaseline = constants._CTX_MIDDLE;
51583      } else {
51584        this.drawingContext.textBaseline = v;
51585      }
51586    }
51587
51588    return this._pInst;
51589  } else {
51590    var valign = this.drawingContext.textBaseline;
51591
51592    if (valign === constants._CTX_MIDDLE) {
51593      valign = constants.CENTER;
51594    }
51595
51596    return {
51597      horizontal: this.drawingContext.textAlign,
51598      vertical: valign
51599    };
51600  }
51601};
51602
51603p5.Renderer2D.prototype._applyTextProperties = function() {
51604  var font,
51605    p = this._pInst;
51606
51607  this._setProperty('_textAscent', null);
51608  this._setProperty('_textDescent', null);
51609
51610  font = this._textFont;
51611
51612  if (this._isOpenType()) {
51613    font = this._textFont.font.familyName;
51614    this._setProperty('_textStyle', this._textFont.font.styleName);
51615  }
51616
51617  this.drawingContext.font =
51618    (this._textStyle || 'normal') +
51619    ' ' +
51620    (this._textSize || 12) +
51621    'px ' +
51622    (font || 'sans-serif');
51623
51624  return p;
51625};
51626
51627//////////////////////////////////////////////
51628// STRUCTURE
51629//////////////////////////////////////////////
51630
51631// a push() operation is in progress.
51632// the renderer should return a 'style' object that it wishes to
51633// store on the push stack.
51634// derived renderers should call the base class' push() method
51635// to fetch the base style object.
51636p5.Renderer2D.prototype.push = function() {
51637  this.drawingContext.save();
51638
51639  // get the base renderer style
51640  return p5.Renderer.prototype.push.apply(this);
51641};
51642
51643// a pop() operation is in progress
51644// the renderer is passed the 'style' object that it returned
51645// from its push() method.
51646// derived renderers should pass this object to their base
51647// class' pop method
51648p5.Renderer2D.prototype.pop = function(style) {
51649  this.drawingContext.restore();
51650  // Re-cache the fill / stroke state
51651  this._cachedFillStyle = this.drawingContext.fillStyle;
51652  this._cachedStrokeStyle = this.drawingContext.strokeStyle;
51653
51654  p5.Renderer.prototype.pop.call(this, style);
51655};
51656
51657module.exports = p5.Renderer2D;
51658
51659},{"../image/filters":41,"./canvas":20,"./constants":21,"./core":22,"./p5.Renderer":29}],31:[function(_dereq_,module,exports){
51660/**
51661 * @module Rendering
51662 * @submodule Rendering
51663 * @for p5
51664 */
51665
51666'use strict';
51667
51668var p5 = _dereq_('./core');
51669var constants = _dereq_('./constants');
51670_dereq_('./p5.Graphics');
51671_dereq_('./p5.Renderer2D');
51672_dereq_('../webgl/p5.RendererGL');
51673var defaultId = 'defaultCanvas0'; // this gets set again in createCanvas
51674var defaultClass = 'p5Canvas';
51675
51676/**
51677 * Creates a canvas element in the document, and sets the dimensions of it
51678 * in pixels. This method should be called only once at the start of setup.
51679 * Calling createCanvas more than once in a sketch will result in very
51680 * unpredictable behavior. If you want more than one drawing canvas
51681 * you could use createGraphics (hidden by default but it can be shown).
51682 * <br><br>
51683 * The system variables width and height are set by the parameters passed
51684 * to this function. If createCanvas() is not used, the window will be
51685 * given a default size of 100x100 pixels.
51686 * <br><br>
51687 * For more ways to position the canvas, see the
51688 * <a href='https://github.com/processing/p5.js/wiki/Positioning-your-canvas'>
51689 * positioning the canvas</a> wiki page.
51690 *
51691 * @method createCanvas
51692 * @param  {Number} w width of the canvas
51693 * @param  {Number} h height of the canvas
51694 * @param  {Constant} [renderer] either P2D or WEBGL
51695 * @return {p5.Renderer}
51696 * @example
51697 * <div>
51698 * <code>
51699 * function setup() {
51700 *   createCanvas(100, 50);
51701 *   background(153);
51702 *   line(0, 0, width, height);
51703 * }
51704 * </code>
51705 * </div>
51706 *
51707 * @alt
51708 * Black line extending from top-left of canvas to bottom right.
51709 *
51710 */
51711
51712p5.prototype.createCanvas = function(w, h, renderer) {
51713  p5._validateParameters('createCanvas', arguments);
51714  //optional: renderer, otherwise defaults to p2d
51715  var r = renderer || constants.P2D;
51716  var c;
51717
51718  if (r === constants.WEBGL) {
51719    c = document.getElementById(defaultId);
51720    if (c) {
51721      //if defaultCanvas already exists
51722      c.parentNode.removeChild(c); //replace the existing defaultCanvas
51723      var thisRenderer = this._renderer;
51724      this._elements = this._elements.filter(function(e) {
51725        return e !== thisRenderer;
51726      });
51727    }
51728    c = document.createElement('canvas');
51729    c.id = defaultId;
51730    c.classList.add(defaultClass);
51731  } else {
51732    if (!this._defaultGraphicsCreated) {
51733      c = document.createElement('canvas');
51734      var i = 0;
51735      while (document.getElementById('defaultCanvas' + i)) {
51736        i++;
51737      }
51738      defaultId = 'defaultCanvas' + i;
51739      c.id = defaultId;
51740      c.classList.add(defaultClass);
51741    } else {
51742      // resize the default canvas if new one is created
51743      c = this.canvas;
51744    }
51745  }
51746
51747  // set to invisible if still in setup (to prevent flashing with manipulate)
51748  if (!this._setupDone) {
51749    c.dataset.hidden = true; // tag to show later
51750    c.style.visibility = 'hidden';
51751  }
51752
51753  if (this._userNode) {
51754    // user input node case
51755    this._userNode.appendChild(c);
51756  } else {
51757    document.body.appendChild(c);
51758  }
51759
51760  // Init our graphics renderer
51761  //webgl mode
51762  if (r === constants.WEBGL) {
51763    this._setProperty('_renderer', new p5.RendererGL(c, this, true));
51764    this._elements.push(this._renderer);
51765  } else {
51766    //P2D mode
51767    if (!this._defaultGraphicsCreated) {
51768      this._setProperty('_renderer', new p5.Renderer2D(c, this, true));
51769      this._defaultGraphicsCreated = true;
51770      this._elements.push(this._renderer);
51771    }
51772  }
51773  this._renderer.resize(w, h);
51774  this._renderer._applyDefaults();
51775  return this._renderer;
51776};
51777
51778/**
51779 * Resizes the canvas to given width and height. The canvas will be cleared
51780 * and draw will be called immediately, allowing the sketch to re-render itself
51781 * in the resized canvas.
51782 * @method resizeCanvas
51783 * @param  {Number} w width of the canvas
51784 * @param  {Number} h height of the canvas
51785 * @param  {Boolean} [noRedraw] don't redraw the canvas immediately
51786 * @example
51787 * <div class="norender"><code>
51788 * function setup() {
51789 *   createCanvas(windowWidth, windowHeight);
51790 * }
51791 *
51792 * function draw() {
51793 *   background(0, 100, 200);
51794 * }
51795 *
51796 * function windowResized() {
51797 *   resizeCanvas(windowWidth, windowHeight);
51798 * }
51799 * </code></div>
51800 *
51801 * @alt
51802 * No image displayed.
51803 *
51804 */
51805p5.prototype.resizeCanvas = function(w, h, noRedraw) {
51806  p5._validateParameters('resizeCanvas', arguments);
51807  if (this._renderer) {
51808    // save canvas properties
51809    var props = {};
51810    for (var key in this.drawingContext) {
51811      var val = this.drawingContext[key];
51812      if (typeof val !== 'object' && typeof val !== 'function') {
51813        props[key] = val;
51814      }
51815    }
51816    this._renderer.resize(w, h);
51817    // reset canvas properties
51818    for (var savedKey in props) {
51819      try {
51820        this.drawingContext[savedKey] = props[savedKey];
51821      } catch (err) {
51822        // ignore read-only property errors
51823      }
51824    }
51825    if (!noRedraw) {
51826      this.redraw();
51827    }
51828  }
51829};
51830
51831/**
51832 * Removes the default canvas for a p5 sketch that doesn't
51833 * require a canvas
51834 * @method noCanvas
51835 * @example
51836 * <div>
51837 * <code>
51838 * function setup() {
51839 *   noCanvas();
51840 * }
51841 * </code>
51842 * </div>
51843 *
51844 * @alt
51845 * no image displayed
51846 *
51847 */
51848p5.prototype.noCanvas = function() {
51849  if (this.canvas) {
51850    this.canvas.parentNode.removeChild(this.canvas);
51851  }
51852};
51853
51854/**
51855 * Creates and returns a new p5.Renderer object. Use this class if you need
51856 * to draw into an off-screen graphics buffer. The two parameters define the
51857 * width and height in pixels.
51858 *
51859 * @method createGraphics
51860 * @param  {Number} w width of the offscreen graphics buffer
51861 * @param  {Number} h height of the offscreen graphics buffer
51862 * @param  {Constant} [renderer] either P2D or WEBGL
51863 * undefined defaults to p2d
51864 * @return {p5.Graphics} offscreen graphics buffer
51865 * @example
51866 * <div>
51867 * <code>
51868 * var pg;
51869 * function setup() {
51870 *   createCanvas(100, 100);
51871 *   pg = createGraphics(100, 100);
51872 * }
51873 * function draw() {
51874 *   background(200);
51875 *   pg.background(100);
51876 *   pg.noStroke();
51877 *   pg.ellipse(pg.width / 2, pg.height / 2, 50, 50);
51878 *   image(pg, 50, 50);
51879 *   image(pg, 0, 0, 50, 50);
51880 * }
51881 * </code>
51882 * </div>
51883 *
51884 * @alt
51885 * 4 grey squares alternating light and dark grey. White quarter circle mid-left.
51886 *
51887 */
51888p5.prototype.createGraphics = function(w, h, renderer) {
51889  p5._validateParameters('createGraphics', arguments);
51890  return new p5.Graphics(w, h, renderer, this);
51891};
51892
51893/**
51894 * Blends the pixels in the display window according to the defined mode.
51895 * There is a choice of the following modes to blend the source pixels (A)
51896 * with the ones of pixels already in the display window (B):
51897 * <ul>
51898 * <li><code>BLEND</code> - linear interpolation of colours: C =
51899 * A\*factor + B. This is the default blending mode.</li>
51900 * <li><code>ADD</code> - sum of A and B</li>
51901 * <li><code>DARKEST</code> - only the darkest colour succeeds: C =
51902 * min(A\*factor, B).</li>
51903 * <li><code>LIGHTEST</code> - only the lightest colour succeeds: C =
51904 * max(A\*factor, B).</li>
51905 * <li><code>DIFFERENCE</code> - subtract colors from underlying image.</li>
51906 * <li><code>EXCLUSION</code> - similar to <code>DIFFERENCE</code>, but less
51907 * extreme.</li>
51908 * <li><code>MULTIPLY</code> - multiply the colors, result will always be
51909 * darker.</li>
51910 * <li><code>SCREEN</code> - opposite multiply, uses inverse values of the
51911 * colors.</li>
51912 * <li><code>REPLACE</code> - the pixels entirely replace the others and
51913 * don't utilize alpha (transparency) values.</li>
51914 * <li><code>OVERLAY</code> - mix of <code>MULTIPLY</code> and <code>SCREEN
51915 * </code>. Multiplies dark values, and screens light values.</li>
51916 * <li><code>HARD_LIGHT</code> - <code>SCREEN</code> when greater than 50%
51917 * gray, <code>MULTIPLY</code> when lower.</li>
51918 * <li><code>SOFT_LIGHT</code> - mix of <code>DARKEST</code> and
51919 * <code>LIGHTEST</code>. Works like <code>OVERLAY</code>, but not as harsh.
51920 * </li>
51921 * <li><code>DODGE</code> - lightens light tones and increases contrast,
51922 * ignores darks.</li>
51923 * <li><code>BURN</code> - darker areas are applied, increasing contrast,
51924 * ignores lights.</li>
51925 * </ul>
51926 *
51927 * @method blendMode
51928 * @param  {Constant} mode blend mode to set for canvas.
51929 *                either BLEND, DARKEST, LIGHTEST, DIFFERENCE, MULTIPLY,
51930 *                EXCLUSION, SCREEN, REPLACE, OVERLAY, HARD_LIGHT,
51931 *                SOFT_LIGHT, DODGE, BURN, ADD or NORMAL
51932 * @example
51933 * <div>
51934 * <code>
51935 * blendMode(LIGHTEST);
51936 * strokeWeight(30);
51937 * stroke(80, 150, 255);
51938 * line(25, 25, 75, 75);
51939 * stroke(255, 50, 50);
51940 * line(75, 25, 25, 75);
51941 * </code>
51942 * </div>
51943 * <div>
51944 * <code>
51945 * blendMode(MULTIPLY);
51946 * strokeWeight(30);
51947 * stroke(80, 150, 255);
51948 * line(25, 25, 75, 75);
51949 * stroke(255, 50, 50);
51950 * line(75, 25, 25, 75);
51951 * </code>
51952 * </div>
51953 * @alt
51954 * translucent image thick red & blue diagonal rounded lines intersecting center
51955 * Thick red & blue diagonal rounded lines intersecting center. dark at overlap
51956 *
51957 */
51958p5.prototype.blendMode = function(mode) {
51959  p5._validateParameters('blendMode', arguments);
51960  if (
51961    mode === constants.BLEND ||
51962    mode === constants.DARKEST ||
51963    mode === constants.LIGHTEST ||
51964    mode === constants.DIFFERENCE ||
51965    mode === constants.MULTIPLY ||
51966    mode === constants.EXCLUSION ||
51967    mode === constants.SCREEN ||
51968    mode === constants.REPLACE ||
51969    mode === constants.OVERLAY ||
51970    mode === constants.HARD_LIGHT ||
51971    mode === constants.SOFT_LIGHT ||
51972    mode === constants.DODGE ||
51973    mode === constants.BURN ||
51974    mode === constants.ADD ||
51975    mode === constants.NORMAL
51976  ) {
51977    this._renderer.blendMode(mode);
51978  } else {
51979    throw new Error('Mode ' + mode + ' not recognized.');
51980  }
51981};
51982
51983module.exports = p5;
51984
51985},{"../webgl/p5.RendererGL":72,"./constants":21,"./core":22,"./p5.Graphics":28,"./p5.Renderer2D":30}],32:[function(_dereq_,module,exports){
51986'use strict';
51987
51988// requestAnim shim layer by Paul Irish
51989window.requestAnimationFrame = (function() {
51990  return (
51991    window.requestAnimationFrame ||
51992    window.webkitRequestAnimationFrame ||
51993    window.mozRequestAnimationFrame ||
51994    window.oRequestAnimationFrame ||
51995    window.msRequestAnimationFrame ||
51996    function(callback, element) {
51997      // should '60' here be framerate?
51998      window.setTimeout(callback, 1000 / 60);
51999    }
52000  );
52001})();
52002
52003// use window.performance() to get max fast and accurate time in milliseconds
52004window.performance = window.performance || {};
52005window.performance.now = (function() {
52006  var load_date = Date.now();
52007  return (
52008    window.performance.now ||
52009    window.performance.mozNow ||
52010    window.performance.msNow ||
52011    window.performance.oNow ||
52012    window.performance.webkitNow ||
52013    function() {
52014      return Date.now() - load_date;
52015    }
52016  );
52017})();
52018
52019/*
52020// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
52021// http://my.opera.com/emoller/blog/2011/12/20/
52022// requestanimationframe-for-smart-er-animating
52023// requestAnimationFrame polyfill by Erik Möller
52024// fixes from Paul Irish and Tino Zijdel
52025(function() {
52026  var lastTime = 0;
52027  var vendors = ['ms', 'moz', 'webkit', 'o'];
52028  for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
52029    window.requestAnimationFrame =
52030      window[vendors[x]+'RequestAnimationFrame'];
52031    window.cancelAnimationFrame =
52032      window[vendors[x]+'CancelAnimationFrame'] ||
52033      window[vendors[x]+'CancelRequestAnimationFrame'];
52034  }
52035
52036  if (!window.requestAnimationFrame) {
52037    window.requestAnimationFrame = function(callback, element) {
52038      var currTime = new Date().getTime();
52039      var timeToCall = Math.max(0, 16 - (currTime - lastTime));
52040      var id = window.setTimeout(function()
52041        { callback(currTime + timeToCall); }, timeToCall);
52042      lastTime = currTime + timeToCall;
52043      return id;
52044    };
52045  }
52046
52047  if (!window.cancelAnimationFrame) {
52048    window.cancelAnimationFrame = function(id) {
52049      clearTimeout(id);
52050    };
52051  }
52052}());
52053*/
52054
52055/**
52056 * shim for Uint8ClampedArray.slice
52057 * (allows arrayCopy to work with pixels[])
52058 * with thanks to http://halfpapstudios.com/blog/tag/html5-canvas/
52059 * Enumerable set to false to protect for...in from
52060 * Uint8ClampedArray.prototype pollution.
52061 */
52062(function() {
52063  'use strict';
52064  if (
52065    typeof Uint8ClampedArray !== 'undefined' &&
52066    !Uint8ClampedArray.prototype.slice
52067  ) {
52068    Object.defineProperty(Uint8ClampedArray.prototype, 'slice', {
52069      value: Array.prototype.slice,
52070      writable: true,
52071      configurable: true,
52072      enumerable: false
52073    });
52074  }
52075})();
52076
52077},{}],33:[function(_dereq_,module,exports){
52078/**
52079 * @module Structure
52080 * @submodule Structure
52081 * @for p5
52082 * @requires core
52083 */
52084
52085'use strict';
52086
52087var p5 = _dereq_('./core');
52088
52089p5.prototype.exit = function() {
52090  throw 'exit() not implemented, see remove()';
52091};
52092/**
52093 * Stops p5.js from continuously executing the code within draw().
52094 * If loop() is called, the code in draw() begins to run continuously again.
52095 * If using noLoop() in setup(), it should be the last line inside the block.
52096 * <br><br>
52097 * When noLoop() is used, it's not possible to manipulate or access the
52098 * screen inside event handling functions such as mousePressed() or
52099 * keyPressed(). Instead, use those functions to call redraw() or loop(),
52100 * which will run draw(), which can update the screen properly. This means
52101 * that when noLoop() has been called, no drawing can happen, and functions
52102 * like saveFrame() or loadPixels() may not be used.
52103 * <br><br>
52104 * Note that if the sketch is resized, redraw() will be called to update
52105 * the sketch, even after noLoop() has been specified. Otherwise, the sketch
52106 * would enter an odd state until loop() was called.
52107 *
52108 * @method noLoop
52109 * @example
52110 * <div><code>
52111 * function setup() {
52112 *   createCanvas(100, 100);
52113 *   background(200);
52114 *   noLoop();
52115 * }
52116
52117 * function draw() {
52118 *   line(10, 10, 90, 90);
52119 * }
52120 * </code></div>
52121 *
52122 * <div><code>
52123 * var x = 0;
52124 * function setup() {
52125 *   createCanvas(100, 100);
52126 * }
52127 *
52128 * function draw() {
52129 *   background(204);
52130 *   x = x + 0.1;
52131 *   if (x > width) {
52132 *     x = 0;
52133 *   }
52134 *   line(x, 0, x, height);
52135 * }
52136 *
52137 * function mousePressed() {
52138 *   noLoop();
52139 * }
52140 *
52141 * function mouseReleased() {
52142 *   loop();
52143 * }
52144 * </code></div>
52145 *
52146 * @alt
52147 * 113 pixel long line extending from top-left to bottom right of canvas.
52148 * horizontal line moves slowly from left. Loops but stops on mouse press.
52149 *
52150 */
52151p5.prototype.noLoop = function() {
52152  this._loop = false;
52153};
52154/**
52155 * By default, p5.js loops through draw() continuously, executing the code
52156 * within it. However, the draw() loop may be stopped by calling noLoop().
52157 * In that case, the draw() loop can be resumed with loop().
52158 *
52159 * @method loop
52160 * @example
52161 * <div><code>
52162 * var x = 0;
52163 * function setup() {
52164 *   createCanvas(100, 100);
52165 *   noLoop();
52166 * }
52167 *
52168 * function draw() {
52169 *   background(204);
52170 *   x = x + 0.1;
52171 *   if (x > width) {
52172 *     x = 0;
52173 *   }
52174 *   line(x, 0, x, height);
52175 * }
52176 *
52177 * function mousePressed() {
52178 *   loop();
52179 * }
52180 *
52181 * function mouseReleased() {
52182 *   noLoop();
52183 * }
52184 * </code></div>
52185 *
52186 * @alt
52187 * horizontal line moves slowly from left. Loops but stops on mouse press.
52188 *
52189 */
52190
52191p5.prototype.loop = function() {
52192  this._loop = true;
52193  this._draw();
52194};
52195
52196function assign(dest, varArgs) {
52197  for (var index = 1; index < arguments.length; index++) {
52198    var src = arguments[index];
52199    if (src != null) {
52200      for (var key in src) {
52201        if (src.hasOwnProperty(key)) {
52202          dest[key] = src[key];
52203        }
52204      }
52205    }
52206  }
52207}
52208
52209/**
52210 * The push() function saves the current drawing style settings and
52211 * transformations, while pop() restores these settings. Note that these
52212 * functions are always used together. They allow you to change the style
52213 * and transformation settings and later return to what you had. When a new
52214 * state is started with push(), it builds on the current style and transform
52215 * information. The push() and pop() functions can be embedded to provide
52216 * more control. (See the second example for a demonstration.)
52217 * <br><br>
52218 * push() stores information related to the current transformation state
52219 * and style settings controlled by the following functions: fill(),
52220 * stroke(), tint(), strokeWeight(), strokeCap(), strokeJoin(),
52221 * imageMode(), rectMode(), ellipseMode(), colorMode(), textAlign(),
52222 * textFont(), textMode(), textSize(), textLeading().
52223 *
52224 * @method push
52225 * @example
52226 * <div>
52227 * <code>
52228 * ellipse(0, 50, 33, 33); // Left circle
52229 *
52230 * push(); // Start a new drawing state
52231 * strokeWeight(10);
52232 * fill(204, 153, 0);
52233 * translate(50, 0);
52234 * ellipse(0, 50, 33, 33); // Middle circle
52235 * pop(); // Restore original state
52236 *
52237 * ellipse(100, 50, 33, 33); // Right circle
52238 * </code>
52239 * </div>
52240 * <div>
52241 * <code>
52242 * ellipse(0, 50, 33, 33); // Left circle
52243 *
52244 * push(); // Start a new drawing state
52245 * strokeWeight(10);
52246 * fill(204, 153, 0);
52247 * ellipse(33, 50, 33, 33); // Left-middle circle
52248 *
52249 * push(); // Start another new drawing state
52250 * stroke(0, 102, 153);
52251 * ellipse(66, 50, 33, 33); // Right-middle circle
52252 * pop(); // Restore previous state
52253 *
52254 * pop(); // Restore original state
52255 *
52256 * ellipse(100, 50, 33, 33); // Right circle
52257 * </code>
52258 * </div>
52259 *
52260 * @alt
52261 * Gold ellipse + thick black outline @center 2 white ellipses on left and right.
52262 * 2 Gold ellipses left black right blue stroke. 2 white ellipses on left+right.
52263 *
52264 */
52265p5.prototype.push = function() {
52266  this._styles.push({
52267    props: {
52268      _colorMode: this._colorMode
52269    },
52270    renderer: this._renderer.push()
52271  });
52272};
52273
52274/**
52275 * The push() function saves the current drawing style settings and
52276 * transformations, while pop() restores these settings. Note that these
52277 * functions are always used together. They allow you to change the style
52278 * and transformation settings and later return to what you had. When a new
52279 * state is started with push(), it builds on the current style and transform
52280 * information. The push() and pop() functions can be embedded to provide
52281 * more control. (See the second example for a demonstration.)
52282 * <br><br>
52283 * push() stores information related to the current transformation state
52284 * and style settings controlled by the following functions: fill(),
52285 * stroke(), tint(), strokeWeight(), strokeCap(), strokeJoin(),
52286 * imageMode(), rectMode(), ellipseMode(), colorMode(), textAlign(),
52287 * textFont(), textMode(), textSize(), textLeading().
52288 *
52289 * @method pop
52290 * @example
52291 * <div>
52292 * <code>
52293 * ellipse(0, 50, 33, 33); // Left circle
52294 *
52295 * push(); // Start a new drawing state
52296 * translate(50, 0);
52297 * strokeWeight(10);
52298 * fill(204, 153, 0);
52299 * ellipse(0, 50, 33, 33); // Middle circle
52300 * pop(); // Restore original state
52301 *
52302 * ellipse(100, 50, 33, 33); // Right circle
52303 * </code>
52304 * </div>
52305 * <div>
52306 * <code>
52307 * ellipse(0, 50, 33, 33); // Left circle
52308 *
52309 * push(); // Start a new drawing state
52310 * strokeWeight(10);
52311 * fill(204, 153, 0);
52312 * ellipse(33, 50, 33, 33); // Left-middle circle
52313 *
52314 * push(); // Start another new drawing state
52315 * stroke(0, 102, 153);
52316 * ellipse(66, 50, 33, 33); // Right-middle circle
52317 * pop(); // Restore previous state
52318 *
52319 * pop(); // Restore original state
52320 *
52321 * ellipse(100, 50, 33, 33); // Right circle
52322 * </code>
52323 * </div>
52324 *
52325 * @alt
52326 * Gold ellipse + thick black outline @center 2 white ellipses on left and right.
52327 * 2 Gold ellipses left black right blue stroke. 2 white ellipses on left+right.
52328 *
52329 */
52330p5.prototype.pop = function() {
52331  var style = this._styles.pop();
52332  if (style) {
52333    this._renderer.pop(style.renderer);
52334    assign(this, style.props);
52335  } else {
52336    console.warn('pop() was called without matching push()');
52337  }
52338};
52339
52340p5.prototype.pushStyle = function() {
52341  throw new Error('pushStyle() not used, see push()');
52342};
52343
52344p5.prototype.popStyle = function() {
52345  throw new Error('popStyle() not used, see pop()');
52346};
52347
52348/**
52349 *
52350 * Executes the code within draw() one time. This functions allows the
52351 * program to update the display window only when necessary, for example
52352 * when an event registered by mousePressed() or keyPressed() occurs.
52353 * <br><br>
52354 * In structuring a program, it only makes sense to call redraw() within
52355 * events such as mousePressed(). This is because redraw() does not run
52356 * draw() immediately (it only sets a flag that indicates an update is
52357 * needed).
52358 * <br><br>
52359 * The redraw() function does not work properly when called inside draw().
52360 * To enable/disable animations, use loop() and noLoop().
52361 * <br><br>
52362 * In addition you can set the number of redraws per method call. Just
52363 * add an integer as single parameter for the number of redraws.
52364 *
52365 * @method redraw
52366 * @param  {Integer} [n] Redraw for n-times. The default value is 1.
52367 * @example
52368 * <div><code>
52369 * var x = 0;
52370 *
52371 * function setup() {
52372 *   createCanvas(100, 100);
52373 *   noLoop();
52374 * }
52375 *
52376 * function draw() {
52377 *   background(204);
52378 *   line(x, 0, x, height);
52379 * }
52380 *
52381 * function mousePressed() {
52382 *   x += 1;
52383 *   redraw();
52384 * }
52385 * </code></div>
52386 *
52387 * <div class='norender'><code>
52388 * var x = 0;
52389 *
52390 * function setup() {
52391 *   createCanvas(100, 100);
52392 *   noLoop();
52393 * }
52394 *
52395 * function draw() {
52396 *   background(204);
52397 *   x += 1;
52398 *   line(x, 0, x, height);
52399 * }
52400 *
52401 * function mousePressed() {
52402 *   redraw(5);
52403 * }
52404 * </code></div>
52405 *
52406 * @alt
52407 * black line on far left of canvas
52408 * black line on far left of canvas
52409 *
52410 */
52411p5.prototype.redraw = function(n) {
52412  this.resetMatrix();
52413  if (this._renderer.isP3D) {
52414    this._renderer._update();
52415  }
52416
52417  var numberOfRedraws = parseInt(n);
52418  if (isNaN(numberOfRedraws) || numberOfRedraws < 1) {
52419    numberOfRedraws = 1;
52420  }
52421
52422  var userSetup = this.setup || window.setup;
52423  var userDraw = this.draw || window.draw;
52424  if (typeof userDraw === 'function') {
52425    if (typeof userSetup === 'undefined') {
52426      this.scale(this._pixelDensity, this._pixelDensity);
52427    }
52428    var self = this;
52429    var callMethod = function(f) {
52430      f.call(self);
52431    };
52432    for (var idxRedraw = 0; idxRedraw < numberOfRedraws; idxRedraw++) {
52433      this._setProperty('frameCount', this.frameCount + 1);
52434      this._registeredMethods.pre.forEach(callMethod);
52435      userDraw();
52436      this._registeredMethods.post.forEach(callMethod);
52437    }
52438  }
52439};
52440
52441p5.prototype.size = function() {
52442  var s = 'size() is not a valid p5 function, to set the size of the ';
52443  s += 'drawing canvas, please use createCanvas() instead';
52444  throw s;
52445};
52446
52447module.exports = p5;
52448
52449},{"./core":22}],34:[function(_dereq_,module,exports){
52450/**
52451 * @module Transform
52452 * @submodule Transform
52453 * @for p5
52454 * @requires core
52455 * @requires constants
52456 */
52457
52458'use strict';
52459
52460var p5 = _dereq_('./core');
52461
52462/**
52463 * Multiplies the current matrix by the one specified through the parameters.
52464 * This is a powerful operation that can perform the equivalent of translate,
52465 * scale, shear and rotate all at once. You can learn more about transformation
52466 * matrices on <a href="https://en.wikipedia.org/wiki/Transformation_matrix">
52467 * Wikipedia</a>.
52468 *
52469 * The naming of the arguments here follows the naming of the <a href=
52470 * "https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-transform">
52471 * WHATWG specification</a> and corresponds to a
52472 * transformation matrix of the
52473 * form:
52474 *
52475 * > <img style="max-width: 150px" src="assets/transformation-matrix.png"
52476 * alt="The transformation matrix used when applyMatrix is called"/>
52477 *
52478 * @method applyMatrix
52479 * @param  {Number} a numbers which define the 2x3 matrix to be multiplied
52480 * @param  {Number} b numbers which define the 2x3 matrix to be multiplied
52481 * @param  {Number} c numbers which define the 2x3 matrix to be multiplied
52482 * @param  {Number} d numbers which define the 2x3 matrix to be multiplied
52483 * @param  {Number} e numbers which define the 2x3 matrix to be multiplied
52484 * @param  {Number} f numbers which define the 2x3 matrix to be multiplied
52485 * @chainable
52486 * @example
52487 * <div>
52488 * <code>
52489 * function setup() {
52490 *   frameRate(10);
52491 *   rectMode(CENTER);
52492 * }
52493 *
52494 * function draw() {
52495 *   var step = frameCount % 20;
52496 *   background(200);
52497 *   // Equivalent to translate(x, y);
52498 *   applyMatrix(1, 0, 0, 1, 40 + step, 50);
52499 *   rect(0, 0, 50, 50);
52500 * }
52501 * </code>
52502 * </div>
52503 * <div>
52504 * <code>
52505 * function setup() {
52506 *   frameRate(10);
52507 *   rectMode(CENTER);
52508 * }
52509 *
52510 * function draw() {
52511 *   var step = frameCount % 20;
52512 *   background(200);
52513 *   translate(50, 50);
52514 *   // Equivalent to scale(x, y);
52515 *   applyMatrix(1 / step, 0, 0, 1 / step, 0, 0);
52516 *   rect(0, 0, 50, 50);
52517 * }
52518 * </code>
52519 * </div>
52520 * <div>
52521 * <code>
52522 * function setup() {
52523 *   frameRate(10);
52524 *   rectMode(CENTER);
52525 * }
52526 *
52527 * function draw() {
52528 *   var step = frameCount % 20;
52529 *   var angle = map(step, 0, 20, 0, TWO_PI);
52530 *   var cos_a = cos(angle);
52531 *   var sin_a = sin(angle);
52532 *   background(200);
52533 *   translate(50, 50);
52534 *   // Equivalent to rotate(angle);
52535 *   applyMatrix(cos_a, sin_a, -sin_a, cos_a, 0, 0);
52536 *   rect(0, 0, 50, 50);
52537 * }
52538 * </code>
52539 * </div>
52540 * <div>
52541 * <code>
52542 * function setup() {
52543 *   frameRate(10);
52544 *   rectMode(CENTER);
52545 * }
52546 *
52547 * function draw() {
52548 *   var step = frameCount % 20;
52549 *   var angle = map(step, 0, 20, -PI / 4, PI / 4);
52550 *   background(200);
52551 *   translate(50, 50);
52552 *   // equivalent to shearX(angle);
52553 *   var shear_factor = 1 / tan(PI / 2 - angle);
52554 *   applyMatrix(1, 0, shear_factor, 1, 0, 0);
52555 *   rect(0, 0, 50, 50);
52556 * }
52557 * </code>
52558 * </div>
52559 *
52560 * @alt
52561 * A rectangle translating to the right
52562 * A rectangle shrinking to the center
52563 * A rectangle rotating clockwise about the center
52564 * A rectangle shearing
52565 *
52566 */
52567p5.prototype.applyMatrix = function(a, b, c, d, e, f) {
52568  this._renderer.applyMatrix(a, b, c, d, e, f);
52569  return this;
52570};
52571
52572p5.prototype.popMatrix = function() {
52573  throw new Error('popMatrix() not used, see pop()');
52574};
52575
52576p5.prototype.printMatrix = function() {
52577  throw new Error('printMatrix() not implemented');
52578};
52579
52580p5.prototype.pushMatrix = function() {
52581  throw new Error('pushMatrix() not used, see push()');
52582};
52583
52584/**
52585 * Replaces the current matrix with the identity matrix.
52586 *
52587 * @method resetMatrix
52588 * @chainable
52589 * @example
52590 * <div>
52591 * <code>
52592 * translate(50, 50);
52593 * applyMatrix(0.5, 0.5, -0.5, 0.5, 0, 0);
52594 * rect(0, 0, 20, 20);
52595 * // Note that the translate is also reset.
52596 * resetMatrix();
52597 * rect(0, 0, 20, 20);
52598 * </code>
52599 * </div>
52600 *
52601 * @alt
52602 * A rotated retangle in the center with another at the top left corner
52603 *
52604 */
52605p5.prototype.resetMatrix = function() {
52606  this._renderer.resetMatrix();
52607  return this;
52608};
52609
52610/**
52611 * Rotates a shape the amount specified by the angle parameter. This
52612 * function accounts for angleMode, so angles can be entered in either
52613 * RADIANS or DEGREES.
52614 * <br><br>
52615 * Objects are always rotated around their relative position to the
52616 * origin and positive numbers rotate objects in a clockwise direction.
52617 * Transformations apply to everything that happens after and subsequent
52618 * calls to the function accumulates the effect. For example, calling
52619 * rotate(HALF_PI) and then rotate(HALF_PI) is the same as rotate(PI).
52620 * All tranformations are reset when draw() begins again.
52621 * <br><br>
52622 * Technically, rotate() multiplies the current transformation matrix
52623 * by a rotation matrix. This function can be further controlled by
52624 * the push() and pop().
52625 *
52626 * @method rotate
52627 * @param  {Number} angle the angle of rotation, specified in radians
52628 *                        or degrees, depending on current angleMode
52629 * @param  {p5.Vector|Number[]} [axis] (in 3d) the axis to rotate around
52630 * @chainable
52631 * @example
52632 * <div>
52633 * <code>
52634 * translate(width / 2, height / 2);
52635 * rotate(PI / 3.0);
52636 * rect(-26, -26, 52, 52);
52637 * </code>
52638 * </div>
52639 *
52640 * @alt
52641 * white 52x52 rect with black outline at center rotated counter 45 degrees
52642 *
52643 */
52644p5.prototype.rotate = function(angle, axis) {
52645  p5._validateParameters('rotate', arguments);
52646  this._renderer.rotate(this._toRadians(angle), axis);
52647  return this;
52648};
52649
52650/**
52651 * Rotates around X axis.
52652 * @method  rotateX
52653 * @param  {Number} angle the angle of rotation, specified in radians
52654 *                        or degrees, depending on current angleMode
52655 * @chainable
52656 * @example
52657 * <div modernizr='webgl'>
52658 * <code>
52659 * function setup() {
52660 *   createCanvas(100, 100, WEBGL);
52661 * }
52662 * function draw() {
52663 *   background(255);
52664 *   rotateX(millis() / 1000);
52665 *   box();
52666 * }
52667 * </code>
52668 * </div>
52669 *
52670 * @alt
52671 * 3d box rotating around the x axis.
52672 */
52673p5.prototype.rotateX = function(angle) {
52674  this._assert3d('rotateX');
52675  p5._validateParameters('rotateX', arguments);
52676  this._renderer.rotateX(this._toRadians(angle));
52677  return this;
52678};
52679
52680/**
52681 * Rotates around Y axis.
52682 * @method rotateY
52683 * @param  {Number} angle the angle of rotation, specified in radians
52684 *                        or degrees, depending on current angleMode
52685 * @chainable
52686 * @example
52687 * <div modernizr='webgl'>
52688 * <code>
52689 * function setup() {
52690 *   createCanvas(100, 100, WEBGL);
52691 * }
52692 * function draw() {
52693 *   background(255);
52694 *   rotateY(millis() / 1000);
52695 *   box();
52696 * }
52697 * </code>
52698 * </div>
52699 *
52700 * @alt
52701 * 3d box rotating around the y axis.
52702 */
52703p5.prototype.rotateY = function(angle) {
52704  this._assert3d('rotateY');
52705  p5._validateParameters('rotateY', arguments);
52706  this._renderer.rotateY(this._toRadians(angle));
52707  return this;
52708};
52709
52710/**
52711 * Rotates around Z axis. Webgl mode only.
52712 * @method rotateZ
52713 * @param  {Number} angle the angle of rotation, specified in radians
52714 *                        or degrees, depending on current angleMode
52715 * @chainable
52716 * @example
52717 * <div modernizr='webgl'>
52718 * <code>
52719 * function setup() {
52720 *   createCanvas(100, 100, WEBGL);
52721 * }
52722 * function draw() {
52723 *   background(255);
52724 *   rotateZ(millis() / 1000);
52725 *   box();
52726 * }
52727 * </code>
52728 * </div>
52729 *
52730 * @alt
52731 * 3d box rotating around the z axis.
52732 */
52733p5.prototype.rotateZ = function(angle) {
52734  this._assert3d('rotateZ');
52735  p5._validateParameters('rotateZ', arguments);
52736  this._renderer.rotateZ(this._toRadians(angle));
52737  return this;
52738};
52739
52740/**
52741 * Increases or decreases the size of a shape by expanding and contracting
52742 * vertices. Objects always scale from their relative origin to the
52743 * coordinate system. Scale values are specified as decimal percentages.
52744 * For example, the function call scale(2.0) increases the dimension of a
52745 * shape by 200%.
52746 * <br><br>
52747 * Transformations apply to everything that happens after and subsequent
52748 * calls to the function multiply the effect. For example, calling scale(2.0)
52749 * and then scale(1.5) is the same as scale(3.0). If scale() is called
52750 * within draw(), the transformation is reset when the loop begins again.
52751 * <br><br>
52752 * Using this function with the z parameter is only available in WEBGL mode.
52753 * This function can be further controlled with push() and pop().
52754 *
52755 * @method scale
52756 * @param  {Number|p5.Vector|Number[]} s
52757 *                      percent to scale the object, or percentage to
52758 *                      scale the object in the x-axis if multiple arguments
52759 *                      are given
52760 * @param  {Number} [y] percent to scale the object in the y-axis
52761 * @param  {Number} [z] percent to scale the object in the z-axis (webgl only)
52762 * @chainable
52763 * @example
52764 * <div>
52765 * <code>
52766 * translate(width / 2, height / 2);
52767 * rotate(PI / 3.0);
52768 * rect(-26, -26, 52, 52);
52769 * </code>
52770 * </div>
52771 *
52772 * <div>
52773 * <code>
52774 * rect(30, 20, 50, 50);
52775 * scale(0.5, 1.3);
52776 * rect(30, 20, 50, 50);
52777 * </code>
52778 * </div>
52779 *
52780 * @alt
52781 * white 52x52 rect with black outline at center rotated counter 45 degrees
52782 * 2 white rects with black outline- 1 50x50 at center. other 25x65 bottom left
52783 *
52784 */
52785/**
52786 * @method scale
52787 * @param  {p5.Vector|Number[]} scales per-axis percents to scale the object
52788 * @chainable
52789 */
52790p5.prototype.scale = function(x, y, z) {
52791  p5._validateParameters('scale', arguments);
52792  // Only check for Vector argument type if Vector is available
52793  if (x instanceof p5.Vector) {
52794    var v = x;
52795    x = v.x;
52796    y = v.y;
52797    z = v.z;
52798  } else if (x instanceof Array) {
52799    var rg = x;
52800    x = rg[0];
52801    y = rg[1];
52802    z = rg[2] || 1;
52803  }
52804  if (isNaN(y)) {
52805    y = z = x;
52806  } else if (isNaN(z)) {
52807    z = 1;
52808  }
52809
52810  this._renderer.scale.call(this._renderer, x, y, z);
52811
52812  return this;
52813};
52814
52815/**
52816 * Shears a shape around the x-axis the amount specified by the angle
52817 * parameter. Angles should be specified in the current angleMode.
52818 * Objects are always sheared around their relative position to the origin
52819 * and positive numbers shear objects in a clockwise direction.
52820 * <br><br>
52821 * Transformations apply to everything that happens after and subsequent
52822 * calls to the function accumulates the effect. For example, calling
52823 * shearX(PI/2) and then shearX(PI/2) is the same as shearX(PI).
52824 * If shearX() is called within the draw(), the transformation is reset when
52825 * the loop begins again.
52826 * <br><br>
52827 * Technically, shearX() multiplies the current transformation matrix by a
52828 * rotation matrix. This function can be further controlled by the
52829 * push() and pop() functions.
52830 *
52831 * @method shearX
52832 * @param  {Number} angle angle of shear specified in radians or degrees,
52833 *                        depending on current angleMode
52834 * @chainable
52835 * @example
52836 * <div>
52837 * <code>
52838 * translate(width / 4, height / 4);
52839 * shearX(PI / 4.0);
52840 * rect(0, 0, 30, 30);
52841 * </code>
52842 * </div>
52843 *
52844 * @alt
52845 * white irregular quadrilateral with black outline at top middle.
52846 *
52847 */
52848p5.prototype.shearX = function(angle) {
52849  p5._validateParameters('shearX', arguments);
52850  this._renderer.shearX(this._toRadians(angle));
52851  return this;
52852};
52853
52854/**
52855 * Shears a shape around the y-axis the amount specified by the angle
52856 * parameter. Angles should be specified in the current angleMode. Objects
52857 * are always sheared around their relative position to the origin and
52858 * positive numbers shear objects in a clockwise direction.
52859 * <br><br>
52860 * Transformations apply to everything that happens after and subsequent
52861 * calls to the function accumulates the effect. For example, calling
52862 * shearY(PI/2) and then shearY(PI/2) is the same as shearY(PI). If
52863 * shearY() is called within the draw(), the transformation is reset when
52864 * the loop begins again.
52865 * <br><br>
52866 * Technically, shearY() multiplies the current transformation matrix by a
52867 * rotation matrix. This function can be further controlled by the
52868 * push() and pop() functions.
52869 *
52870 * @method shearY
52871 * @param  {Number} angle angle of shear specified in radians or degrees,
52872 *                        depending on current angleMode
52873 * @chainable
52874 * @example
52875 * <div>
52876 * <code>
52877 * translate(width / 4, height / 4);
52878 * shearY(PI / 4.0);
52879 * rect(0, 0, 30, 30);
52880 * </code>
52881 * </div>
52882 *
52883 * @alt
52884 * white irregular quadrilateral with black outline at middle bottom.
52885 *
52886 */
52887p5.prototype.shearY = function(angle) {
52888  p5._validateParameters('shearY', arguments);
52889  this._renderer.shearY(this._toRadians(angle));
52890  return this;
52891};
52892
52893/**
52894 * Specifies an amount to displace objects within the display window.
52895 * The x parameter specifies left/right translation, the y parameter
52896 * specifies up/down translation.
52897 * <br><br>
52898 * Transformations are cumulative and apply to everything that happens after
52899 * and subsequent calls to the function accumulates the effect. For example,
52900 * calling translate(50, 0) and then translate(20, 0) is the same as
52901 * translate(70, 0). If translate() is called within draw(), the
52902 * transformation is reset when the loop begins again. This function can be
52903 * further controlled by using push() and pop().
52904 *
52905 * @method translate
52906 * @param  {Number} x left/right translation
52907 * @param  {Number} y up/down translation
52908 * @param  {Number} [z] forward/backward translation (webgl only)
52909 * @chainable
52910 * @example
52911 * <div>
52912 * <code>
52913 * translate(30, 20);
52914 * rect(0, 0, 55, 55);
52915 * </code>
52916 * </div>
52917 *
52918 * <div>
52919 * <code>
52920 * rect(0, 0, 55, 55); // Draw rect at original 0,0
52921 * translate(30, 20);
52922 * rect(0, 0, 55, 55); // Draw rect at new 0,0
52923 * translate(14, 14);
52924 * rect(0, 0, 55, 55); // Draw rect at new 0,0
52925 * </code>
52926 * </div>
52927 *
52928
52929 * <div>
52930 * <code>
52931 * function draw() {
52932 *   background(200);
52933 *   rectMode(CENTER);
52934 *   translate(width / 2, height / 2);
52935 *   translate(p5.Vector.fromAngle(millis() / 1000, 40));
52936 *   rect(0, 0, 20, 20);
52937 * }
52938 * </code>
52939 * </div>
52940 *
52941 * @alt
52942 * white 55x55 rect with black outline at center right.
52943 * 3 white 55x55 rects with black outlines at top-l, center-r and bottom-r.
52944 * a 20x20 white rect moving in a circle around the canvas
52945 *
52946 */
52947/**
52948 * @method translate
52949 * @param  {p5.Vector} vector the vector to translate by
52950 * @chainable
52951 */
52952p5.prototype.translate = function(x, y, z) {
52953  p5._validateParameters('translate', arguments);
52954  if (this._renderer.isP3D) {
52955    this._renderer.translate(x, y, z);
52956  } else {
52957    this._renderer.translate(x, y);
52958  }
52959  return this;
52960};
52961
52962module.exports = p5;
52963
52964},{"./core":22}],35:[function(_dereq_,module,exports){
52965/**
52966 * @module Shape
52967 * @submodule Vertex
52968 * @for p5
52969 * @requires core
52970 * @requires constants
52971 */
52972
52973'use strict';
52974
52975var p5 = _dereq_('./core');
52976var constants = _dereq_('./constants');
52977var shapeKind = null;
52978var vertices = [];
52979var contourVertices = [];
52980var isBezier = false;
52981var isCurve = false;
52982var isQuadratic = false;
52983var isContour = false;
52984var isFirstContour = true;
52985
52986/**
52987 * Use the beginContour() and endContour() functions to create negative
52988 * shapes within shapes such as the center of the letter 'O'. beginContour()
52989 * begins recording vertices for the shape and endContour() stops recording.
52990 * The vertices that define a negative shape must "wind" in the opposite
52991 * direction from the exterior shape. First draw vertices for the exterior
52992 * clockwise order, then for internal shapes, draw vertices
52993 * shape in counter-clockwise.
52994 * <br><br>
52995 * These functions can only be used within a beginShape()/endShape() pair and
52996 * transformations such as translate(), rotate(), and scale() do not work
52997 * within a beginContour()/endContour() pair. It is also not possible to use
52998 * other shapes, such as ellipse() or rect() within.
52999 *
53000 * @method beginContour
53001 * @chainable
53002 * @example
53003 * <div>
53004 * <code>
53005 * translate(50, 50);
53006 * stroke(255, 0, 0);
53007 * beginShape();
53008 * // Exterior part of shape, clockwise winding
53009 * vertex(-40, -40);
53010 * vertex(40, -40);
53011 * vertex(40, 40);
53012 * vertex(-40, 40);
53013 * // Interior part of shape, counter-clockwise winding
53014 * beginContour();
53015 * vertex(-20, -20);
53016 * vertex(-20, 20);
53017 * vertex(20, 20);
53018 * vertex(20, -20);
53019 * endContour();
53020 * endShape(CLOSE);
53021 * </code>
53022 * </div>
53023 *
53024 * @alt
53025 * white rect and smaller grey rect with red outlines in center of canvas.
53026 *
53027 */
53028p5.prototype.beginContour = function() {
53029  contourVertices = [];
53030  isContour = true;
53031  return this;
53032};
53033
53034/**
53035 * Using the beginShape() and endShape() functions allow creating more
53036 * complex forms. beginShape() begins recording vertices for a shape and
53037 * endShape() stops recording. The value of the kind parameter tells it which
53038 * types of shapes to create from the provided vertices. With no mode
53039 * specified, the shape can be any irregular polygon.
53040 * <br><br>
53041 * The parameters available for beginShape() are POINTS, LINES, TRIANGLES,
53042 * TRIANGLE_FAN, TRIANGLE_STRIP, QUADS, and QUAD_STRIP. After calling the
53043 * beginShape() function, a series of vertex() commands must follow. To stop
53044 * drawing the shape, call endShape(). Each shape will be outlined with the
53045 * current stroke color and filled with the fill color.
53046 * <br><br>
53047 * Transformations such as translate(), rotate(), and scale() do not work
53048 * within beginShape(). It is also not possible to use other shapes, such as
53049 * ellipse() or rect() within beginShape().
53050 *
53051 * @method beginShape
53052 * @param  {Constant} [kind] either POINTS, LINES, TRIANGLES, TRIANGLE_FAN
53053 *                                TRIANGLE_STRIP, QUADS, or QUAD_STRIP
53054 * @chainable
53055 * @example
53056 * <div>
53057 * <code>
53058 * beginShape();
53059 * vertex(30, 20);
53060 * vertex(85, 20);
53061 * vertex(85, 75);
53062 * vertex(30, 75);
53063 * endShape(CLOSE);
53064 * </code>
53065 * </div>
53066 *
53067 * <div>
53068 * <code>
53069 * beginShape(POINTS);
53070 * vertex(30, 20);
53071 * vertex(85, 20);
53072 * vertex(85, 75);
53073 * vertex(30, 75);
53074 * endShape();
53075 * </code>
53076 * </div>
53077 *
53078 * <div>
53079 * <code>
53080 * beginShape(LINES);
53081 * vertex(30, 20);
53082 * vertex(85, 20);
53083 * vertex(85, 75);
53084 * vertex(30, 75);
53085 * endShape();
53086 * </code>
53087 * </div>
53088 *
53089 * <div>
53090 * <code>
53091 * noFill();
53092 * beginShape();
53093 * vertex(30, 20);
53094 * vertex(85, 20);
53095 * vertex(85, 75);
53096 * vertex(30, 75);
53097 * endShape();
53098 * </code>
53099 * </div>
53100 *
53101 * <div>
53102 * <code>
53103 * noFill();
53104 * beginShape();
53105 * vertex(30, 20);
53106 * vertex(85, 20);
53107 * vertex(85, 75);
53108 * vertex(30, 75);
53109 * endShape(CLOSE);
53110 * </code>
53111 * </div>
53112 *
53113 * <div>
53114 * <code>
53115 * beginShape(TRIANGLES);
53116 * vertex(30, 75);
53117 * vertex(40, 20);
53118 * vertex(50, 75);
53119 * vertex(60, 20);
53120 * vertex(70, 75);
53121 * vertex(80, 20);
53122 * endShape();
53123 * </code>
53124 * </div>
53125 *
53126 * <div>
53127 * <code>
53128 * beginShape(TRIANGLE_STRIP);
53129 * vertex(30, 75);
53130 * vertex(40, 20);
53131 * vertex(50, 75);
53132 * vertex(60, 20);
53133 * vertex(70, 75);
53134 * vertex(80, 20);
53135 * vertex(90, 75);
53136 * endShape();
53137 * </code>
53138 * </div>
53139 *
53140 * <div>
53141 * <code>
53142 * beginShape(TRIANGLE_FAN);
53143 * vertex(57.5, 50);
53144 * vertex(57.5, 15);
53145 * vertex(92, 50);
53146 * vertex(57.5, 85);
53147 * vertex(22, 50);
53148 * vertex(57.5, 15);
53149 * endShape();
53150 * </code>
53151 * </div>
53152 *
53153 * <div>
53154 * <code>
53155 * beginShape(QUADS);
53156 * vertex(30, 20);
53157 * vertex(30, 75);
53158 * vertex(50, 75);
53159 * vertex(50, 20);
53160 * vertex(65, 20);
53161 * vertex(65, 75);
53162 * vertex(85, 75);
53163 * vertex(85, 20);
53164 * endShape();
53165 * </code>
53166 * </div>
53167 *
53168 * <div>
53169 * <code>
53170 * beginShape(QUAD_STRIP);
53171 * vertex(30, 20);
53172 * vertex(30, 75);
53173 * vertex(50, 20);
53174 * vertex(50, 75);
53175 * vertex(65, 20);
53176 * vertex(65, 75);
53177 * vertex(85, 20);
53178 * vertex(85, 75);
53179 * endShape();
53180 * </code>
53181 * </div>
53182 *
53183 * <div>
53184 * <code>
53185 * beginShape();
53186 * vertex(20, 20);
53187 * vertex(40, 20);
53188 * vertex(40, 40);
53189 * vertex(60, 40);
53190 * vertex(60, 60);
53191 * vertex(20, 60);
53192 * endShape(CLOSE);
53193 * </code>
53194 * </div>
53195 * @alt
53196 * white square-shape with black outline in middle-right of canvas.
53197 * 4 black points in a square shape in middle-right of canvas.
53198 * 2 horizontal black lines. In the top-right and bottom-right of canvas.
53199 * 3 line shape with horizontal on top, vertical in middle and horizontal bottom.
53200 * square line shape in middle-right of canvas.
53201 * 2 white triangle shapes mid-right canvas. left one pointing up and right down.
53202 * 5 horizontal interlocking and alternating white triangles in mid-right canvas.
53203 * 4 interlocking white triangles in 45 degree rotated square-shape.
53204 * 2 white rectangle shapes in mid-right canvas. Both 20x55.
53205 * 3 side-by-side white rectangles center rect is smaller in mid-right canvas.
53206 * Thick white l-shape with black outline mid-top-left of canvas.
53207 *
53208 */
53209p5.prototype.beginShape = function(kind) {
53210  p5._validateParameters('beginShape', arguments);
53211  if (this._renderer.isP3D) {
53212    this._renderer.beginShape.apply(this._renderer, arguments);
53213  } else {
53214    if (
53215      kind === constants.POINTS ||
53216      kind === constants.LINES ||
53217      kind === constants.TRIANGLES ||
53218      kind === constants.TRIANGLE_FAN ||
53219      kind === constants.TRIANGLE_STRIP ||
53220      kind === constants.QUADS ||
53221      kind === constants.QUAD_STRIP
53222    ) {
53223      shapeKind = kind;
53224    } else {
53225      shapeKind = null;
53226    }
53227
53228    vertices = [];
53229    contourVertices = [];
53230  }
53231  return this;
53232};
53233
53234/**
53235 * Specifies vertex coordinates for Bezier curves. Each call to
53236 * bezierVertex() defines the position of two control points and
53237 * one anchor point of a Bezier curve, adding a new segment to a
53238 * line or shape.
53239 * <br><br>
53240 * The first time bezierVertex() is used within a
53241 * beginShape() call, it must be prefaced with a call to vertex()
53242 * to set the first anchor point. This function must be used between
53243 * beginShape() and endShape() and only when there is no MODE
53244 * parameter specified to beginShape().
53245 *
53246 * @method bezierVertex
53247 * @param  {Number} x2 x-coordinate for the first control point
53248 * @param  {Number} y2 y-coordinate for the first control point
53249 * @param  {Number} x3 x-coordinate for the second control point
53250 * @param  {Number} y3 y-coordinate for the second control point
53251 * @param  {Number} x4 x-coordinate for the anchor point
53252 * @param  {Number} y4 y-coordinate for the anchor point
53253 * @chainable
53254 * @example
53255 * <div>
53256 * <code>
53257 * strokeWeight(5);
53258 * point(30, 20);
53259 * point(80, 20);
53260 * point(80, 75);
53261 * point(30, 75);
53262 *
53263 * strokeWeight(1);
53264 * noFill();
53265 * beginShape();
53266 * vertex(30, 20);
53267 * bezierVertex(80, 20, 80, 75, 30, 75);
53268 * endShape();
53269 * </code>
53270 * </div>
53271 *
53272 * <div>
53273 * <code>
53274 * strokeWeight(5);
53275 * point(30, 20);
53276 * point(80, 20);
53277 * point(80, 75);
53278 * point(30, 75);
53279 *
53280 * stroke(244, 122, 158);
53281 * point(50, 80);
53282 * point(60, 25);
53283 * point(30, 20);
53284 *
53285 * stroke(0);
53286 * strokeWeight(1);
53287 * beginShape();
53288 * vertex(30, 20);
53289 * bezierVertex(80, 20, 80, 75, 30, 75);
53290 * bezierVertex(50, 80, 60, 25, 30, 20);
53291 * endShape();
53292 * </code>
53293 * </div>
53294 *
53295 * @alt
53296 * crescent-shaped line in middle of canvas. Points facing left.
53297 * white crescent shape in middle of canvas. Points facing left.
53298 *
53299 */
53300p5.prototype.bezierVertex = function(x2, y2, x3, y3, x4, y4) {
53301  p5._validateParameters('bezierVertex', arguments);
53302  if (vertices.length === 0) {
53303    throw 'vertex() must be used once before calling bezierVertex()';
53304  } else {
53305    isBezier = true;
53306    var vert = [];
53307    for (var i = 0; i < arguments.length; i++) {
53308      vert[i] = arguments[i];
53309    }
53310    vert.isVert = false;
53311    if (isContour) {
53312      contourVertices.push(vert);
53313    } else {
53314      vertices.push(vert);
53315    }
53316  }
53317  return this;
53318};
53319
53320/**
53321 * Specifies vertex coordinates for curves. This function may only
53322 * be used between beginShape() and endShape() and only when there
53323 * is no MODE parameter specified to beginShape().
53324 * <br><br>
53325 * The first and last points in a series of curveVertex() lines will be used to
53326 * guide the beginning and end of a the curve. A minimum of four
53327 * points is required to draw a tiny curve between the second and
53328 * third points. Adding a fifth point with curveVertex() will draw
53329 * the curve between the second, third, and fourth points. The
53330 * curveVertex() function is an implementation of Catmull-Rom
53331 * splines.
53332 *
53333 * @method curveVertex
53334 * @param {Number} x x-coordinate of the vertex
53335 * @param {Number} y y-coordinate of the vertex
53336 * @chainable
53337 * @example
53338 * <div>
53339 * <code>
53340 * strokeWeight(5);
53341 * point(84, 91);
53342 * point(68, 19);
53343 * point(21, 17);
53344 * point(32, 91);
53345 * strokeWeight(1);
53346 *
53347 * noFill();
53348 * beginShape();
53349 * curveVertex(84, 91);
53350 * curveVertex(84, 91);
53351 * curveVertex(68, 19);
53352 * curveVertex(21, 17);
53353 * curveVertex(32, 91);
53354 * curveVertex(32, 91);
53355 * endShape();
53356 * </code>
53357 * </div>
53358 *
53359 *
53360 * @alt
53361 * Upside-down u-shape line, mid canvas. left point extends beyond canvas view.
53362 *
53363 */
53364p5.prototype.curveVertex = function(x, y) {
53365  p5._validateParameters('curveVertex', arguments);
53366  isCurve = true;
53367  this.vertex(x, y);
53368  return this;
53369};
53370
53371/**
53372 * Use the beginContour() and endContour() functions to create negative
53373 * shapes within shapes such as the center of the letter 'O'. beginContour()
53374 * begins recording vertices for the shape and endContour() stops recording.
53375 * The vertices that define a negative shape must "wind" in the opposite
53376 * direction from the exterior shape. First draw vertices for the exterior
53377 * clockwise order, then for internal shapes, draw vertices
53378 * shape in counter-clockwise.
53379 * <br><br>
53380 * These functions can only be used within a beginShape()/endShape() pair and
53381 * transformations such as translate(), rotate(), and scale() do not work
53382 * within a beginContour()/endContour() pair. It is also not possible to use
53383 * other shapes, such as ellipse() or rect() within.
53384 *
53385 * @method endContour
53386 * @chainable
53387 * @example
53388 * <div>
53389 * <code>
53390 * translate(50, 50);
53391 * stroke(255, 0, 0);
53392 * beginShape();
53393 * // Exterior part of shape, clockwise winding
53394 * vertex(-40, -40);
53395 * vertex(40, -40);
53396 * vertex(40, 40);
53397 * vertex(-40, 40);
53398 * // Interior part of shape, counter-clockwise winding
53399 * beginContour();
53400 * vertex(-20, -20);
53401 * vertex(-20, 20);
53402 * vertex(20, 20);
53403 * vertex(20, -20);
53404 * endContour();
53405 * endShape(CLOSE);
53406 * </code>
53407 * </div>
53408 *
53409 * @alt
53410 * white rect and smaller grey rect with red outlines in center of canvas.
53411 *
53412 */
53413p5.prototype.endContour = function() {
53414  var vert = contourVertices[0].slice(); // copy all data
53415  vert.isVert = contourVertices[0].isVert;
53416  vert.moveTo = false;
53417  contourVertices.push(vert);
53418
53419  // prevent stray lines with multiple contours
53420  if (isFirstContour) {
53421    vertices.push(vertices[0]);
53422    isFirstContour = false;
53423  }
53424
53425  for (var i = 0; i < contourVertices.length; i++) {
53426    vertices.push(contourVertices[i]);
53427  }
53428  return this;
53429};
53430
53431/**
53432 * The endShape() function is the companion to beginShape() and may only be
53433 * called after beginShape(). When endshape() is called, all of image data
53434 * defined since the previous call to beginShape() is written into the image
53435 * buffer. The constant CLOSE as the value for the MODE parameter to close
53436 * the shape (to connect the beginning and the end).
53437 *
53438 * @method endShape
53439 * @param  {Constant} [mode] use CLOSE to close the shape
53440 * @chainable
53441 * @example
53442 * <div>
53443 * <code>
53444 * noFill();
53445 *
53446 * beginShape();
53447 * vertex(20, 20);
53448 * vertex(45, 20);
53449 * vertex(45, 80);
53450 * endShape(CLOSE);
53451 *
53452 * beginShape();
53453 * vertex(50, 20);
53454 * vertex(75, 20);
53455 * vertex(75, 80);
53456 * endShape();
53457 * </code>
53458 * </div>
53459 *
53460 * @alt
53461 * Triangle line shape with smallest interior angle on bottom and upside-down L.
53462 *
53463 */
53464p5.prototype.endShape = function(mode) {
53465  p5._validateParameters('endShape', arguments);
53466  if (this._renderer.isP3D) {
53467    this._renderer.endShape(
53468      mode,
53469      isCurve,
53470      isBezier,
53471      isQuadratic,
53472      isContour,
53473      shapeKind
53474    );
53475  } else {
53476    if (vertices.length === 0) {
53477      return this;
53478    }
53479    if (!this._renderer._doStroke && !this._renderer._doFill) {
53480      return this;
53481    }
53482
53483    var closeShape = mode === constants.CLOSE;
53484
53485    // if the shape is closed, the first element is also the last element
53486    if (closeShape && !isContour) {
53487      vertices.push(vertices[0]);
53488    }
53489
53490    this._renderer.endShape(
53491      mode,
53492      vertices,
53493      isCurve,
53494      isBezier,
53495      isQuadratic,
53496      isContour,
53497      shapeKind
53498    );
53499
53500    // Reset some settings
53501    isCurve = false;
53502    isBezier = false;
53503    isQuadratic = false;
53504    isContour = false;
53505    isFirstContour = true;
53506
53507    // If the shape is closed, the first element was added as last element.
53508    // We must remove it again to prevent the list of vertices from growing
53509    // over successive calls to endShape(CLOSE)
53510    if (closeShape) {
53511      vertices.pop();
53512    }
53513  }
53514  return this;
53515};
53516
53517/**
53518 * Specifies vertex coordinates for quadratic Bezier curves. Each call to
53519 * quadraticVertex() defines the position of one control points and one
53520 * anchor point of a Bezier curve, adding a new segment to a line or shape.
53521 * The first time quadraticVertex() is used within a beginShape() call, it
53522 * must be prefaced with a call to vertex() to set the first anchor point.
53523 * This function must be used between beginShape() and endShape() and only
53524 * when there is no MODE parameter specified to beginShape().
53525 *
53526 * @method quadraticVertex
53527 * @param  {Number} cx x-coordinate for the control point
53528 * @param  {Number} cy y-coordinate for the control point
53529 * @param  {Number} x3 x-coordinate for the anchor point
53530 * @param  {Number} y3 y-coordinate for the anchor point
53531 * @chainable
53532 * @example
53533 * <div>
53534 * <code>
53535 * strokeWeight(5);
53536 * point(20, 20);
53537 * point(80, 20);
53538 * point(50, 50);
53539 *
53540 * noFill();
53541 * strokeWeight(1);
53542 * beginShape();
53543 * vertex(20, 20);
53544 * quadraticVertex(80, 20, 50, 50);
53545 * endShape();
53546 * </code>
53547 * </div>
53548 *
53549 * <div>
53550 * <code>
53551 * strokeWeight(5);
53552 * point(20, 20);
53553 * point(80, 20);
53554 * point(50, 50);
53555 *
53556 * point(20, 80);
53557 * point(80, 80);
53558 * point(80, 60);
53559 *
53560 * noFill();
53561 * strokeWeight(1);
53562 * beginShape();
53563 * vertex(20, 20);
53564 * quadraticVertex(80, 20, 50, 50);
53565 * quadraticVertex(20, 80, 80, 80);
53566 * vertex(80, 60);
53567 * endShape();
53568 * </code>
53569 * </div>
53570 *
53571 * @alt
53572 * arched-shaped black line with 4 pixel thick stroke weight.
53573 * backwards s-shaped black line with 4 pixel thick stroke weight.
53574 *
53575 */
53576p5.prototype.quadraticVertex = function(cx, cy, x3, y3) {
53577  p5._validateParameters('quadraticVertex', arguments);
53578  //if we're drawing a contour, put the points into an
53579  // array for inside drawing
53580  if (this._contourInited) {
53581    var pt = {};
53582    pt.x = cx;
53583    pt.y = cy;
53584    pt.x3 = x3;
53585    pt.y3 = y3;
53586    pt.type = constants.QUADRATIC;
53587    this._contourVertices.push(pt);
53588
53589    return this;
53590  }
53591  if (vertices.length > 0) {
53592    isQuadratic = true;
53593    var vert = [];
53594    for (var i = 0; i < arguments.length; i++) {
53595      vert[i] = arguments[i];
53596    }
53597    vert.isVert = false;
53598    if (isContour) {
53599      contourVertices.push(vert);
53600    } else {
53601      vertices.push(vert);
53602    }
53603  } else {
53604    throw 'vertex() must be used once before calling quadraticVertex()';
53605  }
53606  return this;
53607};
53608
53609/**
53610 * All shapes are constructed by connecting a series of vertices. vertex()
53611 * is used to specify the vertex coordinates for points, lines, triangles,
53612 * quads, and polygons. It is used exclusively within the beginShape() and
53613 * endShape() functions.
53614 *
53615 * @method vertex
53616 * @param  {Number} x x-coordinate of the vertex
53617 * @param  {Number} y y-coordinate of the vertex
53618 * @chainable
53619 * @example
53620 * <div>
53621 * <code>
53622 * strokeWeight(3);
53623 * beginShape(POINTS);
53624 * vertex(30, 20);
53625 * vertex(85, 20);
53626 * vertex(85, 75);
53627 * vertex(30, 75);
53628 * endShape();
53629 * </code>
53630 * </div>
53631 *
53632 * @alt
53633 * 4 black points in a square shape in middle-right of canvas.
53634 *
53635 * <div>
53636 * <code>
53637 * createCanvas(100, 100, WEBGL);
53638 * background(240, 240, 240);
53639 * fill(237, 34, 93);
53640 * noStroke();
53641 * beginShape();
53642 * vertex(0, 35);
53643 * vertex(35, 0);
53644 * vertex(0, -35);
53645 * vertex(-35, 0);
53646 * endShape();
53647 * </code>
53648 * </div>
53649 *
53650 * @alt
53651 * 4 points making a diamond shape
53652 *
53653 * <div>
53654 * <code>
53655 * createCanvas(100, 100, WEBGL);
53656 * background(240, 240, 240);
53657 * fill(237, 34, 93);
53658 * noStroke();
53659 * beginShape();
53660 * vertex(-10, 10);
53661 * vertex(0, 35);
53662 * vertex(10, 10);
53663 * vertex(35, 0);
53664 * vertex(10, -8);
53665 * vertex(0, -35);
53666 * vertex(-10, -8);
53667 * vertex(-35, 0);
53668 * endShape();
53669 * </code>
53670 * </div>
53671 *
53672 * @alt
53673 * 8 points making a star
53674 *
53675 * <div>
53676 * <code>
53677 * strokeWeight(3);
53678 * stroke(237, 34, 93);
53679 * beginShape(LINES);
53680 * vertex(10, 35);
53681 * vertex(90, 35);
53682 * vertex(10, 65);
53683 * vertex(90, 65);
53684 * vertex(35, 10);
53685 * vertex(35, 90);
53686 * vertex(65, 10);
53687 * vertex(65, 90);
53688 * endShape();
53689 * </code>
53690 * </div>
53691 *
53692 * @alt
53693 * 8 points making 4 lines
53694 *
53695 */
53696/**
53697 * @method vertex
53698 * @param  {Number} x
53699 * @param  {Number} y
53700 * @param  {Number} [z] z-coordinate of the vertex
53701 * @param  {Number} [u] the vertex's texture u-coordinate
53702 * @param  {Number} [v] the vertex's texture v-coordinate
53703 */
53704p5.prototype.vertex = function(x, y, moveTo, u, v) {
53705  if (this._renderer.isP3D) {
53706    this._renderer.vertex.apply(this._renderer, arguments);
53707  } else {
53708    var vert = [];
53709    vert.isVert = true;
53710    vert[0] = x;
53711    vert[1] = y;
53712    vert[2] = 0;
53713    vert[3] = 0;
53714    vert[4] = 0;
53715    vert[5] = this._renderer._getFill();
53716    vert[6] = this._renderer._getStroke();
53717
53718    if (moveTo) {
53719      vert.moveTo = moveTo;
53720    }
53721    if (isContour) {
53722      if (contourVertices.length === 0) {
53723        vert.moveTo = true;
53724      }
53725      contourVertices.push(vert);
53726    } else {
53727      vertices.push(vert);
53728    }
53729  }
53730  return this;
53731};
53732
53733module.exports = p5;
53734
53735},{"./constants":21,"./core":22}],36:[function(_dereq_,module,exports){
53736/**
53737 * @module Data
53738 * @submodule Dictionary
53739 * @for p5.TypedDict
53740 * @requires core
53741 *
53742 * This module defines the p5 methods for the p5 Dictionary classes
53743 * these classes StringDict and NumberDict are for storing and working
53744 * with key, value pairs
53745 */
53746
53747'use strict';
53748
53749var p5 = _dereq_('../core/core');
53750
53751/**
53752 *
53753 * Creates a new instance of p5.StringDict using the key, value pair
53754 * or object you provide.
53755 *
53756 * @method createStringDict
53757 * @for p5
53758 * @param {String} key
53759 * @param {String} value
53760 * @return {p5.StringDict}
53761 *
53762 * @example
53763 * <div class="norender">
53764 * <code>
53765 * function setup() {
53766 *   var myDictionary = createStringDict('p5', 'js');
53767 *   print(myDictionary.hasKey('p5')); // logs true to console
53768 * }
53769 * </code></div>
53770 */
53771/**
53772 * @method createStringDict
53773 * @param {Object} object object
53774 * @return {p5.StringDict}
53775 */
53776
53777p5.prototype.createStringDict = function(key, value) {
53778  p5._validateParameters('createStringDict', arguments);
53779  return new p5.StringDict(key, value);
53780};
53781
53782/**
53783 *
53784 * Creates a new instance of p5.NumberDict using the key, value pair
53785 * or object you provide.
53786 *
53787 * @method createNumberDict
53788 * @for p5
53789 * @param {Number} key
53790 * @param {Number} value
53791 * @return {p5.NumberDict}
53792 *
53793 * @example
53794 * <div class="norender">
53795 * <code>
53796 * function setup() {
53797 *   var myDictionary = createNumberDict(100, 42);
53798 *   print(myDictionary.hasKey(100)); // logs true to console
53799 * }
53800 * </code></div>
53801 */
53802/**
53803 * @method createNumberDict
53804 * @param {Object} object object
53805 * @return {p5.NumberDict}
53806 */
53807
53808p5.prototype.createNumberDict = function(key, value) {
53809  p5._validateParameters('createNumberDict', arguments);
53810  return new p5.NumberDict(key, value);
53811};
53812
53813/**
53814 *
53815 * Base class for all p5.Dictionary types. More specifically
53816 * typed Dictionary objects inherit from this
53817 *
53818 * @class p5.TypedDict
53819 *
53820 */
53821
53822p5.TypedDict = function(key, value) {
53823  if (key instanceof Object) {
53824    this.data = key;
53825  } else {
53826    this.data = {};
53827    this.data[key] = value;
53828  }
53829  return this;
53830};
53831
53832/**
53833 * Returns the number of key-value pairs currently in Dictionary object
53834 *
53835 * @method size
53836 * @return {Integer} the number of key-value pairs in Dictionary object
53837 *
53838 * @example
53839 * <div class="norender">
53840 * <code>
53841 * function setup() {
53842 *   var myDictionary = createNumberDict(1, 10);
53843 *   myDictionary.create(2, 20);
53844 *   myDictionary.create(3, 30);
53845 *   print(myDictionary.size()); // value of amt is 3
53846 * }
53847 * </code></div>
53848 *
53849 */
53850p5.TypedDict.prototype.size = function() {
53851  return Object.keys(this.data).length;
53852};
53853
53854/**
53855 * Returns true if key exists in Dictionary
53856 * otherwise returns false
53857 *
53858 * @method hasKey
53859 * @param {Number|String} key that you want to access
53860 * @return {Boolean} whether that key exists in Dictionary
53861 *
53862 * @example
53863 * <div class="norender">
53864 * <code>
53865 * function setup() {
53866 *   var myDictionary = createStringDict('p5', 'js');
53867 *   print(myDictionary.hasKey('p5')); // logs true to console
53868 * }
53869 * </code></div>
53870 *
53871 */
53872
53873p5.TypedDict.prototype.hasKey = function(key) {
53874  return this.data.hasOwnProperty(key);
53875};
53876
53877/**
53878 * Returns value stored at supplied key.
53879 *
53880 * @method get
53881 * @param {Number|String} key that you want to access
53882 * @return {Number|String} the value stored at that key
53883 *
53884 * @example
53885 * <div class="norender">
53886 * <code>
53887 * function setup() {
53888 *   var myDictionary = createStringDict('p5', 'js');
53889 *   var myValue = myDictionary.get('p5');
53890 *   print(myValue === 'js'); // logs true to console
53891 * }
53892 * </code></div>
53893 *
53894 */
53895
53896p5.TypedDict.prototype.get = function(key) {
53897  if (this.data.hasOwnProperty(key)) {
53898    return this.data[key];
53899  } else {
53900    console.log(key + ' does not exist in this Dictionary');
53901  }
53902};
53903
53904/**
53905 * Changes the value of key if in it already exists in
53906 * in the Dictionary otherwise makes a new key-value pair
53907 *
53908 * @method set
53909 * @param {Number|String} key
53910 * @param {Number|String} value
53911 *
53912 * @example
53913 * <div class="norender">
53914 * <code>
53915 * function setup() {
53916 *   var myDictionary = createStringDict('p5', 'js');
53917 *   myDictionary.set('p5', 'JS');
53918 *   myDictionary.print();
53919 *   // above logs "key: p5 - value: JS" to console
53920 * }
53921 * </code></div>
53922 *
53923 */
53924
53925p5.TypedDict.prototype.set = function(key, value) {
53926  if (this._validate(value)) {
53927    this.data[key] = value;
53928  } else {
53929    console.log('Those values dont work for this dictionary type.');
53930  }
53931};
53932
53933/**
53934 * private helper function to handle the user passing objects in
53935 * during construction or calls to create()
53936 */
53937
53938p5.TypedDict.prototype._addObj = function(obj) {
53939  for (var key in obj) {
53940    this.set(key, obj[key]);
53941  }
53942};
53943
53944/**
53945 * Creates a key-value pair in the Dictionary
53946 *
53947 * @method create
53948 * @param {Number|String} key
53949 * @param {Number|String} value
53950 *
53951 * @example
53952 * <div class="norender">
53953 * <code>
53954 * function setup() {
53955 *   var myDictionary = createStringDict('p5', 'js');
53956 *   myDictionary.create('happy', 'coding');
53957 *   myDictionary.print();
53958 *   // above logs "key: p5 - value: js, key: happy - value: coding" to console
53959 * }
53960 * </code></div>
53961 */
53962/**
53963 * @method create
53964 * @param {Object} obj key/value pair
53965 */
53966
53967p5.TypedDict.prototype.create = function(key, value) {
53968  if (key instanceof Object && typeof value === 'undefined') {
53969    this._addObj(key);
53970  } else if (typeof key !== 'undefined') {
53971    this.set(key, value);
53972  } else {
53973    console.log(
53974      'In order to create a new Dictionary entry you must pass ' +
53975        'an object or a key, value pair'
53976    );
53977  }
53978};
53979
53980/**
53981 * Empties Dictionary of all key-value pairs
53982 * @method clear
53983 * @example
53984 * <div class="norender">
53985 * <code>
53986 * function setup() {
53987 *   var myDictionary = createStringDict('p5', 'js');
53988 *   print(myDictionary.hasKey('p5')); // prints 'true'
53989 *   myDictionary.clear();
53990 *   print(myDictionary.hasKey('p5')); // prints 'false'
53991 * }
53992 * </code>
53993 * </div>
53994 */
53995
53996p5.TypedDict.prototype.clear = function() {
53997  this.data = {};
53998};
53999
54000/**
54001 * Removes a key-value pair in the Dictionary
54002 *
54003 * @method remove
54004 * @param {Number|String} key for the pair to remove
54005 *
54006 * @example
54007 * <div class="norender">
54008 * <code>
54009 * function setup() {
54010 *   var myDictionary = createStringDict('p5', 'js');
54011 *   myDictionary.create('happy', 'coding');
54012 *   myDictionary.print();
54013 *   // above logs "key: p5 - value: js, key: happy - value: coding" to console
54014 *   myDictionary.remove('p5');
54015 *   myDictionary.print();
54016 *   // above logs "key: happy value: coding" to console
54017 * }
54018 * </code></div>
54019 *
54020 */
54021
54022p5.TypedDict.prototype.remove = function(key) {
54023  if (this.data.hasOwnProperty(key)) {
54024    delete this.data[key];
54025  } else {
54026    throw key + ' does not exist in this Dictionary';
54027  }
54028};
54029
54030/**
54031 * Logs the list of items currently in the Dictionary to the console
54032 *
54033 * @method print
54034 *
54035 * @example
54036 * <div class="norender">
54037 * <code>
54038 * function setup() {
54039 *   var myDictionary = createStringDict('p5', 'js');
54040 *   myDictionary.create('happy', 'coding');
54041 *   myDictionary.print();
54042 *   // above logs "key: p5 - value: js, key: happy - value: coding" to console
54043 * }
54044 * </code>
54045 * </div>
54046 */
54047
54048p5.TypedDict.prototype.print = function() {
54049  for (var item in this.data) {
54050    console.log('key:' + item + ' value:' + this.data[item]);
54051  }
54052};
54053
54054/**
54055 * Converts the Dictionary into a CSV file for local
54056 * storage.
54057 *
54058 * @method saveTable
54059 * @example
54060 * <div>
54061 * <code>
54062 * createButton('save')
54063 *   .position(10, 10)
54064 *   .mousePressed(function() {
54065 *     createStringDict({
54066 *       john: 1940,
54067      paul: 1942,
54068      george: 1943,
54069      ringo: 1940
54070 *     }).saveTable('beatles');
54071 *   });
54072 * </code>
54073 * </div>
54074 */
54075
54076p5.TypedDict.prototype.saveTable = function(filename) {
54077  var output = '';
54078
54079  for (var key in this.data) {
54080    output += key + ',' + this.data[key] + '\n';
54081  }
54082
54083  var blob = new Blob([output], { type: 'text/csv' });
54084  p5.prototype.downloadFile(blob, filename || 'mycsv', 'csv');
54085};
54086
54087/**
54088 * Converts the Dictionary into a JSON file for local
54089 * storage.
54090 *
54091 * @method saveJSON
54092 * @example
54093 * <div>
54094 * <code>
54095 * createButton('save')
54096 *   .position(10, 10)
54097 *   .mousePressed(function() {
54098 *     createStringDict({
54099 *       john: 1940,
54100      paul: 1942,
54101      george: 1943,
54102      ringo: 1940
54103 *     }).saveJSON('beatles');
54104 *   });
54105 * </code>
54106 * </div>
54107 */
54108
54109p5.TypedDict.prototype.saveJSON = function(filename, opt) {
54110  p5.prototype.saveJSON(this.data, filename, opt);
54111};
54112
54113/**
54114 * private helper function to ensure that the user passed in valid
54115 * values for the Dictionary type
54116 */
54117
54118p5.TypedDict.prototype._validate = function(value) {
54119  return true;
54120};
54121
54122/**
54123 *
54124 * A  Dictionary class for Strings.
54125 *
54126 *
54127 * @class p5.StringDict
54128 * @extends p5.TypedDict
54129 *
54130 */
54131
54132p5.StringDict = function() {
54133  p5.TypedDict.apply(this, arguments);
54134};
54135
54136p5.StringDict.prototype = Object.create(p5.TypedDict.prototype);
54137
54138p5.StringDict.prototype._validate = function(value) {
54139  return typeof value === 'string';
54140};
54141
54142/**
54143 *
54144 * A simple Dictionary class for Numbers.
54145 *
54146 *
54147 * @class p5.NumberDict
54148 * @extends p5.TypedDict
54149 *
54150 */
54151
54152p5.NumberDict = function() {
54153  p5.TypedDict.apply(this, arguments);
54154};
54155
54156p5.NumberDict.prototype = Object.create(p5.TypedDict.prototype);
54157
54158/**
54159 * private helper function to ensure that the user passed in valid
54160 * values for the Dictionary type
54161 */
54162
54163p5.NumberDict.prototype._validate = function(value) {
54164  return typeof value === 'number';
54165};
54166
54167/**
54168 * Add to a value stored at a certain key
54169 * The sum is stored in that location in the Dictionary.
54170 *
54171 * @method add
54172 * @param {Number} Key for value you wish to add to
54173 * @param {Number} Amount to add to the value
54174 * @example
54175 * <div class='norender'>
54176 * <code>
54177 * function setup() {
54178 *   var myDictionary = createNumberDict(2, 5);
54179 *   myDictionary.add(2, 2);
54180 *   console.log(myDictionary.get(2)); // logs 7 to console.
54181 * }
54182 * </code></div>
54183 *
54184 *
54185 */
54186
54187p5.NumberDict.prototype.add = function(key, amount) {
54188  if (this.data.hasOwnProperty(key)) {
54189    this.data[key] += amount;
54190  } else {
54191    console.log('The key - ' + key + ' does not exist in this dictionary.');
54192  }
54193};
54194
54195/**
54196 * Subtract from a value stored at a certain key
54197 * The difference is stored in that location in the Dictionary.
54198 *
54199 * @method sub
54200 * @param {Number}
54200 Key for value you wish to subtract from
54201 * @param {Number} Amount to subtract from the value
54202 * @example
54203 * <div class='norender'>
54204 * <code>
54205 * function setup() {
54206 *   var myDictionary = createNumberDict(2, 5);
54207 *   myDictionary.sub(2, 2);
54208 *   console.log(myDictionary.get(2)); // logs 3 to console.
54209 * }
54210 * </code></div>
54211 *
54212 *
54213 */
54214
54215p5.NumberDict.prototype.sub = function(key, amount) {
54216  this.add(key, -amount);
54217};
54218
54219/**
54220 * Multiply a value stored at a certain key
54221 * The product is stored in that location in the Dictionary.
54222 *
54223 * @method mult
54224 * @param {Number} Key for value you wish to multiply
54225 * @param {Number} Amount to multiply the value by
54226 * @example
54227 * <div class='norender'>
54228 * <code>
54229 * function setup() {
54230 *   var myDictionary = createNumberDict(2, 4);
54231 *   myDictionary.mult(2, 2);
54232 *   console.log(myDictionary.get(2)); // logs 8 to console.
54233 * }
54234 * </code></div>
54235 *
54236 *
54237 */
54238
54239p5.NumberDict.prototype.mult = function(key, amount) {
54240  if (this.data.hasOwnProperty(key)) {
54241    this.data[key] *= amount;
54242  } else {
54243    console.log('The key - ' + key + ' does not exist in this dictionary.');
54244  }
54245};
54246
54247/**
54248 * Divide a value stored at a certain key
54249 * The quotient is stored in that location in the Dictionary.
54250 *
54251 * @method div
54252 * @param {Number} Key for value you wish to divide
54253 * @param {Number} Amount to divide the value by
54254 * @example
54255 * <div class='norender'>
54256 * <code>
54257 * function setup() {
54258 *   var myDictionary = createNumberDict(2, 8);
54259 *   myDictionary.div(2, 2);
54260 *   console.log(myDictionary.get(2)); // logs 4 to console.
54261 * }
54262 * </code></div>
54263 *
54264 *
54265 */
54266
54267p5.NumberDict.prototype.div = function(key, amount) {
54268  if (this.data.hasOwnProperty(key)) {
54269    this.data[key] /= amount;
54270  } else {
54271    console.log('The key - ' + key + ' does not exist in this dictionary.');
54272  }
54273};
54274
54275/**
54276 * private helper function for finding lowest or highest value
54277 * the argument 'flip' is used to flip the comparison arrow
54278 * from 'less than' to 'greater than'
54279 *
54280 */
54281
54282p5.NumberDict.prototype._valueTest = function(flip) {
54283  if (Object.keys(this.data).length === 0) {
54284    throw 'Unable to search for a minimum or maximum value on an empty NumberDict';
54285  } else if (Object.keys(this.data).length === 1) {
54286    return this.data[Object.keys(this.data)[0]];
54287  } else {
54288    var result = this.data[Object.keys(this.data)[0]];
54289    for (var key in this.data) {
54290      if (this.data[key] * flip < result * flip) {
54291        result = this.data[key];
54292      }
54293    }
54294    return result;
54295  }
54296};
54297
54298/**
54299 * Return the lowest value.
54300 *
54301 * @method minValue
54302 * @return {Number}
54303 * @example
54304 * <div class='norender'>
54305 * <code>
54306 * function setup() {
54307 *   var myDictionary = createNumberDict({ 2: -10, 4: 0.65, 1.2: 3 });
54308 *   var lowestValue = myDictionary.minValue(); // value is -10
54309 *   print(lowestValue);
54310 * }
54311 * </code></div>
54312 *
54313 */
54314
54315p5.NumberDict.prototype.minValue = function() {
54316  return this._valueTest(1);
54317};
54318
54319/**
54320 * Return the highest value.
54321 *
54322 * @method maxValue
54323 * @return {Number}
54324 * @example
54325 * <div class='norender'>
54326 * <code>
54327 * function setup() {
54328 *   var myDictionary = createNumberDict({ 2: -10, 4: 0.65, 1.2: 3 });
54329 *   var highestValue = myDictionary.maxValue(); // value is 3
54330 *   print(highestValue);
54331 * }
54332 * </code></div>
54333 *
54334 */
54335
54336p5.NumberDict.prototype.maxValue = function() {
54337  return this._valueTest(-1);
54338};
54339
54340/**
54341 * private helper function for finding lowest or highest key
54342 * the argument 'flip' is used to flip the comparison arrow
54343 * from 'less than' to 'greater than'
54344 *
54345 */
54346
54347p5.NumberDict.prototype._keyTest = function(flip) {
54348  if (Object.keys(this.data).length === 0) {
54349    throw 'Unable to use minValue on an empty NumberDict';
54350  } else if (Object.keys(this.data).length === 1) {
54351    return Object.keys(this.data)[0];
54352  } else {
54353    var result = Object.keys(this.data)[0];
54354    for (var i = 1; i < Object.keys(this.data).length; i++) {
54355      if (Object.keys(this.data)[i] * flip < result * flip) {
54356        result = Object.keys(this.data)[i];
54357      }
54358    }
54359    return result;
54360  }
54361};
54362
54363/**
54364 * Return the lowest key.
54365 *
54366 * @method minKey
54367 * @return {Number}
54368 * @example
54369 * <div class='norender'>
54370 * <code>
54371 * function setup() {
54372 *   var myDictionary = createNumberDict({ 2: 4, 4: 6, 1.2: 3 });
54373 *   var lowestKey = myDictionary.minKey(); // value is 1.2
54374 *   print(lowestKey);
54375 * }
54376 * </code></div>
54377 *
54378 */
54379
54380p5.NumberDict.prototype.minKey = function() {
54381  return this._keyTest(1);
54382};
54383
54384/**
54385 * Return the highest key.
54386 *
54387 * @method maxKey
54388 * @return {Number}
54389 * @example
54390 * <div class='norender'>
54391 * <code>
54392 * function setup() {
54393 *   var myDictionary = createNumberDict({ 2: 4, 4: 6, 1.2: 3 });
54394 *   var highestKey = myDictionary.maxKey(); // value is 4
54395 *   print(highestKey);
54396 * }
54397 * </code></div>
54398 *
54399 */
54400
54401p5.NumberDict.prototype.maxKey = function() {
54402  return this._keyTest(-1);
54403};
54404
54405module.exports = p5.TypedDict;
54406
54407},{"../core/core":22}],37:[function(_dereq_,module,exports){
54408/**
54409 * @module Events
54410 * @submodule Acceleration
54411 * @for p5
54412 * @requires core
54413 */
54414
54415'use strict';
54416
54417var p5 = _dereq_('../core/core');
54418
54419/**
54420 * The system variable deviceOrientation always contains the orientation of
54421 * the device. The value of this variable will either be set 'landscape'
54422 * or 'portrait'. If no data is available it will be set to 'undefined'.
54423 * either LANDSCAPE or PORTRAIT.
54424 *
54425 * @property {Constant} deviceOrientation
54426 * @readOnly
54427 */
54428p5.prototype.deviceOrientation = undefined;
54429
54430/**
54431 * The system variable accelerationX always contains the acceleration of the
54432 * device along the x axis. Value is represented as meters per second squared.
54433 *
54434 * @property {Number} accelerationX
54435 * @readOnly
54436 */
54437p5.prototype.accelerationX = 0;
54438
54439/**
54440 * The system variable accelerationY always contains the acceleration of the
54441 * device along the y axis. Value is represented as meters per second squared.
54442 *
54443 * @property {Number} accelerationY
54444 * @readOnly
54445 */
54446p5.prototype.accelerationY = 0;
54447
54448/**
54449 * The system variable accelerationZ always contains the acceleration of the
54450 * device along the z axis. Value is represented as meters per second squared.
54451 *
54452 * @property {Number} accelerationZ
54453 * @readOnly
54454 */
54455p5.prototype.accelerationZ = 0;
54456
54457/**
54458 * The system variable pAccelerationX always contains the acceleration of the
54459 * device along the x axis in the frame previous to the current frame. Value
54460 * is represented as meters per second squared.
54461 *
54462 * @property {Number} pAccelerationX
54463 * @readOnly
54464 */
54465p5.prototype.pAccelerationX = 0;
54466
54467/**
54468 * The system variable pAccelerationY always contains the acceleration of the
54469 * device along the y axis in the frame previous to the current frame. Value
54470 * is represented as meters per second squared.
54471 *
54472 * @property {Number} pAccelerationY
54473 * @readOnly
54474 */
54475p5.prototype.pAccelerationY = 0;
54476
54477/**
54478 * The system variable pAccelerationZ always contains the acceleration of the
54479 * device along the z axis in the frame previous to the current frame. Value
54480 * is represented as meters per second squared.
54481 *
54482 * @property {Number} pAccelerationZ
54483 * @readOnly
54484 */
54485p5.prototype.pAccelerationZ = 0;
54486
54487/**
54488 * _updatePAccelerations updates the pAcceleration values
54489 *
54490 * @private
54491 */
54492p5.prototype._updatePAccelerations = function() {
54493  this._setProperty('pAccelerationX', this.accelerationX);
54494  this._setProperty('pAccelerationY', this.accelerationY);
54495  this._setProperty('pAccelerationZ', this.accelerationZ);
54496};
54497
54498/**
54499 * The system variable rotationX always contains the rotation of the
54500 * device along the x axis. Value is represented as 0 to +/-180 degrees.
54501 * <br><br>
54502 * Note: The order the rotations are called is important, ie. if used
54503 * together, it must be called in the order Z-X-Y or there might be
54504 * unexpected behaviour.
54505 *
54506 * @example
54507 * <div>
54508 * <code>
54509 * function setup() {
54510 *   createCanvas(100, 100, WEBGL);
54511 * }
54512 *
54513 * function draw() {
54514 *   background(200);
54515 *   //rotateZ(radians(rotationZ));
54516 *   rotateX(radians(rotationX));
54517 *   //rotateY(radians(rotationY));
54518 *   box(200, 200, 200);
54519 * }
54520 * </code>
54521 * </div>
54522 *
54523 * @property {Number} rotationX
54524 * @readOnly
54525 *
54526 * @alt
54527 * red horizontal line right, green vertical line bottom. black background.
54528 *
54529 */
54530p5.prototype.rotationX = 0;
54531
54532/**
54533 * The system variable rotationY always contains the rotation of the
54534 * device along the y axis. Value is represented as 0 to +/-90 degrees.
54535 * <br><br>
54536 * Note: The order the rotations are called is important, ie. if used
54537 * together, it must be called in the order Z-X-Y or there might be
54538 * unexpected behaviour.
54539 *
54540 * @example
54541 * <div>
54542 * <code>
54543 * function setup() {
54544 *   createCanvas(100, 100, WEBGL);
54545 * }
54546 *
54547 * function draw() {
54548 *   background(200);
54549 *   //rotateZ(radians(rotationZ));
54550 *   //rotateX(radians(rotationX));
54551 *   rotateY(radians(rotationY));
54552 *   box(200, 200, 200);
54553 * }
54554 * </code>
54555 * </div>
54556 *
54557 * @property {Number} rotationY
54558 * @readOnly
54559 *
54560 * @alt
54561 * red horizontal line right, green vertical line bottom. black background.
54562 */
54563p5.prototype.rotationY = 0;
54564
54565/**
54566 * The system variable rotationZ always contains the rotation of the
54567 * device along the z axis. Value is represented as 0 to 359 degrees.
54568 * <br><br>
54569 * Unlike rotationX and rotationY, this variable is available for devices
54570 * with a built-in compass only.
54571 * <br><br>
54572 * Note: The order the rotations are called is important, ie. if used
54573 * together, it must be called in the order Z-X-Y or there might be
54574 * unexpected behaviour.
54575 *
54576 * @example
54577 * <div>
54578 * <code>
54579 * function setup() {
54580 *   createCanvas(100, 100, WEBGL);
54581 * }
54582 *
54583 * function draw() {
54584 *   background(200);
54585 *   rotateZ(radians(rotationZ));
54586 *   //rotateX(radians(rotationX));
54587 *   //rotateY(radians(rotationY));
54588 *   box(200, 200, 200);
54589 * }
54590 * </code>
54591 * </div>
54592 *
54593 * @property {Number} rotationZ
54594 * @readOnly
54595 *
54596 * @alt
54597 * red horizontal line right, green vertical line bottom. black background.
54598 */
54599p5.prototype.rotationZ = 0;
54600
54601/**
54602 * The system variable pRotationX always contains the rotation of the
54603 * device along the x axis in the frame previous to the current frame. Value
54604 * is represented as 0 to +/-180 degrees.
54605 * <br><br>
54606 * pRotationX can also be used with rotationX to determine the rotate
54607 * direction of the device along the X-axis.
54608 * @example
54609 * <div class='norender'>
54610 * <code>
54611 * // A simple if statement looking at whether
54612 * // rotationX - pRotationX < 0 is true or not will be
54613 * // sufficient for determining the rotate direction
54614 * // in most cases.
54615 *
54616 * // Some extra logic is needed to account for cases where
54617 * // the angles wrap around.
54618 * var rotateDirection = 'clockwise';
54619 *
54620 * // Simple range conversion to make things simpler.
54621 * // This is not absolutely necessary but the logic
54622 * // will be different in that case.
54623 *
54624 * var rX = rotationX + 180;
54625 * var pRX = pRotationX + 180;
54626 *
54627 * if ((rX - pRX > 0 && rX - pRX < 270) || rX - pRX < -270) {
54628 *   rotateDirection = 'clockwise';
54629 * } else if (rX - pRX < 0 || rX - pRX > 270) {
54630 *   rotateDirection = 'counter-clockwise';
54631 * }
54632 *
54633 * print(rotateDirection);
54634 * </code>
54635 * </div>
54636 *
54637 * @alt
54638 * no image to display.
54639 *
54640 *
54641 * @property {Number} pRotationX
54642 * @readOnly
54643 */
54644p5.prototype.pRotationX = 0;
54645
54646/**
54647 * The system variable pRotationY always contains the rotation of the
54648 * device along the y axis in the frame previous to the current frame. Value
54649 * is represented as 0 to +/-90 degrees.
54650 * <br><br>
54651 * pRotationY can also be used with rotationY to determine the rotate
54652 * direction of the device along the Y-axis.
54653 * @example
54654 * <div class='norender'>
54655 * <code>
54656 * // A simple if statement looking at whether
54657 * // rotationY - pRotationY < 0 is true or not will be
54658 * // sufficient for determining the rotate direction
54659 * // in most cases.
54660 *
54661 * // Some extra logic is needed to account for cases where
54662 * // the angles wrap around.
54663 * var rotateDirection = 'clockwise';
54664 *
54665 * // Simple range conversion to make things simpler.
54666 * // This is not absolutely necessary but the logic
54667 * // will be different in that case.
54668 *
54669 * var rY = rotationY + 180;
54670 * var pRY = pRotationY + 180;
54671 *
54672 * if ((rY - pRY > 0 && rY - pRY < 270) || rY - pRY < -270) {
54673 *   rotateDirection = 'clockwise';
54674 * } else if (rY - pRY < 0 || rY - pRY > 270) {
54675 *   rotateDirection = 'counter-clockwise';
54676 * }
54677 * print(rotateDirection);
54678 * </code>
54679 * </div>
54680 *
54681 * @alt
54682 * no image to display.
54683 *
54684 *
54685 * @property {Number} pRotationY
54686 * @readOnly
54687 */
54688p5.prototype.pRotationY = 0;
54689
54690/**
54691 * The system variable pRotationZ always contains the rotation of the
54692 * device along the z axis in the frame previous to the current frame. Value
54693 * is represented as 0 to 359 degrees.
54694 * <br><br>
54695 * pRotationZ can also be used with rotationZ to determine the rotate
54696 * direction of the device along the Z-axis.
54697 * @example
54698 * <div class='norender'>
54699 * <code>
54700 * // A simple if statement looking at whether
54701 * // rotationZ - pRotationZ < 0 is true or not will be
54702 * // sufficient for determining the rotate direction
54703 * // in most cases.
54704 *
54705 * // Some extra logic is needed to account for cases where
54706 * // the angles wrap around.
54707 * var rotateDirection = 'clockwise';
54708 *
54709 * if (
54710 *   (rotationZ - pRotationZ > 0 && rotationZ - pRotationZ < 270) ||
54711 *   rotationZ - pRotationZ < -270
54712 * ) {
54713 *   rotateDirection = 'clockwise';
54714 * } else if (rotationZ - pRotationZ < 0 || rotationZ - pRotationZ > 270) {
54715 *   rotateDirection = 'counter-clockwise';
54716 * }
54717 * print(rotateDirection);
54718 * </code>
54719 * </div>
54720 *
54721 * @alt
54722 * no image to display.
54723 *
54724 *
54725 * @property {Number} pRotationZ
54726 * @readOnly
54727 */
54728p5.prototype.pRotationZ = 0;
54729
54730var startAngleX = 0;
54731var startAngleY = 0;
54732var startAngleZ = 0;
54733
54734var rotateDirectionX = 'clockwise';
54735var rotateDirectionY = 'clockwise';
54736var rotateDirectionZ = 'clockwise';
54737
54738var pRotateDirectionX;
54739var pRotateDirectionY;
54740var pRotateDirectionZ;
54741
54742p5.prototype._updatePRotations = function() {
54743  this._setProperty('pRotationX', this.rotationX);
54744  this._setProperty('pRotationY', this.rotationY);
54745  this._setProperty('pRotationZ', this.rotationZ);
54746};
54747
54748/**
54749 * @property {String} turnAxis
54750 * @readOnly
54751 */
54752p5.prototype.turnAxis = undefined;
54753
54754var move_threshold = 0.5;
54755var shake_threshold = 30;
54756
54757/**
54758 * The setMoveThreshold() function is used to set the movement threshold for
54759 * the deviceMoved() function. The default threshold is set to 0.5.
54760 *
54761 * @method setMoveThreshold
54762 * @param {number} value The threshold value
54763 */
54764p5.prototype.setMoveThreshold = function(val) {
54765  p5._validateParameters('setMoveThreshold', arguments);
54766  move_threshold = val;
54767};
54768
54769/**
54770 * The setShakeThreshold() function is used to set the movement threshold for
54771 * the deviceShaken() function. The default threshold is set to 30.
54772 *
54773 * @method setShakeThreshold
54774 * @param {number} value The threshold value
54775 */
54776p5.prototype.setShakeThreshold = function(val) {
54777  p5._validateParameters('setShakeThreshold', arguments);
54778  shake_threshold = val;
54779};
54780
54781/**
54782 * The deviceMoved() function is called when the device is moved by more than
54783 * the threshold value along X, Y or Z axis. The default threshold is set to
54784 * 0.5.
54785 * @method deviceMoved
54786 * @example
54787 * <div class="norender">
54788 * <code>
54789 * // Run this example on a mobile device
54790 * // Move the device around
54791 * // to change the value.
54792 *
54793 * var value = 0;
54794 * function draw() {
54795 *   fill(value);
54796 *   rect(25, 25, 50, 50);
54797 * }
54798 * function deviceMoved() {
54799 *   value = value + 5;
54800 *   if (value > 255) {
54801 *     value = 0;
54802 *   }
54803 * }
54804 * </code>
54805 * </div>
54806 *
54807 * @alt
54808 * 50x50 black rect in center of canvas. turns white on mobile when device moves
54809 *
54810 */
54811
54812/**
54813 * The deviceTurned() function is called when the device rotates by
54814 * more than 90 degrees continuously.
54815 * <br><br>
54816 * The axis that triggers the deviceTurned() method is stored in the turnAxis
54817 * variable. The deviceTurned() method can be locked to trigger on any axis:
54818 * X, Y or Z by comparing the turnAxis variable to 'X', 'Y' or 'Z'.
54819 *
54820 * @method deviceTurned
54821 * @example
54822 * <div class="norender">
54823 * <code>
54824 * // Run this example on a mobile device
54825 * // Rotate the device by 90 degrees
54826 * // to change the value.
54827 *
54828 * var value = 0;
54829 * function draw() {
54830 *   fill(value);
54831 *   rect(25, 25, 50, 50);
54832 * }
54833 * function deviceTurned() {
54834 *   if (value === 0) {
54835 *     value = 255;
54836 *   }
54836 else if (value === 255) {
54837 *     value = 0;
54838 *   }
54839 * }
54840 * </code>
54841 * </div>
54842 * <div>
54843 * <code>
54844 * // Run this example on a mobile device
54845 * // Rotate the device by 90 degrees in the
54846 * // X-axis to change the value.
54847 *
54848 * var value = 0;
54849 * function draw() {
54850 *   fill(value);
54851 *   rect(25, 25, 50, 50);
54852 * }
54853 * function deviceTurned() {
54854 *   if (turnAxis === 'X') {
54855 *     if (value === 0) {
54856 *       value = 255;
54857 *     } else if (value === 255) {
54858 *       value = 0;
54859 *     }
54860 *   }
54861 * }
54862 * </code>
54863 * </div>
54864 *
54865 * @alt
54866 * 50x50 black rect in center of canvas. turns white on mobile when device turns
54867 * 50x50 black rect in center of canvas. turns white on mobile when x-axis turns
54868 *
54869 */
54870
54871/**
54872 * The deviceShaken() function is called when the device total acceleration
54873 * changes of accelerationX and accelerationY values is more than
54874 * the threshold value. The default threshold is set to 30.
54875 * @method deviceShaken
54876 * @example
54877 * <div class="norender">
54878 * <code>
54879 * // Run this example on a mobile device
54880 * // Shake the device to change the value.
54881 *
54882 * var value = 0;
54883 * function draw() {
54884 *   fill(value);
54885 *   rect(25, 25, 50, 50);
54886 * }
54887 * function deviceShaken() {
54888 *   value = value + 5;
54889 *   if (value > 255) {
54890 *     value = 0;
54891 *   }
54892 * }
54893 * </code>
54894 * </div>
54895 *
54896 * @alt
54897 * 50x50 black rect in center of canvas. turns white on mobile when device shakes
54898 *
54899 */
54900
54901p5.prototype._ondeviceorientation = function(e) {
54902  this._updatePRotations();
54903  this._setProperty('rotationX', e.beta);
54904  this._setProperty('rotationY', e.gamma);
54905  this._setProperty('rotationZ', e.alpha);
54906  this._handleMotion();
54907};
54908p5.prototype._ondevicemotion = function(e) {
54909  this._updatePAccelerations();
54910  this._setProperty('accelerationX', e.acceleration.x * 2);
54911  this._setProperty('accelerationY', e.acceleration.y * 2);
54912  this._setProperty('accelerationZ', e.acceleration.z * 2);
54913  this._handleMotion();
54914};
54915p5.prototype._handleMotion = function() {
54916  if (window.orientation === 90 || window.orientation === -90) {
54917    this._setProperty('deviceOrientation', 'landscape');
54918  } else if (window.orientation === 0) {
54919    this._setProperty('deviceOrientation', 'portrait');
54920  } else if (window.orientation === undefined) {
54921    this._setProperty('deviceOrientation', 'undefined');
54922  }
54923  var deviceMoved = this.deviceMoved || window.deviceMoved;
54924  if (typeof deviceMoved === 'function') {
54925    if (
54926      Math.abs(this.accelerationX - this.pAccelerationX) > move_threshold ||
54927      Math.abs(this.accelerationY - this.pAccelerationY) > move_threshold ||
54928      Math.abs(this.accelerationZ - this.pAccelerationZ) > move_threshold
54929    ) {
54930      deviceMoved();
54931    }
54932  }
54933  var deviceTurned = this.deviceTurned || window.deviceTurned;
54934  if (typeof deviceTurned === 'function') {
54935    // The angles given by rotationX etc is from range -180 to 180.
54936    // The following will convert them to 0 to 360 for ease of calculation
54937    // of cases when the angles wrapped around.
54938    // _startAngleX will be converted back at the end and updated.
54939    var wRX = this.rotationX + 180;
54940    var wPRX = this.pRotationX + 180;
54941    var wSAX = startAngleX + 180;
54942    if ((wRX - wPRX > 0 && wRX - wPRX < 270) || wRX - wPRX < -270) {
54943      rotateDirectionX = 'clockwise';
54944    } else if (wRX - wPRX < 0 || wRX - wPRX > 270) {
54945      rotateDirectionX = 'counter-clockwise';
54946    }
54947    if (rotateDirectionX !== pRotateDirectionX) {
54948      wSAX = wRX;
54949    }
54950    if (Math.abs(wRX - wSAX) > 90 && Math.abs(wRX - wSAX) < 270) {
54951      wSAX = wRX;
54952      this._setProperty('turnAxis', 'X');
54953      deviceTurned();
54954    }
54955    pRotateDirectionX = rotateDirectionX;
54956    startAngleX = wSAX - 180;
54957
54958    // Y-axis is identical to X-axis except for changing some names.
54959    var wRY = this.rotationY + 180;
54960    var wPRY = this.pRotationY + 180;
54961    var wSAY = startAngleY + 180;
54962    if ((wRY - wPRY > 0 && wRY - wPRY < 270) || wRY - wPRY < -270) {
54963      rotateDirectionY = 'clockwise';
54964    } else if (wRY - wPRY < 0 || wRY - this.pRotationY > 270) {
54965      rotateDirectionY = 'counter-clockwise';
54966    }
54967    if (rotateDirectionY !== pRotateDirectionY) {
54968      wSAY = wRY;
54969    }
54970    if (Math.abs(wRY - wSAY) > 90 && Math.abs(wRY - wSAY) < 270) {
54971      wSAY = wRY;
54972      this._setProperty('turnAxis', 'Y');
54973      deviceTurned();
54974    }
54975    pRotateDirectionY = rotateDirectionY;
54976    startAngleY = wSAY - 180;
54977
54978    // Z-axis is already in the range 0 to 360
54979    // so no conversion is needed.
54980    if (
54981      (this.rotationZ - this.pRotationZ > 0 &&
54982        this.rotationZ - this.pRotationZ < 270) ||
54983      this.rotationZ - this.pRotationZ < -270
54984    ) {
54985      rotateDirectionZ = 'clockwise';
54986    } else if (
54987      this.rotationZ - this.pRotationZ < 0 ||
54988      this.rotationZ - this.pRotationZ > 270
54989    ) {
54990      rotateDirectionZ = 'counter-clockwise';
54991    }
54992    if (rotateDirectionZ !== pRotateDirectionZ) {
54993      startAngleZ = this.rotationZ;
54994    }
54995    if (
54996      Math.abs(this.rotationZ - startAngleZ) > 90 &&
54997      Math.abs(this.rotationZ - startAngleZ) < 270
54998    ) {
54999      startAngleZ = this.rotationZ;
55000      this._setProperty('turnAxis', 'Z');
55001      deviceTurned();
55002    }
55003    pRotateDirectionZ = rotateDirectionZ;
55004    this._setProperty('turnAxis', undefined);
55005  }
55006  var deviceShaken = this.deviceShaken || window.deviceShaken;
55007  if (typeof deviceShaken === 'function') {
55008    var accelerationChangeX;
55009    var accelerationChangeY;
55010    // Add accelerationChangeZ if acceleration change on Z is needed
55011    if (this.pAccelerationX !== null) {
55012      accelerationChangeX = Math.abs(this.accelerationX - this.pAccelerationX);
55013      accelerationChangeY = Math.abs(this.accelerationY - this.pAccelerationY);
55014    }
55015    if (accelerationChangeX + accelerationChangeY > shake_threshold) {
55016      deviceShaken();
55017    }
55018  }
55019};
55020
55021module.exports = p5;
55022
55023},{"../core/core":22}],38:[function(_dereq_,module,exports){
55024/**
55025 * @module Events
55026 * @submodule Keyboard
55027 * @for p5
55028 * @requires core
55029 */
55030
55031'use strict';
55032
55033var p5 = _dereq_('../core/core');
55034
55035/**
55036 * Holds the key codes of currently pressed keys.
55037 * @private
55038 */
55039var downKeys = {};
55040
55041/**
55042 * The boolean system variable keyIsPressed is true if any key is pressed
55043 * and false if no keys are pressed.
55044 *
55045 * @property {Boolean} keyIsPressed
55046 * @readOnly
55047 * @example
55048 * <div>
55049 * <code>
55050 * function draw() {
55051 *   if (keyIsPressed === true) {
55052 *     fill(0);
55053 *   } else {
55054 *     fill(255);
55055 *   }
55056 *   rect(25, 25, 50, 50);
55057 * }
55058 * </code>
55059 * </div>
55060 *
55061 * @alt
55062 * 50x50 white rect that turns black on keypress.
55063 *
55064 */
55065p5.prototype.isKeyPressed = false;
55066p5.prototype.keyIsPressed = false; // khan
55067
55068/**
55069 * The system variable key always contains the value of the most recent
55070 * key on the keyboard that was typed. To get the proper capitalization, it
55071 * is best to use it within keyTyped(). For non-ASCII keys, use the keyCode
55072 * variable.
55073 *
55074 * @property {String} key
55075 * @readOnly
55076 * @example
55077 * <div><code>
55078 * // Click any key to display it!
55079 * // (Not Guaranteed to be Case Sensitive)
55080 * function setup() {
55081 *   fill(245, 123, 158);
55082 *   textSize(50);
55083 * }
55084 *
55085 * function draw() {
55086 *   background(200);
55087 *   text(key, 33, 65); // Display last key pressed.
55088 * }
55089 * </code></div>
55090 *
55091 * @alt
55092 * canvas displays any key value that is pressed in pink font.
55093 *
55094 */
55095p5.prototype.key = '';
55096
55097/**
55098 * The variable keyCode is used to detect special keys such as BACKSPACE,
55099 * DELETE, ENTER, RETURN, TAB, ESCAPE, SHIFT, CONTROL, OPTION, ALT, UP_ARROW,
55100 * DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW.
55101 * You can also check for custom keys by looking up the keyCode of any key
55102 * on a site like this: <a href="http://keycode.info/">keycode.info</a>.
55103 *
55104 * @property {Integer} keyCode
55105 * @readOnly
55106 * @example
55107 * <div><code>
55108 * var fillVal = 126;
55109 * function draw() {
55110 *   fill(fillVal);
55111 *   rect(25, 25, 50, 50);
55112 * }
55113 *
55114 * function keyPressed() {
55115 *   if (keyCode === UP_ARROW) {
55116 *     fillVal = 255;
55117 *   } else if (keyCode === DOWN_ARROW) {
55118 *     fillVal = 0;
55119 *   }
55120 *   return false; // prevent default
55121 * }
55122 * </code></div>
55123 *
55124 * @alt
55125 * Grey rect center. turns white when up arrow pressed and black when down
55126 *
55127 */
55128p5.prototype.keyCode = 0;
55129
55130/**
55131 * The keyPressed() function is called once every time a key is pressed. The
55132 * keyCode for the key that was pressed is stored in the keyCode variable.
55133 * <br><br>
55134 * For non-ASCII keys, use the keyCode variable. You can check if the keyCode
55135 * equals BACKSPACE, DELETE, ENTER, RETURN, TAB, ESCAPE, SHIFT, CONTROL,
55136 * OPTION, ALT, UP_ARROW, DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW.
55137 * <br><br>
55138 * For ASCII keys that was pressed is stored in the key variable. However, it
55139 * does not distinguish between uppercase and lowercase. For this reason, it
55140 * is recommended to use keyTyped() to read the key variable, in which the
55141 * case of the variable will be distinguished.
55142 * <br><br>
55143 * Because of how operating systems handle key repeats, holding down a key
55144 * may cause multiple calls to keyTyped() (and keyReleased() as well). The
55145 * rate of repeat is set by the operating system and how each computer is
55146 * configured.<br><br>
55147 * Browsers may have different default
55148 * behaviors attached to various key events. To prevent any default
55149 * behavior for this event, add "return false" to the end of the method.
55150 *
55151 * @method keyPressed
55152 * @example
55153 * <div>
55154 * <code>
55155 * var value = 0;
55156 * function draw() {
55157 *   fill(value);
55158 *   rect(25, 25, 50, 50);
55159 * }
55160 * function keyPressed() {
55161 *   if (value === 0) {
55162 *     value = 255;
55163 *   } else {
55164 *     value = 0;
55165 *   }
55166 * }
55167 * </code>
55168 * </div>
55169 * <div>
55170 * <code>
55171 * var value = 0;
55172 * function draw() {
55173 *   fill(value);
55174 *   rect(25, 25, 50, 50);
55175 * }
55176 * function keyPressed() {
55177 *   if (keyCode === LEFT_ARROW) {
55178 *     value = 255;
55179 *   } else if (keyCode === RIGHT_ARROW) {
55180 *     value = 0;
55181 *   }
55182 * }
55183 * </code>
55184 * </div>
55185 * <div class="norender">
55186 * <code>
55187 * function keyPressed() {
55188 *   // Do something
55189 *   return false; // prevent any default behaviour
55190 * }
55191 * </code>
55192 * </div>
55193 *
55194 * @alt
55195 * black rect center. turns white when key pressed and black when released
55196 * black rect center. turns white when left arrow pressed and black when right.
55197 *
55198 */
55199p5.prototype._onkeydown = function(e) {
55200  if (downKeys[e.which]) {
55201    // prevent multiple firings
55202    return;
55203  }
55204  this._setProperty('isKeyPressed', true);
55205  this._setProperty('keyIsPressed', true);
55206  this._setProperty('keyCode', e.which);
55207  downKeys[e.which] = true;
55208  var key = String.fromCharCode(e.which);
55209  if (!key) {
55210    key = e.which;
55211  }
55212  this._setProperty('key', key);
55213  var keyPressed = this.keyPressed || window.keyPressed;
55214  if (typeof keyPressed === 'function' && !e.charCode) {
55215    var executeDefault = keyPressed(e);
55216    if (executeDefault === false) {
55217      e.preventDefault();
55218    }
55219  }
55220};
55221/**
55222 * The keyReleased() function is called once every time a key is released.
55223 * See key and keyCode for more information.<br><br>
55224 * Browsers may have different default
55225 * behaviors attached to various key events. To prevent any default
55226 * behavior for this event, add "return false" to the end of the method.
55227 *
55228 * @method keyReleased
55229 * @example
55230 * <div>
55231 * <code>
55232 * var value = 0;
55233 * function draw() {
55234 *   fill(value);
55235 *   rect(25, 25, 50, 50);
55236 * }
55237 * function keyReleased() {
55238 *   if (value === 0) {
55239 *     value = 255;
55240 *   } else {
55241 *     value = 0;
55242 *   }
55243 *   return false; // prevent any default behavior
55244 * }
55245 * </code>
55246 * </div>
55247 *
55248 * @alt
55249 * black rect center. turns white when key pressed and black when pressed again
55250 *
55251 */
55252p5.prototype._onkeyup = function(e) {
55253  var keyReleased = this.keyReleased || window.keyReleased;
55254  downKeys[e.which] = false;
55255
55256  if (!areDownKeys()) {
55257    this._setProperty('isKeyPressed', false);
55258    this._setProperty('keyIsPressed', false);
55259  }
55260
55261  this._setProperty('_lastKeyCodeTyped', null);
55262
55263  var key = String.fromCharCode(e.which);
55264  if (!key) {
55265    key = e.which;
55266  }
55267  this._setProperty('key', key);
55268  this._setProperty('keyCode', e.which);
55269  if (typeof keyReleased === 'function') {
55270    var executeDefault = keyReleased(e);
55271    if (executeDefault === false) {
55272      e.preventDefault();
55273    }
55274  }
55275};
55276
55277/**
55278 * The keyTyped() function is called once every time a key is pressed, but
55279 * action keys such as Ctrl, Shift, and Alt are ignored. The most recent
55280 * key pressed will be stored in the key variable.
55281 * <br><br>
55282 * Because of how operating systems handle key repeats, holding down a key
55283 * will cause multiple calls to keyTyped() (and keyReleased() as well). The
55284 * rate of repeat is set by the operating system and how each computer is
55285 * configured.<br><br>
55286 * Browsers may have different default behaviors attached to various key
55287 * events. To prevent any default behavior for this event, add "return false"
55288 * to the end of the method.
55289 *
55290 * @method keyTyped
55291 * @example
55292 * <div>
55293 * <code>
55294 * var value = 0;
55295 * function draw() {
55296 *   fill(value);
55297 *   rect(25, 25, 50, 50);
55298 * }
55299 * function keyTyped() {
55300 *   if (key === 'a') {
55301 *     value = 255;
55302 *   } else if (key === 'b') {
55303 *     value = 0;
55304 *   }
55305 *   // uncomment to prevent any default behavior
55306 *   // return false;
55307 * }
55308 * </code>
55309 * </div>
55310 *
55311 * @alt
55312 * black rect center. turns white when 'a' key typed and black when 'b' pressed
55313 *
55314 */
55315p5.prototype._onkeypress = function(e) {
55316  if (e.which === this._lastKeyCodeTyped) {
55317    // prevent multiple firings
55318    return;
55319  }
55320  this._setProperty('keyCode', e.which);
55321  this._setProperty('_lastKeyCodeTyped', e.which); // track last keyCode
55322  this._setProperty('key', String.fromCharCode(e.which));
55323  var keyTyped = this.keyTyped || window.keyTyped;
55324  if (typeof keyTyped === 'function') {
55325    var executeDefault = keyTyped(e);
55326    if (executeDefault === false) {
55327      e.preventDefault();
55328    }
55329  }
55330};
55331/**
55332 * The onblur function is called when the user is no longer focused
55333 * on the p5 element. Because the keyup events will not fire if the user is
55334 * not focused on the element we must assume all keys currently down have
55335 * been released.
55336 */
55337p5.prototype._onblur = function(e) {
55338  downKeys = {};
55339};
55340
55341/**
55342 * The keyIsDown() function checks if the key is currently down, i.e. pressed.
55343 * It can be used if you have an object that moves, and you want several keys
55344 * to be able to affect its behaviour simultaneously, such as moving a
55345 * sprite diagonally. You can put in any number representing the keyCode of
55346 * the key, or use any of the variable keyCode names listed
55347 * <a href="http://p5js.org/reference/#p5/keyCode">here</a>.
55348 *
55349 * @method keyIsDown
55350 * @param {Number}          code The key to check for.
55351 * @return {Boolean}        whether key is down or not
55352 * @example
55353 * <div><code>
55354 * var x = 100;
55355 * var y = 100;
55356 *
55357 * function setup() {
55358 *   createCanvas(512, 512);
55359 * }
55360 *
55361 * function draw() {
55362 *   if (keyIsDown(LEFT_ARROW)) {
55363 *     x -= 5;
55364 *   }
55365 *
55366 *   if (keyIsDown(RIGHT_ARROW)) {
55367 *     x += 5;
55368 *   }
55369 *
55370 *   if (keyIsDown(UP_ARROW)) {
55371 *     y -= 5;
55372 *   }
55373 *
55374 *   if (keyIsDown(DOWN_ARROW)) {
55375 *     y += 5;
55376 *   }
55377 *
55378 *   clear();
55379 *   fill(255, 0, 0);
55380 *   ellipse(x, y, 50, 50);
55381 * }
55382 * </code></div>
55383 *
55384 * @alt
55385 * 50x50 red ellipse moves left, right, up and down with arrow presses.
55386 *
55387 */
55388p5.prototype.keyIsDown = function(code) {
55389  p5._validateParameters('keyIsDown', arguments);
55390  return downKeys[code];
55391};
55392
55393/**
55394 * The checkDownKeys function returns a boolean true if any keys pressed
55395 * and a false if no keys are currently pressed.
55396
55397 * Helps avoid instances where a multiple keys are pressed simultaneously and
55398 * releasing a single key will then switch the
55399 * keyIsPressed property to true.
55400 * @private
55401**/
55402function areDownKeys() {
55403  for (var key in downKeys) {
55404    if (downKeys.hasOwnProperty(key) && downKeys[key] === true) {
55405      return true;
55406    }
55407  }
55408  return false;
55409}
55410
55411module.exports = p5;
55412
55413},{"../core/core":22}],39:[function(_dereq_,module,exports){
55414/**
55415 * @module Events
55416 * @submodule Mouse
55417 * @for p5
55418 * @requires core
55419 * @requires constants
55420 */
55421
55422'use strict';
55423
55424var p5 = _dereq_('../core/core');
55425var constants = _dereq_('../core/constants');
55426
55427/*
55428 * This is a flag which is false until the first time
55429 * we receive a mouse event. The pmouseX and pmouseY
55430 * values will match the mouseX and mouseY values until
55431 * this interaction takes place.
55432 */
55433p5.prototype._hasMouseInteracted = false;
55434
55435/**
55436 * The system variable mouseX always contains the current horizontal
55437 * position of the mouse, relative to (0, 0) of the canvas. If touch is
55438 * used instead of mouse input, mouseX will hold the x value of the most
55439 * recent touch point.
55440 *
55441 * @property {Number} mouseX
55442 * @readOnly
55443 *
55444 * @example
55445 * <div>
55446 * <code>
55447 * // Move the mouse across the canvas
55448 * function draw() {
55449 *   background(244, 248, 252);
55450 *   line(mouseX, 0, mouseX, 100);
55451 * }
55452 * </code>
55453 * </div>
55454 *
55455 * @alt
55456 * horizontal black line moves left and right with mouse x-position
55457 *
55458 */
55459p5.prototype.mouseX = 0;
55460
55461/**
55462 * The system variable mouseY always contains the current vertical position
55463 * of the mouse, relative to (0, 0) of the canvas. If touch is
55464 * used instead of mouse input, mouseY will hold the y value of the most
55465 * recent touch point.
55466 *
55467 * @property {Number} mouseY
55468 * @readOnly
55469 *
55470 * @example
55471 * <div>
55472 * <code>
55473 * // Move the mouse across the canvas
55474 * function draw() {
55475 *   background(244, 248, 252);
55476 *   line(0, mouseY, 100, mouseY);
55477 * }
55478 * </code>
55479 * </div>
55480 *
55481 * @alt
55482 * vertical black line moves up and down with mouse y-position
55483 *
55484 */
55485p5.prototype.mouseY = 0;
55486
55487/**
55488 * The system variable pmouseX always contains the horizontal position of
55489 * the mouse or finger in the frame previous to the current frame, relative to
55490 * (0, 0) of the canvas.
55491 *
55492 * @property {Number} pmouseX
55493 * @readOnly
55494 *
55495 * @example
55496 * <div>
55497 * <code>
55498 * // Move the mouse across the canvas to leave a trail
55499 * function setup() {
55500 *   //slow down the frameRate to make it more visible
55501 *   frameRate(10);
55502 * }
55503 *
55504 * function draw() {
55505 *   background(244, 248, 252);
55506 *   line(mouseX, mouseY, pmouseX, pmouseY);
55507 *   print(pmouseX + ' -> ' + mouseX);
55508 * }
55509 * </code>
55510 * </div>
55511 *
55512 * @alt
55513 * line trail is created from cursor movements. faster movement make longer line.
55514 *
55515 */
55516p5.prototype.pmouseX = 0;
55517
55518/**
55519 * The system variable pmouseY always contains the vertical position of the
55520 * mouse or finger in the frame previous to the current frame, relative to
55521 * (0, 0) of the canvas.
55522 *
55523 * @property {Number} pmouseY
55524 * @readOnly
55525 *
55526 * @example
55527 * <div>
55528 * <code>
55529 * function draw() {
55530 *   background(237, 34, 93);
55531 *   fill(0);
55532 *   //draw a square only if the mouse is not moving
55533 *   if (mouseY === pmouseY && mouseX === pmouseX) {
55534 *     rect(20, 20, 60, 60);
55535 *   }
55536 *
55537 *   print(pmouseY + ' -> ' + mouseY);
55538 * }
55539 * </code>
55540 * </div>
55541 *
55542 * @alt
55543 * 60x60 black rect center, fuschia background. rect flickers on mouse movement
55544 *
55545 */
55546p5.prototype.pmouseY = 0;
55547
55548/**
55549 * The system variable winMouseX always contains the current horizontal
55550 * position of the mouse, relative to (0, 0) of the window.
55551 *
55552 * @property {Number} winMouseX
55553 * @readOnly
55554 *
55555 * @example
55556 * <div>
55557 * <code>
55558 * var myCanvas;
55559 *
55560 * function setup() {
55561 *   //use a variable to store a pointer to the canvas
55562 *   myCanvas = createCanvas(100, 100);
55563 * }
55564 *
55565 * function draw() {
55566 *   background(237, 34, 93);
55567 *   fill(0);
55568 *
55569 *   //move the canvas to the horizontal mouse position
55570 *   //rela                    tive to the window
55571 *   myCanvas.position(winMouseX + 1, windowHeight / 2);
55572 *
55573 *   //the y of the square is relative to the canvas
55574 *   rect(20, mouseY, 60, 60);
55575 * }
55576 * </code>
55577 * </div>
55578 *
55579 * @alt
55580 * 60x60 black rect y moves with mouse y and fuschia canvas moves with mouse x
55581 *
55582 */
55583p5.prototype.winMouseX = 0;
55584
55585/**
55586 * The system variable winMouseY always contains the current vertical
55587 * position of the mouse, relative to (0, 0) of the window.
55588 *
55589 * @property {Number} winMouseY
55590 * @readOnly
55591 *
55592 * @example
55593 * <div>
55594 * <code>
55595 * var myCanvas;
55596 *
55597 * function setup() {
55598 *   //use a variable to store a pointer to the canvas
55599 *   myCanvas = createCanvas(100, 100);
55600 * }
55601 *
55602 * function draw() {
55603 *   background(237, 34, 93);
55604 *   fill(0);
55605 *
55606 *   //move the canvas to the vertical mouse position
55607 *   //rel                    ative to the window
55608 *   myCanvas.position(windowWidth / 2, winMouseY + 1);
55609 *
55610 *   //the x of the square is relative to the canvas
55611 *   rect(mouseX, 20, 60, 60);
55612 * }
55613 * </code>
55614 * </div>
55615 *
55616 * @alt
55617 * 60x60 black rect x moves with mouse x and fuschia canvas y moves with mouse y
55618 *
55619 */
55620p5.prototype.winMouseY = 0;
55621
55622/**
55623 * The system variable pwinMouseX always contains the horizontal position
55624 * of the mouse in the frame previous to the current frame, relative to
55625 * (0, 0) of the window.
55626 *
55627 * @property {Number} pwinMouseX
55628 * @readOnly
55629 *
55630 * @example
55631 * <div>
55632 * <code>
55633 * var myCanvas;
55634 *
55635 * function setup() {
55636 *   //use a variable to store a pointer to the canvas
55637 *   myCanvas = createCanvas(100, 100);
55638 *   noStroke();
55639 *   fill(237, 34, 93);
55640 * }
55641 *
55642 * function draw() {
55643 *   clear();
55644 *   //the difference between previous and
55645 *   //current x position is the horizontal mouse speed
55646 *   var speed = abs(winMouseX - pwinMouseX);
55647 *   //change the size of the circle
55648 *   //according to the horizontal speed
55649 *   ellipse(50, 50, 10 + speed * 5, 10 + speed * 5);
55650 *   //move the canvas to the mouse position
55651 *   myCanvas.position(winMouseX + 1, winMouseY + 1);
55652 * }
55653 * </code>
55654 * </div>
55655 *
55656 * @alt
55657 * fuschia ellipse moves with mouse x and y. Grows and shrinks with mouse speed
55658 *
55659 */
55660p5.prototype.pwinMouseX = 0;
55661
55662/**
55663 * The system variable pwinMouseY always contains the vertical position of
55664 * the mouse in the frame previous to the current frame, relative to (0, 0)
55665 * of the window.
55666 *
55667 * @property {Number} pwinMouseY
55668 * @readOnly
55669 *
55670 *
55671 * @example
55672 * <div>
55673 * <code>
55674 * var myCanvas;
55675 *
55676 * function setup() {
55677 *   //use a variable to store a pointer to the canvas
55678 *   myCanvas = createCanvas(100, 100);
55679 *   noStroke();
55680 *   fill(237, 34, 93);
55681 * }
55682 *
55683 * function draw() {
55684 *   clear();
55685 *   //the difference between previous and
55686 *   //current y position is the vertical mouse speed
55687 *   var speed = abs(winMouseY - pwinMouseY);
55688 *   //change the size of the circle
55689 *   //according to the vertical speed
55690 *   ellipse(50, 50, 10 + speed * 5, 10 + speed * 5);
55691 *   //move the canvas to the mouse position
55692 *   myCanvas.position(winMouseX + 1, winMouseY + 1);
55693 * }
55694 * </code>
55695 * </div>
55696 *
55697 * @alt
55698 * fuschia ellipse moves with mouse x and y. Grows and shrinks with mouse speed
55699 *
55700 */
55701p5.prototype.pwinMouseY = 0;
55702
55703/**
55704 * Processing automatically tracks if the mouse button is pressed and which
55705 * button is pressed. The value of the system variable mouseButton is either
55706 * LEFT, RIGHT, or CENTER depending on which button was pressed last.
55707 * Warning: different browsers may track mouseButton differently.
55708 *
55709 * @property {Constant} mouseButton
55710 * @readOnly
55711 *
55712 * @example
55713 * <div>
55714 * <code>
55715 * function draw() {
55716 *   background(237, 34, 93);
55717 *   fill(0);
55718 *
55719 *   if (mouseIsPressed) {
55720 *     if (mouseButton === LEFT) {
55721 *       ellipse(50, 50, 50, 50);
55722 *     }
55723 *     if (mouseButton === RIGHT) {
55724 *       rect(25, 25, 50, 50);
55725 *     }
55726 *     if (mouseButton === CENTER) {
55727 *       triangle(23, 75, 50, 20, 78, 75);
55728 *     }
55729 *   }
55730 *
55731 *   print(mouseButton);
55732 * }
55733 * </code>
55734 * </div>
55735 *
55736 * @alt
55737 * 50x50 black ellipse appears on center of fuschia canvas on mouse click/press.
55738 *
55739 */
55740p5.prototype.mouseButton = 0;
55741
55742/**
55743 * The boolean system variable mouseIsPressed is true if the mouse is pressed
55744 * and false if not.
55745 *
55746 * @property {Boolean} mouseIsPressed
55747 * @readOnly
55748 *
55749 * @example
55750 * <div>
55751 * <code>
55752 * function draw() {
55753 *   background(237, 34, 93);
55754 *   fill(0);
55755 *
55756 *   if (mouseIsPressed) {
55757 *     ellipse(50, 50, 50, 50);
55758 *   } else {
55759 *     rect(25, 25, 50, 50);
55760 *   }
55761 *
55762 *   print(mouseIsPressed);
55763 * }
55764 * </code>
55765 * </div>
55766 *
55767 * @alt
55768 * black 50x50 rect becomes ellipse with mouse click/press. fuschia background.
55769 *
55770 */
55771p5.prototype.mouseIsPressed = false;
55772
55773p5.prototype._updateNextMouseCoords = function(e) {
55774  if (this._curElement !== null && (!e.touches || e.touches.length > 0)) {
55775    var mousePos = getMousePos(
55776      this._curElement.elt,
55777      this.width,
55778      this.height,
55779      e
55780    );
55781    this._setProperty('mouseX', mousePos.x);
55782    this._setProperty('mouseY', mousePos.y);
55783    this._setProperty('winMouseX', mousePos.winX);
55784    this._setProperty('winMouseY', mousePos.winY);
55785  }
55786  if (!this._hasMouseInteracted) {
55787    // For first draw, make previous and next equal
55788    this._updateMouseCoords();
55789    this._setProperty('_hasMouseInteracted', true);
55790  }
55791};
55792
55793p5.prototype._updateMouseCoords = function() {
55794  this._setProperty('pmouseX', this.mouseX);
55795  this._setProperty('pmouseY', this.mouseY);
55796  this._setProperty('pwinMouseX', this.winMouseX);
55797  this._setProperty('pwinMouseY', this.winMouseY);
55798};
55799
55800function getMousePos(canvas, w, h, evt) {
55801  if (evt && !evt.clientX) {
55802    // use touches if touch and not mouse
55803    if (evt.touches) {
55804      evt = evt.touches[0];
55805    } else if (evt.changedTouches) {
55806      evt = evt.changedTouches[0];
55807    }
55808  }
55809  var rect = canvas.getBoundingClientRect();
55810  var sx = canvas.scrollWidth / w;
55811  var sy = canvas.scrollHeight / h;
55812  return {
55813    x: (evt.clientX - rect.left) / sx,
55814    y: (evt.clientY - rect.top) / sy,
55815    winX: evt.clientX,
55816    winY: evt.clientY,
55817    id: evt.identifier
55818  };
55819}
55820
55821p5.prototype._setMouseButton = function(e) {
55822  if (e.button === 1) {
55823    this._setProperty('mouseButton', constants.CENTER);
55824  } else if (e.button === 2) {
55825    this._setProperty('mouseButton', constants.RIGHT);
55826  } else {
55827    this._setProperty('mouseButton', constants.LEFT);
55828  }
55829};
55830
55831/**
55832 * The mouseMoved() function is called every time the mouse moves and a mouse
55833 * button is not pressed.<br><br>
55834 * Browsers may have different default
55835 * behaviors attached to various mouse events. To prevent any default
55836 * behavior for this event, add "return false" to the end of the method.
55837 *
55838 * @method mouseMoved
55839 * @example
55840 * <div>
55841 * <code>
55842 * // Move the mouse across the page
55843 * // to change its value
55844 *
55845 * var value = 0;
55846 * function draw() {
55847 *   fill(value);
55848 *   rect(25, 25, 50, 50);
55849 * }
55850 * function mouseMoved() {
55851 *   value = value + 5;
55852 *   if (value > 255) {
55853 *     value = 0;
55854 *   }
55855 * }
55856 * </code>
55857 * </div>
55858 *
55859 * <div class="norender">
55860 * <code>
55861 * function mouseMoved() {
55862 *   ellipse(mouseX, mouseY, 5, 5);
55863 *   // prevent default
55864 *   return false;
55865 * }
55866 * </code>
55867 * </div>
55868 *
55869 * @alt
55870 * black 50x50 rect becomes lighter with mouse movements until white then resets
55871 * no image displayed
55872 *
55873 */
55874
55875/**
55876 * The mouseDragged() function is called once every time the mouse moves and
55877 * a mouse button is pressed. If no mouseDragged() function is defined, the
55878 * touchMoved() function will be called instead if it is defined.<br><br>
55879 * Browsers may have different default
55880 * behaviors attached to various mouse events. To prevent any default
55881 * behavior for this event, add "return false" to the end of the method.
55882 *
55883 * @method mouseDragged
55884 * @example
55885 * <div>
55886 * <code>
55887 * // Drag the mouse across the page
55888 * // to change its value
55889 *
55890 * var value = 0;
55891 * function draw() {
55892 *   fill(value);
55893 *   rect(25, 25, 50, 50);
55894 * }
55895 * function mouseDragged() {
55896 *   value = value + 5;
55897 *   if (value > 255) {
55898 *     value = 0;
55899 *   }
55900 * }
55901 * </code>
55902 * </div>
55903 *
55904 * <div class="norender">
55905 * <code>
55906 * function mouseDragged() {
55907 *   ellipse(mouseX, mouseY, 5, 5);
55908 *   // prevent default
55909 *   return false;
55910 * }
55911 * </code>
55912 * </div>
55913 *
55914 * @alt
55915 * black 50x50 rect turns lighter with mouse click and drag until white, resets
55916 * no image displayed
55917 *
55918 */
55919p5.prototype._onmousemove = function(e) {
55920  var context = this._isGlobal ? window : this;
55921  var executeDefault;
55922  this._updateNextMouseCoords(e);
55923  if (!this.mouseIsPressed) {
55924    if (typeof context.mouseMoved === 'function') {
55925      executeDefault = context.mouseMoved(e);
55926      if (executeDefault === false) {
55927        e.preventDefault();
55928      }
55929    }
55930  } else {
55931    if (typeof context.mouseDragged === 'function') {
55932      executeDefault = context.mouseDragged(e);
55933      if (executeDefault === false) {
55934        e.preventDefault();
55935      }
55936    } else if (typeof context.touchMoved === 'function') {
55937      executeDefault = context.touchMoved(e);
55938      if (executeDefault === false) {
55939        e.preventDefault();
55940      }
55941    }
55942  }
55943};
55944
55945/**
55946 * The mousePressed() function is called once after every time a mouse button
55947 * is pressed. The mouseButton variable (see the related reference entry)
55948 * can be used to determine which button has been pressed. If no
55949 * mousePressed() function is defined, the touchStarted() function will be
55950 * called instead if it is defined.<br><br>
55951 * Browsers may have different default
55952 * behaviors attached to various mouse events. To prevent any default
55953 * behavior for this event, add "return false" to the end of the method.
55954 *
55955 * @method mousePressed
55956 * @example
55957 * <div>
55958 * <code>
55959 * // Click within the image to change
55960 * // the value of the rectangle
55961 *
55962 * var value = 0;
55963 * function draw() {
55964 *   fill(value);
55965 *   rect(25, 25, 50, 50);
55966 * }
55967 * function mousePressed() {
55968 *   if (value === 0) {
55969 *     value = 255;
55970 *   } else {
55971 *     value = 0;
55972 *   }
55973 * }
55974 * </code>
55975 * </div>
55976 *
55977 * <div class="norender">
55978 * <code>
55979 * function mousePressed() {
55980 *   ellipse(mouseX, mouseY, 5, 5);
55981 *   // prevent default
55982 *   return false;
55983 * }
55984 * </code>
55985 * </div>
55986 *
55987 * @alt
55988 * black 50x50 rect turns white with mouse click/press.
55989 * no image displayed
55990 *
55991 */
55992p5.prototype._onmousedown = function(e) {
55993  var context = this._isGlobal ? window : this;
55994  var executeDefault;
55995  this._setProperty('mouseIsPressed', true);
55996  this._setMouseButton(e);
55997  this._updateNextMouseCoords(e);
55998  if (typeof context.mousePressed === 'function') {
55999    executeDefault = context.mousePressed(e);
56000    if (executeDefault === false) {
56001      e.preventDefault();
56002    }
56003  } else if (typeof context.touchStarted === 'function') {
56004    executeDefault = context.touchStarted(e);
56005    if (executeDefault === false) {
56006      e.preventDefault();
56007    }
56008  }
56009};
56010
56011/**
56012 * The mouseReleased() function is called every time a mouse button is
56013 * released. If no mouseReleased() function is defined, the touchEnded()
56014 * function will be called instead if it is defined.<br><br>
56015 * Browsers may have different default
56016 * behaviors attached to various mouse events. To prevent any default
56017 * behavior for this event, add "return false" to the end of the method.
56018 *
56019 *
56020 * @method mouseReleased
56021 * @example
56022 * <div>
56023 * <code>
56024 * // Click within the image to change
56025 * // the value of the rectangle
56026 * // after the mouse has been clicked
56027 *
56028 * var value = 0;
56029 * function draw() {
56030 *   fill(value);
56031 *   rect(25, 25, 50, 50);
56032 * }
56033 * function mouseReleased() {
56034 *   if (value === 0) {
56035 *     value = 255;
56036 *   } else {
56037 *     value = 0;
56038 *   }
56039 * }
56040 * </code>
56041 * </div>
56042 *
56043 * <div class="norender">
56044 * <code>
56045 * function mouseReleased() {
56046 *   ellipse(mouseX, mouseY, 5, 5);
56047 *   // prevent default
56048 *   return false;
56049 * }
56050 * </code>
56051 * </div>
56052 *
56053 * @alt
56054 * black 50x50 rect turns white with mouse click/press.
56055 * no image displayed
56056 *
56057 */
56058p5.prototype._onmouseup = function(e) {
56059  var context = this._isGlobal ? window : this;
56060  var executeDefault;
56061  this._setProperty('mouseIsPressed', false);
56062  if (typeof context.mouseReleased === 'function') {
56063    executeDefault = context.mouseReleased(e);
56064    if (executeDefault === false) {
56065      e.preventDefault();
56066    }
56067  } else if (typeof context.touchEnded === 'function') {
56068    executeDefault = context.touchEnded(e);
56069    if (executeDefault === false) {
56070      e.preventDefault();
56071    }
56072  }
56073};
56074
56075p5.prototype._ondragend = p5.prototype._onmouseup;
56076p5.prototype._ondragover = p5.prototype._onmousemove;
56077
56078/**
56079 * The mouseClicked() function is called once after a mouse button has been
56080 * pressed and then released.<br><br>
56081 * Browsers handle clicks differently, so this function is only guaranteed to be
56082 * run when the left mouse button is clicked. To handle other mouse buttons
56083 * being pressed or released, see mousePressed() or mouseReleased().<br><br>
56084 * Browsers may have different default
56085 * behaviors attached to various mouse events. To prevent any default
56086 * behavior for this event, add "return false" to the end of the method.
56087 *
56088 * @method mouseClicked
56089 * @example
56090 * <div>
56091 * <code>
56092 * // Click within the image to change
56093 * // the value of the rectangle
56094 * // after the mouse has been clicked
56095 *
56096 * var value = 0;
56097 * function draw() {
56098 *   fill(value);
56099 *   rect(25, 25, 50, 50);
56100 * }
56101 *
56102 * function mouseClicked() {
56103 *   if (value === 0) {
56104 *     value = 255;
56105 *   } else {
56106 *     value = 0;
56107 *   }
56108 * }
56109 * </code>
56110 * </div>
56111 *
56112 * <div class="norender">
56113 * <code>
56114 * function mouseClicked() {
56115 *   ellipse(mouseX, mouseY, 5, 5);
56116 *   // prevent default
56117 *   return false;
56118 * }
56119 * </code>
56120 * </div>
56121 *
56122 * @alt
56123 * black 50x50 rect turns white with mouse click/press.
56124 * no image displayed
56125 *
56126 */
56127p5.prototype._onclick = function(e) {
56128  var context = this._isGlobal ? window : this;
56129  if (typeof context.mouseClicked === 'function') {
56130    var executeDefault = context.mouseClicked(e);
56131    if (executeDefault === false) {
56132      e.preventDefault();
56133    }
56134  }
56135};
56136
56137/**
56138 * The doubleClicked() function is executed every time a event
56139 * listener has detected a dblclick event which is a part of the
56140 * DOM L3 specification. The doubleClicked event is fired when a
56141 * pointing device button (usually a mouse's primary button)
56142 * is clicked twice on a single element. For more info on the
56143 * dblclick event refer to mozilla's documentation here:
56144 * https://developer.mozilla.org/en-US/docs/Web/Events/dblclick
56145 *
56146 * @method doubleClicked
56147 * @example
56148 * <div>
56149 * <code>
56150 * // Click within the image to change
56151 * // the value of the rectangle
56152 * // after the mouse has been double clicked
56153 *
56154 * var value = 0;
56155 * function draw() {
56156 *   fill(value);
56157 *   rect(25, 25, 50, 50);
56158 * }
56159 *
56160 * function doubleClicked() {
56161 *   if (value === 0) {
56162 *     value = 255;
56163 *   } else {
56164 *     value = 0;
56165 *   }
56166 * }
56167 * </code>
56168 * </div>
56169 *
56170 * <div class="norender">
56171 * <code>
56172 * function doubleClicked() {
56173 *   ellipse(mouseX, mouseY, 5, 5);
56174 *   // prevent default
56175 *   return false;
56176 * }
56177 * </code>
56178 * </div>
56179 *
56180 * @alt
56181 * black 50x50 rect turns white with mouse doubleClick/press.
56182 * no image displayed
56183 */
56184
56185p5.prototype._ondblclick = function(e) {
56186  var context = this._isGlobal ? window : this;
56187  if (typeof context.doubleClicked === 'function') {
56188    var executeDefault = context.doubleClicked(e);
56189    if (executeDefault === false) {
56190      e.preventDefault();
56191    }
56192  }
56193};
56194
56195/**
56196 * The function mouseWheel() is executed every time a vertical mouse wheel
56197 * event is detected either triggered by an actual mouse wheel or by a
56198 * touchpad.<br><br>
56199 * The event.delta property returns the amount the mouse wheel
56200 * have scrolled. The values can be positive or negative depending on the
56201 * scroll direction (on OS X with "natural" scrolling enabled, the signs
56202 * are inverted).<br><br>
56203 * Browsers may have different default behaviors attached to various
56204 * mouse events. To prevent any default behavior for this event, add
56205 * "return false" to the end of the method.<br><br>
56206 * Due to the current support of the "wheel" event on Safari, the function
56207 * may only work as expected if "return false" is included while using Safari.
56208 *
56209 * @method mouseWheel
56210 *
56211 * @example
56212 * <div>
56213 * <code>
56214 * var pos = 25;
56215 *
56216 * function draw() {
56217 *   background(237, 34, 93);
56218 *   fill(0);
56219 *   rect(25, pos, 50, 50);
56220 * }
56221 *
56222 * function mouseWheel(event) {
56223 *   print(event.delta);
56224 *   //move the square according to the vertical scroll amount
56225 *   pos += event.delta;
56226 *   //uncomment to block page scrolling
56227 *   //return false;
56228 * }
56229 * </code>
56230 * </div>
56231 *
56232 * @alt
56233 * black 50x50 rect moves up and down with vertical scroll. fuschia background
56234 *
56235 */
56236p5.prototype._onwheel = function(e) {
56237  var context = this._isGlobal ? window : this;
56238  if (typeof context.mouseWheel === 'function') {
56239    e.delta = e.deltaY;
56240    var executeDefault = context.mouseWheel(e);
56241    if (executeDefault === false) {
56242      e.preventDefault();
56243    }
56244  }
56245};
56246
56247module.exports = p5;
56248
56249},{"../core/constants":21,"../core/core":22}],40:[function(_dereq_,module,exports){
56250/**
56251 * @module Events
56252 * @submodule Touch
56253 * @for p5
56254 * @requires core
56255 */
56256
56257'use strict';
56258
56259var p5 = _dereq_('../core/core');
56260
56261/**
56262 * The system variable touches[] contains an array of the positions of all
56263 * current touch points, relative to (0, 0) of the canvas, and IDs identifying a
56264 * unique touch as it moves. Each element in the array is an object with x, y,
56265 * and id properties.
56266 *
56267 * The touches[] array is not supported on Safari and IE on touch-based
56268 * desktops (laptops).
56269 *
56270 * @property {Object[]} touches
56271 * @readOnly
56272 */
56273p5.prototype.touches = [];
56274
56275p5.prototype._updateTouchCoords = function(e) {
56276  if (this._curElement !== null) {
56277    var touches = [];
56278    for (var i = 0; i < e.touches.length; i++) {
56279      touches[i] = getTouchInfo(
56280        this._curElement.elt,
56281        this.width,
56282        this.height,
56283        e,
56284        i
56285      );
56286    }
56287    this._setProperty('touches', touches);
56288  }
56289};
56290
56291function getTouchInfo(canvas, w, h, e, i) {
56292  i = i || 0;
56293  var rect = canvas.getBoundingClientRect();
56294  var sx = canvas.scrollWidth / w;
56295  var sy = canvas.scrollHeight / h;
56296  var touch = e.touches[i] || e.changedTouches[i];
56297  return {
56298    x: (touch.clientX - rect.left) / sx,
56299    y: (touch.clientY - rect.top) / sy,
56300    winX: touch.clientX,
56301    winY: touch.clientY,
56302    id: touch.identifier
56303  };
56304}
56305
56306/**
56307 * The touchStarted() function is called once after every time a touch is
56308 * registered. If no touchStarted() function is defined, the mousePressed()
56309 * function will be called instead if it is defined.<br><br>
56310 * Browsers may have different default behaviors attached to various touch
56311 * events. To prevent any default behavior for this event, add "return false"
56312 * to the end of the method.
56313 *
56314 * @method touchStarted
56315 * @example
56316 * <div>
56317 * <code>
56318 * // Touch within the image to change
56319 * // the value of the rectangle
56320 *
56321 * var value = 0;
56322 * function draw() {
56323 *   fill(value);
56324 *   rect(25, 25, 50, 50);
56325 * }
56326 * function touchStarted() {
56327 *   if (value === 0) {
56328 *     value = 255;
56329 *   } else {
56330 *     value = 0;
56331 *   }
56332 * }
56333 * </code>
56334 * </div>
56335 *
56336 * <div class="norender">
56337 * <code>
56338 * function touchStarted() {
56339 *   ellipse(mouseX, mouseY, 5, 5);
56340 *   // prevent default
56341 *   return false;
56342 * }
56343 * </code>
56344 * </div>
56345 *
56346 * @alt
56347 * 50x50 black rect turns white with touch event.
56348 * no image displayed
56349 */
56350p5.prototype._ontouchstart = function(e) {
56351  var context = this._isGlobal ? window : this;
56352  var executeDefault;
56353  this._setProperty('mouseIsPressed', true);
56354  this._updateTouchCoords(e);
56355  this._updateNextMouseCoords(e);
56356  if (typeof context.touchStarted === 'function') {
56357    executeDefault = context.touchStarted(e);
56358    if (executeDefault === false) {
56359      e.preventDefault();
56360    }
56361  } else if (typeof context.mousePressed === 'function') {
56362    executeDefault = context.mousePressed(e);
56363    if (executeDefault === false) {
56364      e.preventDefault();
56365    }
56366  }
56367};
56368
56369/**
56370 * The touchMoved() function is called every time a touch move is registered.
56371 * If no touchMoved() function is defined, the mouseDragged() function will
56372 * be called instead if it is defined.<br><br>
56373 * Browsers may have different default behaviors attached to various touch
56374 * events. To prevent any default behavior for this event, add "return false"
56375 * to the end of the method.
56376 *
56377 * @method touchMoved
56378 * @example
56379 * <div>
56380 * <code>
56381 * // Move your finger across the page
56382 * // to change its value
56383 *
56384 * var value = 0;
56385 * function draw() {
56386 *   fill(value);
56387 *   rect(25, 25, 50, 50);
56388 * }
56389 * function touchMoved() {
56390 *   value = value + 5;
56391 *   if (value > 255) {
56392 *     value = 0;
56393 *   }
56394 * }
56395 * </code>
56396 * </div>
56397 *
56398 * <div class="norender">
56399 * <code>
56400 * function touchMoved() {
56401 *   ellipse(mouseX, mouseY, 5, 5);
56402 *   // prevent default
56403 *   return false;
56404 * }
56405 * </code>
56406 * </div>
56407 *
56408 * @alt
56409 * 50x50 black rect turns lighter with touch until white. resets
56410 * no image displayed
56411 *
56412 */
56413p5.prototype._ontouchmove = function(e) {
56414  var context = this._isGlobal ? window : this;
56415  var executeDefault;
56416  this._updateTouchCoords(e);
56417  this._updateNextMouseCoords(e);
56418  if (typeof context.touchMoved === 'function') {
56419    executeDefault = context.touchMoved(e);
56420    if (executeDefault === false) {
56421      e.preventDefault();
56422    }
56423  } else if (typeof context.mouseDragged === 'function') {
56424    executeDefault = context.mouseDragged(e);
56425    if (executeDefault === false) {
56426      e.preventDefault();
56427    }
56428  }
56429};
56430
56431/**
56432 * The touchEnded() function is called every time a touch ends. If no
56433 * touchEnded() function is defined, the mouseReleased() function will be
56434 * called instead if it is defined.<br><br>
56435 * Browsers may have different default behaviors attached to various touch
56436 * events. To prevent any default behavior for this event, add "return false"
56437 * to the end of the method.
56438 *
56439 * @method touchEnded
56440 * @example
56441 * <div>
56442 * <code>
56443 * // Release touch within the image to
56444 * // change the value of the rectangle
56445 *
56446 * var value = 0;
56447 * function draw() {
56448 *   fill(value);
56449 *   rect(25, 25, 50, 50);
56450 * }
56451 * function touchEnded() {
56452 *   if (value === 0) {
56453 *     value = 255;
56454 *   } else {
56455 *     value = 0;
56456 *   }
56457 * }
56458 * </code>
56459 * </div>
56460 *
56461 * <div class="norender">
56462 * <code>
56463 * function touchEnded() {
56464 *   ellipse(mouseX, mouseY, 5, 5);
56465 *   // prevent default
56466 *   return false;
56467 * }
56468 * </code>
56469 * </div>
56470 *
56471 * @alt
56472 * 50x50 black rect turns white with touch.
56473 * no image displayed
56474 *
56475 */
56476p5.prototype._ontouchend = function(e) {
56477  this._setProperty('mouseIsPressed', false);
56478  this._updateTouchCoords(e);
56479  this._updateNextMouseCoords(e);
56480  var context = this._isGlobal ? window : this;
56481  var executeDefault;
56482  if (typeof context.touchEnded === 'function') {
56483    executeDefault = context.touchEnded(e);
56484    if (executeDefault === false) {
56485      e.preventDefault();
56486    }
56487  } else if (typeof context.mouseReleased === 'function') {
56488    executeDefault = context.mouseReleased(e);
56489    if (executeDefault === false) {
56490      e.preventDefault();
56491    }
56492  }
56493};
56494
56495module.exports = p5;
56496
56497},{"../core/core":22}],41:[function(_dereq_,module,exports){
56498/*global ImageData:false */
56499
56500/**
56501 * This module defines the filters for use with image buffers.
56502 *
56503 * This module is basically a collection of functions stored in an object
56504 * as opposed to modules. The functions are destructive, modifying
56505 * the passed in canvas rather than creating a copy.
56506 *
56507 * Generally speaking users of this module will use the Filters.apply method
56508 * on a canvas to create an effect.
56509 *
56510 * A number of functions are borrowed/adapted from
56511 * http://www.html5rocks.com/en/tutorials/canvas/imagefilters/
56512 * or the java processing implementation.
56513 */
56514
56515'use strict';
56516
56517var Filters = {};
56518
56519/*
56520 * Helper functions
56521 */
56522
56523/**
56524 * Returns the pixel buffer for a canvas
56525 *
56526 * @private
56527 *
56528 * @param  {Canvas|ImageData} canvas the canvas to get pixels from
56529 * @return {Uint8ClampedArray}       a one-dimensional array containing
56530 *                                   the data in thc RGBA order, with integer
56531 *                                   values between 0 and 255
56532 */
56533Filters._toPixels = function(canvas) {
56534  if (canvas instanceof ImageData) {
56535    return canvas.data;
56536  } else {
56537    return canvas
56538      .getContext('2d')
56539      .getImageData(0, 0, canvas.width, canvas.height).data;
56540  }
56541};
56542
56543/**
56544 * Returns a 32 bit number containing ARGB data at ith pixel in the
56545 * 1D array containing pixels data.
56546 *
56547 * @private
56548 *
56549 * @param  {Uint8ClampedArray} data array returned by _toPixels()
56550 * @param  {Integer}           i    index of a 1D Image Array
56551 * @return {Integer}                32 bit integer value representing
56552 *                                  ARGB value.
56553 */
56554Filters._getARGB = function(data, i) {
56555  var offset = i * 4;
56556  return (
56557    ((data[offset + 3] << 24) & 0xff000000) |
56558    ((data[offset] << 16) & 0x00ff0000) |
56559    ((data[offset + 1] << 8) & 0x0000ff00) |
56560    (data[offset + 2] & 0x000000ff)
56561  );
56562};
56563
56564/**
56565 * Modifies pixels RGBA values to values contained in the data object.
56566 *
56567 * @private
56568 *
56569 * @param {Uint8ClampedArray} pixels array returned by _toPixels()
56570 * @param {Int32Array}        data   source 1D array where each value
56571 *                                   represents ARGB values
56572 */
56573Filters._setPixels = function(pixels, data) {
56574  var offset = 0;
56575  for (var i = 0, al = pixels.length; i < al; i++) {
56576    offset = i * 4;
56577    pixels[offset + 0] = (data[i] & 0x00ff0000) >>> 16;
56578    pixels[offset + 1] = (data[i] & 0x0000ff00) >>> 8;
56579    pixels[offset + 2] = data[i] & 0x000000ff;
56580    pixels[offset + 3] = (data[i] & 0xff000000) >>> 24;
56581  }
56582};
56583
56584/**
56585 * Returns the ImageData object for a canvas
56586 * https://developer.mozilla.org/en-US/docs/Web/API/ImageData
56587 *
56588 * @private
56589 *
56590 * @param  {Canvas|ImageData} canvas canvas to get image data from
56591 * @return {ImageData}               Holder of pixel data (and width and
56592 *                                   height) for a canvas
56593 */
56594Filters._toImageData = function(canvas) {
56595  if (canvas instanceof ImageData) {
56596    return canvas;
56597  } else {
56598    return canvas
56599      .getContext('2d')
56600      .getImageData(0, 0, canvas.width, canvas.height);
56601  }
56602};
56603
56604/**
56605 * Returns a blank ImageData object.
56606 *
56607 * @private
56608 *
56609 * @param  {Integer} width
56610 * @param  {Integer} height
56611 * @return {ImageData}
56612 */
56613Filters._createImageData = function(width, height) {
56614  Filters._tmpCanvas = document.createElement('canvas');
56615  Filters._tmpCtx = Filters._tmpCanvas.getContext('2d');
56616  return this._tmpCtx.createImageData(width, height);
56617};
56618
56619/**
56620 * Applys a filter function to a canvas.
56621 *
56622 * The difference between this and the actual filter functions defined below
56623 * is that the filter functions generally modify the pixel buffer but do
56624 * not actually put that data back to the canvas (where it would actually
56625 * update what is visible). By contrast this method does make the changes
56626 * actually visible in the canvas.
56627 *
56628 * The apply method is the method that callers of this module would generally
56629 * use. It has been separated from the actual filters to support an advanced
56630 * use case of creating a filter chain that executes without actually updating
56631 * the canvas in between everystep.
56632 *
56633 * @private
56634 * @param  {HTMLCanvasElement} canvas [description]
56635 * @param  {function(ImageData,Object)} func   [description]
56636 * @param  {Object} filterParam  [description]
56637 */
56638Filters.apply = function(canvas, func, filterParam) {
56639  var ctx = canvas.getContext('2d');
56640  var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
56641
56642  //Filters can either return a new ImageData object, or just modify
56643  //the one they received.
56644  var newImageData = func(imageData, filterParam);
56645  if (newImageData instanceof ImageData) {
56646    ctx.putImageData(newImageData, 0, 0, 0, 0, canvas.width, canvas.height);
56647  } else {
56648    ctx.putImageData(imageData, 0, 0, 0, 0, canvas.width, canvas.height);
56649  }
56650};
56651
56652/*
56653 * Filters
56654 */
56655
56656/**
56657 * Converts the image to black and white pixels depending if they are above or
56658 * below the threshold defined by the level parameter. The parameter must be
56659 * between 0.0 (black) and 1.0 (white). If no level is specified, 0.5 is used.
56660 *
56661 * Borrowed from http://www.html5rocks.com/en/tutorials/canvas/imagefilters/
56662 *
56663 * @private
56664 * @param  {Canvas} canvas
56665 * @param  {Float} level
56666 */
56667Filters.threshold = function(canvas, level) {
56668  var pixels = Filters._toPixels(canvas);
56669
56670  if (level === undefined) {
56671    level = 0.5;
56672  }
56673  var thresh = Math.floor(level * 255);
56674
56675  for (var i = 0; i < pixels.length; i += 4) {
56676    var r = pixels[i];
56677    var g = pixels[i + 1];
56678    var b = pixels[i + 2];
56679    var gray = 0.2126 * r + 0.7152 * g + 0.0722 * b;
56680    var val;
56681    if (gray >= thresh) {
56682      val = 255;
56683    } else {
56684      val = 0;
56685    }
56686    pixels[i] = pixels[i + 1] = pixels[i + 2] = val;
56687  }
56688};
56689
56690/**
56691 * Converts any colors in the image to grayscale equivalents.
56692 * No parameter is used.
56693 *
56694 * Borrowed from http://www.html5rocks.com/en/tutorials/canvas/imagefilters/
56695 *
56696 * @private
56697 * @param {Canvas} canvas
56698 */
56699Filters.gray = function(canvas) {
56700  var pixels = Filters._toPixels(canvas);
56701
56702  for (var i = 0; i < pixels.length; i += 4) {
56703    var r = pixels[i];
56704    var g = pixels[i + 1];
56705    var b = pixels[i + 2];
56706
56707    // CIE luminance for RGB
56708    var gray = 0.2126 * r + 0.7152 * g + 0.0722 * b;
56709    pixels[i] = pixels[i + 1] = pixels[i + 2] = gray;
56710  }
56711};
56712
56713/**
56714 * Sets the alpha channel to entirely opaque. No parameter is used.
56715 *
56716 * @private
56717 * @param {Canvas} canvas
56718 */
56719Filters.opaque = function(canvas) {
56720  var pixels = Filters._toPixels(canvas);
56721
56722  for (var i = 0; i < pixels.length; i += 4) {
56723    pixels[i + 3] = 255;
56724  }
56725
56726  return pixels;
56727};
56728
56729/**
56730 * Sets each pixel to its inverse value. No parameter is used.
56731 * @private
56732 * @param  {Canvas} canvas
56733 */
56734Filters.invert = function(canvas) {
56735  var pixels = Filters._toPixels(canvas);
56736
56737  for (var i = 0; i < pixels.length; i += 4) {
56738    pixels[i] = 255 - pixels[i];
56739    pixels[i + 1] = 255 - pixels[i + 1];
56740    pixels[i + 2] = 255 - pixels[i + 2];
56741  }
56742};
56743
56744/**
56745 * Limits each channel of the image to the number of colors specified as
56746 * the parameter. The parameter can be set to values between 2 and 255, but
56747 * results are most noticeable in the lower ranges.
56748 *
56749 * Adapted from java based processing implementation
56750 *
56751 * @private
56752 * @param  {Canvas} canvas
56753 * @param  {Integer} level
56754 */
56755Filters.posterize = function(canvas, level) {
56756  var pixels = Filters._toPixels(canvas);
56757
56758  if (level < 2 || level > 255) {
56759    throw new Error(
56760      'Level must be greater than 2 and less than 255 for posterize'
56761    );
56762  }
56763
56764  var levels1 = level - 1;
56765  for (var i = 0; i < pixels.length; i += 4) {
56766    var rlevel = pixels[i];
56767    var glevel = pixels[i + 1];
56768    var blevel = pixels[i + 2];
56769
56770    pixels[i] = ((rlevel * level) >> 8) * 255 / levels1;
56771    pixels[i + 1] = ((glevel * level) >> 8) * 255 / levels1;
56772    pixels[i + 2] = ((blevel * level) >> 8) * 255 / levels1;
56773  }
56774};
56775
56776/**
56777 * reduces the bright areas in an image
56778 * @private
56779 * @param  {Canvas} canvas
56780 *
56781 */
56782Filters.dilate = function(canvas) {
56783  var pixels = Filters._toPixels(canvas);
56784  var currIdx = 0;
56785  var maxIdx = pixels.length ? pixels.length / 4 : 0;
56786  var out = new Int32Array(maxIdx);
56787  var currRowIdx, maxRowIdx, colOrig, colOut, currLum;
56788
56789  var idxRight, idxLeft, idxUp, idxDown;
56790  var colRight, colLeft, colUp, colDown;
56791  var lumRight, lumLeft, lumUp, lumDown;
56792
56793  while (currIdx < maxIdx) {
56794    currRowIdx = currIdx;
56795    maxRowIdx = currIdx + canvas.width;
56796    while (currIdx < maxRowIdx) {
56797      colOrig = colOut = Filters._getARGB(pixels, currIdx);
56798      idxLeft = currIdx - 1;
56799      idxRight = currIdx + 1;
56800      idxUp = currIdx - canvas.width;
56801      idxDown = currIdx + canvas.width;
56802
56803      if (idxLeft < currRowIdx) {
56804        idxLeft = currIdx;
56805      }
56806      if (idxRight >= maxRowIdx) {
56807        idxRight = currIdx;
56808      }
56809      if (idxUp < 0) {
56810        idxUp = 0;
56811      }
56812      if (idxDown >= maxIdx) {
56813        idxDown = currIdx;
56814      }
56815      colUp = Filters._getARGB(pixels, idxUp);
56816      colLeft = Filters._getARGB(pixels, idxLeft);
56817      colDown = Filters._getARGB(pixels, idxDown);
56818      colRight = Filters._getARGB(pixels, idxRight);
56819
56820      //compute luminance
56821      currLum =
56822        77 * ((colOrig >> 16) & 0xff) +
56823        151 * ((colOrig >> 8) & 0xff) +
56824        28 * (colOrig & 0xff);
56825      lumLeft =
56826        77 * ((colLeft >> 16) & 0xff) +
56827        151 * ((colLeft >> 8) & 0xff) +
56828        28 * (colLeft & 0xff);
56829      lumRight =
56830        77 * ((colRight >>
56830 16) & 0xff) +
56831        151 * ((colRight >> 8) & 0xff) +
56832        28 * (colRight & 0xff);
56833      lumUp =
56834        77 * ((colUp >> 16) & 0xff) +
56835        151 * ((colUp >> 8) & 0xff) +
56836        28 * (colUp & 0xff);
56837      lumDown =
56838        77 * ((colDown >> 16) & 0xff) +
56839        151 * ((colDown >> 8) & 0xff) +
56840        28 * (colDown & 0xff);
56841
56842      if (lumLeft > currLum) {
56843        colOut = colLeft;
56844        currLum = lumLeft;
56845      }
56846      if (lumRight > currLum) {
56847        colOut = colRight;
56848        currLum = lumRight;
56849      }
56850      if (lumUp > currLum) {
56851        colOut = colUp;
56852        currLum = lumUp;
56853      }
56854      if (lumDown > currLum) {
56855        colOut = colDown;
56856        currLum = lumDown;
56857      }
56858      out[currIdx++] = colOut;
56859    }
56860  }
56861  Filters._setPixels(pixels, out);
56862};
56863
56864/**
56865 * increases the bright areas in an image
56866 * @private
56867 * @param  {Canvas} canvas
56868 *
56869 */
56870Filters.erode = function(canvas) {
56871  var pixels = Filters._toPixels(canvas);
56872  var currIdx = 0;
56873  var maxIdx = pixels.length ? pixels.length / 4 : 0;
56874  var out = new Int32Array(maxIdx);
56875  var currRowIdx, maxRowIdx, colOrig, colOut, currLum;
56876  var idxRight, idxLeft, idxUp, idxDown;
56877  var colRight, colLeft, colUp, colDown;
56878  var lumRight, lumLeft, lumUp, lumDown;
56879
56880  while (currIdx < maxIdx) {
56881    currRowIdx = currIdx;
56882    maxRowIdx = currIdx + canvas.width;
56883    while (currIdx < maxRowIdx) {
56884      colOrig = colOut = Filters._getARGB(pixels, currIdx);
56885      idxLeft = currIdx - 1;
56886      idxRight = currIdx + 1;
56887      idxUp = currIdx - canvas.width;
56888      idxDown = currIdx + canvas.width;
56889
56890      if (idxLeft < currRowIdx) {
56891        idxLeft = currIdx;
56892      }
56893      if (idxRight >= maxRowIdx) {
56894        idxRight = currIdx;
56895      }
56896      if (idxUp < 0) {
56897        idxUp = 0;
56898      }
56899      if (idxDown >= maxIdx) {
56900        idxDown = currIdx;
56901      }
56902      colUp = Filters._getARGB(pixels, idxUp);
56903      colLeft = Filters._getARGB(pixels, idxLeft);
56904      colDown = Filters._getARGB(pixels, idxDown);
56905      colRight = Filters._getARGB(pixels, idxRight);
56906
56907      //compute luminance
56908      currLum =
56909        77 * ((colOrig >> 16) & 0xff) +
56910        151 * ((colOrig >> 8) & 0xff) +
56911        28 * (colOrig & 0xff);
56912      lumLeft =
56913        77 * ((colLeft >> 16) & 0xff) +
56914        151 * ((colLeft >> 8) & 0xff) +
56915        28 * (colLeft & 0xff);
56916      lumRight =
56917        77 * ((colRight >>
56917 16) & 0xff) +
56918        151 * ((colRight >> 8) & 0xff) +
56919        28 * (colRight & 0xff);
56920      lumUp =
56921        77 * ((colUp >> 16) & 0xff) +
56922        151 * ((colUp >> 8) & 0xff) +
56923        28 * (colUp & 0xff);
56924      lumDown =
56925        77 * ((colDown >> 16) & 0xff) +
56926        151 * ((colDown >> 8) & 0xff) +
56927        28 * (colDown & 0xff);
56928
56929      if (lumLeft < currLum) {
56930        colOut = colLeft;
56931        currLum = lumLeft;
56932      }
56933      if (lumRight < currLum) {
56934        colOut = colRight;
56935        currLum = lumRight;
56936      }
56937      if (lumUp < currLum) {
56938        colOut = colUp;
56939        currLum = lumUp;
56940      }
56941      if (lumDown < currLum) {
56942        colOut = colDown;
56943        currLum = lumDown;
56944      }
56945
56946      out[currIdx++] = colOut;
56947    }
56948  }
56949  Filters._setPixels(pixels, out);
56950};
56951
56952// BLUR
56953
56954// internal kernel stuff for the gaussian blur filter
56955var blurRadius;
56956var blurKernelSize;
56957var blurKernel;
56958var blurMult;
56959
56960/*
56961 * Port of https://github.com/processing/processing/blob/
56962 * master/core/src/processing/core/PImage.java#L1250
56963 *
56964 * Optimized code for building the blur kernel.
56965 * further optimized blur code (approx. 15% for radius=20)
56966 * bigger speed gains for larger radii (~30%)
56967 * added support for various image types (ALPHA, RGB, ARGB)
56968 * [toxi 050728]
56969 */
56970function buildBlurKernel(r) {
56971  var radius = (r * 3.5) | 0;
56972  radius = radius < 1 ? 1 : radius < 248 ? radius : 248;
56973
56974  if (blurRadius !== radius) {
56975    blurRadius = radius;
56976    blurKernelSize = (1 + blurRadius) << 1;
56977    blurKernel = new Int32Array(blurKernelSize);
56978    blurMult = new Array(blurKernelSize);
56979    for (var l = 0; l < blurKernelSize; l++) {
56980      blurMult[l] = new Int32Array(256);
56981    }
56982
56983    var bk, bki;
56984    var bm, bmi;
56985
56986    for (var i = 1, radiusi = radius - 1; i < radius; i++) {
56987      blurKernel[radius + i] = blurKernel[radiusi] = bki = radiusi * radiusi;
56988      bm = blurMult[radius + i];
56989      bmi = blurMult[radiusi--];
56990      for (var j = 0; j < 256; j++) {
56991        bm[j] = bmi[j] = bki * j;
56992      }
56993    }
56994    bk = blurKernel[radius] = radius * radius;
56995    bm = blurMult[radius];
56996
56997    for (var k = 0; k < 256; k++) {
56998      bm[k] = bk * k;
56999    }
57000  }
57001}
57002
57003// Port of https://github.com/processing/processing/blob/
57004// master/core/src/processing/core/PImage.java#L1433
57005function blurARGB(canvas, radius) {
57006  var pixels = Filters._toPixels(canvas);
57007  var width = canvas.width;
57008  var height = canvas.height;
57009  var numPackedPixels = width * height;
57010  var argb = new Int32Array(numPackedPixels);
57011  for (var j = 0; j < numPackedPixels; j++) {
57012    argb[j] = Filters._getARGB(pixels, j);
57013  }
57014  var sum, cr, cg, cb, ca;
57015  var read, ri, ym, ymi, bk0;
57016  var a2 = new Int32Array(numPackedPixels);
57017  var r2 = new Int32Array(numPackedPixels);
57018  var g2 = new Int32Array(numPackedPixels);
57019  var b2 = new Int32Array(numPackedPixels);
57020  var yi = 0;
57021  buildBlurKernel(radius);
57022  var x, y, i;
57023  var bm;
57024  for (y = 0; y < height; y++) {
57025    for (x = 0; x < width; x++) {
57026      cb = cg = cr = ca = sum = 0;
57027      read = x - blurRadius;
57028      if (read < 0) {
57029        bk0 = -read;
57030        read = 0;
57031      } else {
57032        if (read >= width) {
57033          break;
57034        }
57035        bk0 = 0;
57036      }
57037      for (i = bk0; i < blurKernelSize; i++) {
57038        if (read >= width) {
57039          break;
57040        }
57041        var c = argb[read + yi];
57042        bm = blurMult[i];
57043        ca += bm[(c & -16777216) >>> 24];
57044        cr += bm[(c & 16711680) >> 16];
57045        cg += bm[(c & 65280) >> 8];
57046        cb += bm[c & 255];
57047        sum += blurKernel[i];
57048        read++;
57049      }
57050      ri = yi + x;
57051      a2[ri] = ca / sum;
57052      r2[ri] = cr / sum;
57053      g2[ri] = cg / sum;
57054      b2[ri] = cb / sum;
57055    }
57056    yi += width;
57057  }
57058  yi = 0;
57059  ym = -blurRadius;
57060  ymi = ym * width;
57061  for (y = 0; y < height; y++) {
57062    for (x = 0; x < width; x++) {
57063      cb = cg = cr = ca = sum = 0;
57064      if (ym < 0) {
57065        bk0 = ri = -ym;
57066        read = x;
57067      } else {
57068        if (ym >= height) {
57069          break;
57070        }
57071        bk0 = 0;
57072        ri = ym;
57073        read = x + ymi;
57074      }
57075      for (i = bk0; i < blurKernelSize; i++) {
57076        if (ri >= height) {
57077          break;
57078        }
57079        bm = blurMult[i];
57080        ca += bm[a2[read]];
57081        cr += bm[r2[read]];
57082        cg += bm[g2[read]];
57083        cb += bm[b2[read]];
57084        sum += blurKernel[i];
57085        ri++;
57086        read += width;
57087      }
57088      argb[x + yi] =
57089        ((ca / sum) << 24) |
57090        ((cr / sum) << 16) |
57091        ((cg / sum) << 8) |
57092        (cb / sum);
57093    }
57094    yi += width;
57095    ymi += width;
57096    ym++;
57097  }
57098  Filters._setPixels(pixels, argb);
57099}
57100
57101Filters.blur = function(canvas, radius) {
57102  blurARGB(canvas, radius);
57103};
57104
57105module.exports = Filters;
57106
57107},{}],42:[function(_dereq_,module,exports){
57108/**
57109 * @module Image
57110 * @submodule Image
57111 * @for p5
57112 * @requires core
57113 */
57114
57115/**
57116 * This module defines the p5 methods for the p5.Image class
57117 * for drawing images to the main display canvas.
57118 */
57119'use strict';
57120
57121var p5 = _dereq_('../core/core'); // This is not global, but JSHint is not aware that // this module is implicitly enclosed with Browserify: this overrides the // redefined-global error and permits using the name "frames" for the array // of saved animation frames.
57122
57123/* global frames:true */ var frames = [];
57124
57125/**
57126 * Creates a new p5.Image (the datatype for storing images). This provides a
57127 * fresh buffer of pixels to play with. Set the size of the buffer with the
57128 * width and height parameters.
57129 * <br><br>
57130 * .pixels gives access to an array containing the values for all the pixels
57131 * in the display window.
57132 * These values are numbers. This array is the size (including an appropriate
57133 * factor for the pixelDensity) of the display window x4,
57134 * representing the R, G, B, A values in order for each pixel, moving from
57135 * left to right across each row, then down each column. See .pixels for
57136 * more info. It may also be simpler to use set() or get().
57137 * <br><br>
57138 * Before accessing the pixels of an image, the data must loaded with the
57139 * loadPixels() function. After the array data has been modified, the
57140 * updatePixels() function must be run to update the changes.
57141 *
57142 * @method createImage
57143 * @param  {Integer} width  width in pixels
57144 * @param  {Integer} height height in pixels
57145 * @return {p5.Image}       the p5.Image object
57146 * @example
57147 * <div>
57148 * <code>
57149 * var img = createImage(66, 66);
57150 * img.loadPixels();
57151 * for (var i = 0; i < img.width; i++) {
57152 *   for (var j = 0; j < img.height; j++) {
57153 *     img.set(i, j, color(0, 90, 102));
57154 *   }
57155 * }
57156 * img.updatePixels();
57157 * image(img, 17, 17);
57158 * </code>
57159 * </div>
57160 *
57161 * <div>
57162 * <code>
57163 * var img = createImage(66, 66);
57164 * img.loadPixels();
57165 * for (var i = 0; i < img.width; i++) {
57166 *   for (var j = 0; j < img.height; j++) {
57167 *     img.set(i, j, color(0, 90, 102, (i % img.width) * 2));
57168 *   }
57169 * }
57170 * img.updatePixels();
57171 * image(img, 17, 17);
57172 * image(img, 34, 34);
57173 * </code>
57174 * </div>
57175 *
57176 * <div>
57177 * <code>
57178 * var pink = color(255, 102, 204);
57179 * var img = createImage(66, 66);
57180 * img.loadPixels();
57181 * var d = pixelDensity();
57182 * var halfImage = 4 * (width * d) * (height / 2 * d);
57183 * for (var i = 0; i < halfImage; i += 4) {
57184 *   img.pixels[i] = red(pink);
57185 *   img.pixels[i + 1] = green(pink);
57186 *   img.pixels[i + 2] = blue(pink);
57187 *   img.pixels[i + 3] = alpha(pink);
57188 * }
57189 * img.updatePixels();
57190 * image(img, 17, 17);
57191 * </code>
57192 * </div>
57193 *
57194 * @alt
57195 * 66x66 dark turquoise rect in center of canvas.
57196 * 2 gradated dark turquoise rects fade left. 1 center 1 bottom right of canvas
57197 * no image displayed
57198 *
57199 */
57200p5.prototype.createImage = function(width, height) {
57201  p5._validateParameters('createImage', arguments);
57202  return new p5.Image(width, height);
57203};
57204
57205/**
57206 *  Save the current canvas as an image. In Safari, this will open the
57207 *  image in the window and the user must provide their own
57208 *  filename on save-as. Other browsers will either save the
57209 *  file immediately, or prompt the user with a dialogue window.
57210 *
57211 *  @method saveCanvas
57212 *  @param  {p5.Element|HTMLCanvasElement} selectedCanvas   a variable
57213 *                                  representing a specific html5 canvas (optional)
57214 *  @param  {String} [filename]
57215 *  @param  {String} [extension]      'jpg' or 'png'
57216 *
57217 *  @example
57218 * <div class='norender notest'><code>
57219 * function setup() {
57220 *   var c = createCanvas(100, 100);
57221 *   background(255, 0, 0);
57222 *   saveCanvas(c, 'myCanvas', 'jpg');
57223 * }
57224 * </code></div>
57225 * <div class='norender notest'><code>
57226 * // note that this example has the same result as above
57227 * // if no canvas is specified, defaults to main canvas
57228 * function setup() {
57229 *   var c = createCanvas(100, 100);
57230 *   background(255, 0, 0);
57231 *   saveCanvas('myCanvas', 'jpg');
57232 *
57233 *   // all of the following are valid
57234 *   saveCanvas(c, 'myCanvas', 'jpg');
57235 *   saveCanvas(c, 'myCanvas.jpg');
57236 *   saveCanvas(c, 'myCanvas');
57237 *   saveCanvas(c);
57238 *   saveCanvas('myCanvas', 'png');
57239 *   saveCanvas('myCanvas');
57240 *   saveCanvas();
57241 * }
57242 * </code></div>
57243 *
57244 * @alt
57245 * no image displayed
57246 * no image displayed
57247 * no image displayed
57248 */
57249/**
57250 *  @method saveCanvas
57251 *  @param  {String} [filename]
57252 *  @param  {String} [extension]
57253 */
57254p5.prototype.saveCanvas = function() {
57255  p5._validateParameters('saveCanvas', arguments);
57256
57257  // copy arguments to array
57258  var args = [].slice.call(arguments);
57259  var htmlCanvas, filename, extension;
57260
57261  if (arguments[0] instanceof HTMLCanvasElement) {
57262    htmlCanvas = arguments[0];
57263    args.shift();
57264  } else if (arguments[0] instanceof p5.Element) {
57265    htmlCanvas = arguments[0].elt;
57266    args.shift();
57267  } else {
57268    htmlCanvas = this._curElement && this._curElement.elt;
57269  }
57270
57271  if (args.length >= 1) {
57272    filename = args[0];
57273  }
57274  if (args.length >= 2) {
57275    extension = args[1];
57276  }
57277
57278  extension =
57279    extension ||
57280    p5.prototype._checkFileExtension(filename, extension)[1] ||
57281    'png';
57282
57283  var mimeType;
57284  switch (extension) {
57285    default:
57286      //case 'png':
57287      mimeType = 'image/png';
57288      break;
57289    case 'jpeg':
57290    case 'jpg':
57291      mimeType = 'image/jpeg';
57292      break;
57293  }
57294
57295  htmlCanvas.toBlob(function(blob) {
57296    p5.prototype.downloadFile(blob, filename, extension);
57297  }, mimeType);
57298};
57299
57300/**
57301 *  Capture a sequence of frames that can be used to create a movie.
57302 *  Accepts a callback. For example, you may wish to send the frames
57303 *  to a server where they can be stored or converted into a movie.
57304 *  If no callback is provided, the browser will pop up save dialogues in an
57305 *  attempt to download all of the images that have just been created. With the
57306 *  callback provided the image data isn't saved by default but instead passed
57307 *  as an argument to the callback function as an array of objects, with the
57308 *  size of array equal to the total number of frames.
57309 *
57310 *  Note that saveFrames() will only save the first 15 frames of an animation.
57311 *  To export longer animations, you might look into a library like
57312 *  <a href="https://github.com/spite/ccapture.js/">ccapture.js</a>.
57313 *
57314 *  @method saveFrames
57315 *  @param  {String}   filename
57316 *  @param  {String}   extension 'jpg' or 'png'
57317 *  @param  {Number}   duration  Duration in seconds to save the frames for.
57318 *  @param  {Number}   framerate  Framerate to save the frames in.
57319 *  @param  {function(Array)} [callback] A callback function that will be executed
57320                                  to handle the image data. This function
57321                                  should accept an array as argument. The
57322                                  array will contain the specified number of
57323                                  frames of objects. Each object has three
57324                                  properties: imageData - an
57325                                  image/octet-stream, filename and extension.
57326 *  @example
57327 *  <div><code>
57328 * function draw() {
57329 *   background(mouseX);
57330 * }
57331 *
57332 * function mousePressed() {
57333 *   saveFrames('out', 'png', 1, 25, function(data) {
57334 *     print(data);
57335 *   });
57336 * }
57337</code></div>
57338 *
57339 * @alt
57340 * canvas background goes from light to dark with mouse x.
57341 *
57342 */
57343p5.prototype.saveFrames = function(fName, ext, _duration, _fps, callback) {
57344  p5._validateParameters('saveFrames', arguments);
57345  var duration = _duration || 3;
57346  duration = p5.prototype.constrain(duration, 0, 15);
57347  duration = duration * 1000;
57348  var fps = _fps || 15;
57349  fps = p5.prototype.constrain(fps, 0, 22);
57350  var count = 0;
57351
57352  var makeFrame = p5.prototype._makeFrame;
57353  var cnv = this._curElement.elt;
57354  var frameFactory = setInterval(function() {
57355    makeFrame(fName + count, ext, cnv);
57356    count++;
57357  }, 1000 / fps);
57358
57359  setTimeout(function() {
57360    clearInterval(frameFactory);
57361    if (callback) {
57362      callback(frames);
57363    } else {
57364      for (var i = 0; i < frames.length; i++) {
57365        var f = frames[i];
57366        p5.prototype.downloadFile(f.imageData, f.filename, f.ext);
57367      }
57368    }
57369    frames = []; // clear frames
57370  }, duration + 0.01);
57371};
57372
57373p5.prototype._makeFrame = function(filename, extension, _cnv) {
57374  var cnv;
57375  if (this) {
57376    cnv = this._curElement.elt;
57377  } else {
57378    cnv = _cnv;
57379  }
57380  var mimeType;
57381  if (!extension) {
57382    extension = 'png';
57383    mimeType = 'image/png';
57384  } else {
57385    switch (extension.toLowerCase()) {
57386      case 'png':
57387        mimeType = 'image/png';
57388        break;
57389      case 'jpeg':
57390        mimeType = 'image/jpeg';
57391        break;
57392      case 'jpg':
57393        mimeType = 'image/jpeg';
57394        break;
57395      default:
57396        mimeType = 'image/png';
57397        break;
57398    }
57399  }
57400  var downloadMime = 'image/octet-stream';
57401  var imageData = cnv.toDataURL(mimeType);
57402  imageData = imageData.replace(mimeType, downloadMime);
57403
57404  var thisFrame = {};
57405  thisFrame.imageData = imageData;
57406  thisFrame.filename = filename;
57407  thisFrame.ext = extension;
57408  frames.push(thisFrame);
57409};
57410
57411module.exports = p5;
57412
57413},{"../core/core":22}],43:[function(_dereq_,module,exports){
57414/**
57415 * @module Image
57416 * @submodule Loading & Displaying
57417 * @for p5
57418 * @requires core
57419 */
57420
57421'use strict';
57422
57423var p5 = _dereq_('../core/core');
57424var Filters = _dereq_('./filters');
57425var canvas = _dereq_('../core/canvas');
57426var constants = _dereq_('../core/constants');
57427
57428_dereq_('../core/error_helpers');
57429
57430/**
57431 * Loads an image from a path and creates a p5.Image from it.
57432 * <br><br>
57433 * The image may not be immediately available for rendering
57434 * If you want to ensure that the image is ready before doing
57435 * anything with it, place the loadImage() call in preload().
57436 * You may also supply a callback function to handle the image when it's ready.
57437 * <br><br>
57438 * The path to the image should be relative to the HTML file
57439 * that links in your sketch. Loading an image from a URL or other
57440 * remote location may be blocked due to your browser's built-in
57441 * security.
57442 *
57443 * @method loadImage
57444 * @param  {String} path Path of the image to be loaded
57445 * @param  {function(p5.Image)} [successCallback] Function to be called once
57446 *                                the image is loaded. Will be passed the
57447 *                                p5.Image.
57448 * @param  {function(Event)}    [failureCallback] called with event error if
57449 *                                the image fails to load.
57450 * @return {p5.Image}             the p5.Image object
57451 * @example
57452 * <div>
57453 * <code>
57454 * var img;
57455 * function preload() {
57456 *   img = loadImage('assets/laDefense.jpg');
57457 * }
57458 * function setup() {
57459 *   image(img, 0, 0);
57460 * }
57461 * </code>
57462 * </div>
57463 * <div>
57464 * <code>
57465 * function setup() {
57466 *   // here we use a callback to display the image after loading
57467 *   loadImage('assets/laDefense.jpg', function(img) {
57468 *     image(img, 0, 0);
57469 *   });
57470 * }
57471 * </code>
57472 * </div>
57473 *
57474 * @alt
57475 * image of the underside of a white umbrella and grided ceililng above
57476 * image of the underside of a white umbrella and grided ceililng above
57477 *
57478 */
57479p5.prototype.loadImage = function(path, successCallback, failureCallback) {
57480  p5._validateParameters('loadImage', arguments);
57481  var img = new Image();
57482  var pImg = new p5.Image(1, 1, this);
57483
57484  var self = this;
57485  img.onload = function() {
57486    pImg.width = pImg.canvas.width = img.width;
57487    pImg.height = pImg.canvas.height = img.height;
57488
57489    // Draw the image into the backing canvas of the p5.Image
57490    pImg.drawingContext.drawImage(img, 0, 0);
57491    pImg.modified = true;
57492
57493    if (typeof successCallback === 'function') {
57494      successCallback(pImg);
57495    }
57496
57497    self._decrementPreload();
57498  };
57499  img.onerror = function(e) {
57500    p5._friendlyFileLoadError(0, img.src);
57501    if (typeof failureCallback === 'function') {
57502      failureCallback(e);
57503    }
57504  };
57505
57506  //set crossOrigin in case image is served which CORS headers
57507  //this will let us draw to canvas without tainting it.
57508  //see https://developer.mozilla.org/en-US/docs/HTML/CORS_Enabled_Image
57509  // When using data-uris the file will be loaded locally
57510  // so we don't need to worry about crossOrigin with base64 file types
57511  if (path.indexOf('data:image/') !== 0) {
57512    img.crossOrigin = 'Anonymous';
57513  }
57514
57515  //start loading the image
57516  img.src = path;
57517
57518  return pImg;
57519};
57520
57521/**
57522 * Validates clipping params. Per drawImage spec sWidth and sHight cannot be
57523 * negative or greater than image intrinsic width and height
57524 * @private
57525 * @param {Number} sVal
57526 * @param {Number} iVal
57527 * @returns {Number}
57528 * @private
57529 */
57530function _sAssign(sVal, iVal) {
57531  if (sVal > 0 && sVal < iVal) {
57532    return sVal;
57533  } else {
57534    return iVal;
57535  }
57536}
57537
57538/**
57539 * Draw an image to the p5.js canvas.
57540 *
57541 * This function can be used with different numbers of parameters. The
57542 * simplest use requires only three parameters: img, x, and y—where (x, y) is
57543 * the position of the image. Two more parameters can optionally be added to
57544 * specify the width and height of the image.
57545 *
57546 * This function can also be used with all eight Number parameters. To
57547 * differentiate between all these parameters, p5.js uses the language of
57548 * "destination rectangle" (which corresponds to "dx", "dy", etc.) and "source
57549 * image" (which corresponds to "sx", "sy", etc.) below. Specifying the
57550 * "source image" dimensions can be useful when you want to display a
57551 * subsection of the source image instead of the whole thing. Here's a diagram
57552 * to explain further:
57553 * <img src="assets/drawImage.png"></img>
57554 *
57555 * @method image
57556 * @param  {p5.Image|p5.Element} img    the image to display
57557 * @param  {Number}   x     the x-coordinate of the top-left corner of the image
57558 * @param  {Number}   y     the y-coordinate of the top-left corner of the image
57559 * @param  {Number}   [width]  the width to draw the image
57560 * @param  {Number}   [height] the height to draw the image
57561 * @example
57562 * <div>
57563 * <code>
57564 * var img;
57565 * function preload() {
57566 *   img = loadImage('assets/laDefense.jpg');
57567 * }
57568 * function setup() {
57569 *   // Top-left corner of the img is at (0, 0)
57570 *   // Width and height are the img's original width and height
57571 *   image(img, 0, 0);
57572 * }
57573 * </code>
57574 * </div>
57575 * <div>
57576 * <code>
57577 * var img;
57578 * function preload() {
57579 *   img = loadImage('assets/laDefense.jpg');
57580 * }
57581 * function setup() {
57582 *   background(50);
57583 *   // Top-left corner of the img is at (10, 10)
57584 *   // Width and height are 50 x 50
57585 *   image(img, 10, 10, 50, 50);
57586 * }
57587 * </code>
57588 * </div>
57589 * <div>
57590 * <code>
57591 * function setup() {
57592 *   // Here, we use a callback to display the image after loading
57593 *   loadImage('assets/laDefense.jpg', function(img) {
57594 *     image(img, 0, 0);
57595 *   });
57596 * }
57597 * </code>
57598 * </div>
57599 * <div>
57600 * <code>
57601 * var img;
57602 * function preload() {
57603 *   img = loadImage('assets/gradient.png');
57604 * }
57605 * function setup() {
57606 *   // 1. Background image
57607 *   // Top-left corner of the img is at (0, 0)
57608 *   // Width and height are the img's original width and height, 100 x 100
57609 *   image(img, 0, 0);
57610 *   // 2. Top right image
57611 *   // Top-left corner of destination rectangle is at (50, 0)
57612 *   // Destination rectangle width and height are 40 x 20
57613 *   // The next parameters are relative to the source image:
57614 *   // - Starting at position (50, 50) on the source image, capture a 50 x 50
57615 *   // subsection
57616 *   // - Draw this subsection to fill the dimensions of the destination rectangle
57617 *   image(img, 50, 0, 40, 20, 50, 50, 50, 50);
57618 * }
57619 * </code>
57620 * </div>
57621 * @alt
57622 * image of the underside of a white umbrella and gridded ceiling above
57623 * image of the underside of a white umbrella and gridded ceiling above
57624 *
57625 */
57626/**
57627 * @method image
57628 * @param  {p5.Image|p5.Element} img
57629 * @param  {Number}   dx     the x-coordinate of the destination
57630 *                           rectangle in which to draw the source image
57631 * @param  {Number}   dy     the y-coordinate of the destination
57632 *                           rectangle in which to draw the source image
57633 * @param  {Number}   dWidth  the width of the destination rectangle
57634 * @param  {Number}   dHeight the height of the destination rectangle
57635 * @param  {Number}   sx     the x-coordinate of the subsection of the source
57636 * image to draw into the destination rectangle
57637 * @param  {Number}   sy     the y-coordinate of the subsection of the source
57638 * image to draw into the destination rectangle
57639 * @param {Number}    [sWidth] the width of the subsection of the
57640 *                           source image to draw into the destination
57641 *                           rectangle
57642 * @param {Number}    [sHeight] the height of the subsection of the
57643 *                            source image to draw into the destination rectangle
57644 */
57645p5.prototype.image = function(
57646  img,
57647  dx,
57648  dy,
57649  dWidth,
57650  dHeight,
57651  sx,
57652  sy,
57653  sWidth,
57654  sHeight
57655) {
57656  // set defaults per spec: https://goo.gl/3ykfOq
57657
57658  p5._validateParameters('image', arguments);
57659
57660  var defW = img.width;
57661  var defH = img.height;
57662
57663  if (img.elt && img.elt.videoWidth && !img.canvas) {
57664    // video no canvas
57665    defW = img.elt.videoWidth;
57666    defH = img.elt.videoHeight;
57667  }
57668
57669  var _dx = dx;
57670  var _dy = dy;
57671  var _dw = dWidth || defW;
57672  var _dh = dHeight || defH;
57673  var _sx = sx || 0;
57674  var _sy = sy || 0;
57675  var _sw = sWidth || defW;
57676  var _sh = sHeight || defH;
57677
57678  _sw = _sAssign(_sw, defW);
57679  _sh = _sAssign(_sh, defH);
57680
57681  // This part needs cleanup and unit tests
57682  // see issues https://github.com/processing/p5.js/issues/1741
57683  // and https://github.com/processing/p5.js/issues/1673
57684  var pd = 1;
57685
57686  if (img.elt && !img.canvas && img.elt.style.width) {
57687    //if img is video and img.elt.size() has been used and
57688    //no width passed to image()
57689    if (img.elt.videoWidth && !dWidth) {
57690      pd = img.elt.videoWidth;
57691    } else {
57692      //all other cases
57693      pd = img.elt.width;
57694    }
57695    pd /= parseInt(img.elt.style.width, 10);
57696  }
57697
57698  _sx *= pd;
57699  _sy *= pd;
57700  _sh *= pd;
57701  _sw *= pd;
57702
57703  var vals = canvas.modeAdjust(_dx, _dy, _dw, _dh, this._renderer._imageMode);
57704
57705  // tint the image if there is a tint
57706  this._renderer.image(img, _sx, _sy, _sw, _sh, vals.x, vals.y, vals.w, vals.h);
57707};
57708
57709/**
57710 * Sets the fill value for displaying images. Images can be tinted to
57711 * specified colors or made transparent by including an alpha value.
57712 * <br><br>
57713 * To apply transparency to an image without affecting its color, use
57714 * white as the tint color and specify an alpha value. For instance,
57715 * tint(255, 128) will make an image 50% transparent (assuming the default
57716 * alpha range of 0-255, which can be changed with colorMode()).
57717 * <br><br>
57718 * The value for the gray parameter must be less than or equal to the current
57719 * maximum value as specified by colorMode(). The default maximum value is
57720 * 255.
57721 *
57722 *
57723 * @method tint
57724 * @param  {Number}        v1      red or hue value relative to
57725 *                                 the current color range
57726 * @param  {Number}        v2      green or saturation value
57727 *                                 relative to the current color range
57728 * @param  {Number}        v3      blue or brightness value
57729 *                                 relative to the current color range
57730 * @param  {Number}        [alpha]
57731 *
57732 * @example
57733 * <div>
57734 * <code>
57735 * var img;
57736 * function preload() {
57737 *   img = loadImage('assets/laDefense.jpg');
57738 * }
57739 * function setup() {
57740 *   image(img, 0, 0);
57741 *   tint(0, 153, 204); // Tint blue
57742 *   image(img, 50, 0);
57743 * }
57744 * </code>
57745 * </div>
57746 *
57747 * <div>
57748 * <code>
57749 * var img;
57750 * function preload() {
57751 *   img = loadImage('assets/laDefense.jpg');
57752 * }
57753 * function setup() {
57754 *   image(img, 0, 0);
57755 *   tint(0, 153, 204, 126); // Tint blue and set transparency
57756 *   image(img, 50, 0);
57757 * }
57758 * </code>
57759 * </div>
57760 *
57761 * <div>
57762 * <code>
57763 * var img;
57764 * function preload() {
57765 *   img = loadImage('assets/laDefense.jpg');
57766 * }
57767 * function setup() {
57768 *   image(img, 0, 0);
57769 *   tint(255, 126); // Apply transparency without changing color
57770 *   image(img, 50, 0);
57771 * }
57772 * </code>
57773 * </div>
57774 *
57775 * @alt
57776 * 2 side by side images of umbrella and ceiling, one image with blue tint
57777 * Images of umbrella and ceiling, one half of image with blue tint
57778 * 2 side by side images of umbrella and ceiling, one image translucent
57779 *
57780 */
57781
57782/**
57783 * @method tint
57784 * @param  {String}        value   a color string
57785 */
57786
57787/**
57788 * @method tint
57789 * @param  {Number}        gray   a gray value
57790 * @param  {Number}        [alpha]
57791 */
57792
57793/**
57794 * @method tint
57795 * @param  {Number[]}      values  an array containing the red,green,blue &
57796 *                                 and alpha components of the color
57797 */
57798
57799/**
57800 * @method tint
57801 * @param  {p5.Color}      color   the tint color
57802 */
57803p5.prototype.tint = function() {
57804  p5._validateParameters('tint', arguments);
57805  var c = this.color.apply(this, arguments);
57806  this._renderer._tint = c.levels;
57807};
57808
57809/**
57810 * Removes the current fill value for displaying images and reverts to
57811 * displaying images with their original hues.
57812 *
57813 * @method noTint
57814 * @example
57815 * <div>
57816 * <code>
57817 * var img;
57818 * function preload() {
57819 *   img = loadImage('assets/bricks.jpg');
57820 * }
57821 * function setup() {
57822 *   tint(0, 153, 204); // Tint blue
57823 *   image(img, 0, 0);
57824 *   noTint(); // Disable tint
57825 *   image(img, 50, 0);
57826 * }
57827 * </code>
57828 * </div>
57829 *
57830 * @alt
57831 * 2 side by side images of bricks, left image with blue tint
57832 *
57833 */
57834p5.prototype.noTint = function() {
57835  this._renderer._tint = null;
57836};
57837
57838/**
57839 * Apply the current tint color to the input image, return the resulting
57840 * canvas.
57841 *
57842 * @private
57843 * @param {p5.Image} The image to be tinted
57844 * @return {canvas} The resulting tinted canvas
57845 *
57846 */
57847p5.prototype._getTintedImageCanvas = function(img) {
57848  if (!img.canvas) {
57849    return img;
57850  }
57851  var pixels = Filters._toPixels(img.canvas);
57852  var tmpCanvas = document.createElement('canvas');
57853  tmpCanvas.width = img.canvas.width;
57854  tmpCanvas.height = img.canvas.height;
57855  var tmpCtx = tmpCanvas.getContext('2d');
57856  var id = tmpCtx.createImageData(img.canvas.width, img.canvas.height);
57857  var newPixels = id.data;
57858
57859  for (var i = 0; i < pixels.length; i += 4) {
57860    var r = pixels[i];
57861    var g = pixels[i + 1];
57862    var b = pixels[i + 2];
57863    var a = pixels[i + 3];
57864
57865    newPixels[i] = r * this._renderer._tint[0] / 255;
57866    newPixels[i + 1] = g * this._renderer._tint[1] / 255;
57867    newPixels[i + 2] = b * this._renderer._tint[2] / 255;
57868    newPixels[i + 3] = a * this._renderer._tint[3] / 255;
57869  }
57870
57871  tmpCtx.putImageData(id, 0, 0);
57872  return tmpCanvas;
57873};
57874
57875/**
57876 * Set image mode. Modifies the location from which images are drawn by
57877 * changing the way in which parameters given to image() are interpreted.
57878 * The default mode is imageMode(CORNER), which interprets the second and
57879 * third parameters of image() as the upper-left corner of the image. If
57880 * two additional parameters are specified, they are used to set the image's
57881 * width and height.
57882 * <br><br>
57883 * imageMode(CORNERS) interprets the second and third parameters of image()
57884 * as the location of one corner, and the fourth and fifth parameters as the
57885 * opposite corner.
57886 * <br><br>
57887 * imageMode(CENTER) interprets the second and third parameters of image()
57888 * as the image's center point. If two additional parameters are specified,
57889 * they are used to set the image's width and height.
57890 *
57891 * @method imageMode
57892 * @param {Constant} mode either CORNER, CORNERS, or CENTER
57893 * @example
57894 *
57895 * <div>
57896 * <code>
57897 * var img;
57898 * function preload() {
57899 *   img = loadImage('assets/bricks.jpg');
57900 * }
57901 * function setup() {
57902 *   imageMode(CORNER);
57903 *   image(img, 10, 10, 50, 50);
57904 * }
57905 * </code>
57906 * </div>
57907 *
57908 * <div>
57909 * <code>
57910 * var img;
57911 * function preload() {
57912 *   img = loadImage('assets/bricks.jpg');
57913 * }
57914 * function setup() {
57915 *   imageMode(CORNERS);
57916 *   image(img, 10, 10, 90, 40);
57917 * }
57918 * </code>
57919 * </div>
57920 *
57921 * <div>
57922 * <code>
57923 * var img;
57924 * function preload() {
57925 *   img = loadImage('assets/bricks.jpg');
57926 * }
57927 * function setup() {
57928 *   imageMode(CENTER);
57929 *   image(img, 50, 50, 80, 80);
57930 * }
57931 * </code>
57932 * </div>
57933 *
57934 * @alt
57935 * small square image of bricks
57936 * horizontal rectangle image of bricks
57937 * large square image of bricks
57938 *
57939 */
57940p5.prototype.imageMode = function(m) {
57941  p5._validateParameters('imageMode', arguments);
57942  if (
57943    m === constants.CORNER ||
57944    m === constants.CORNERS ||
57945    m === constants.CENTER
57946  ) {
57947    this._renderer._imageMode = m;
57948  }
57949};
57950
57951module.exports = p5;
57952
57953},{"../core/canvas":20,"../core/constants":21,"../core/core":22,"../core/error_helpers":25,"./filters":41}],44:[function(_dereq_,module,exports){
57954/**
57955 * @module Image
57956 * @submodule Image
57957 * @requires core
57958 * @requires constants
57959 * @requires filters
57960 */
57961
57962/**
57963 * This module defines the p5.Image class and P5 methods for
57964 * drawing images to the main display canvas.
57965 */
57966
57967'use strict';
57968
57969var p5 = _dereq_('../core/core');
57970var Filters = _dereq_('./filters');
57971
57972/*
57973 * Class methods
57974 */
57975
57976/**
57977 * Creates a new p5.Image. A p5.Image is a canvas backed representation of an
57978 * image.
57979 * <br><br>
57980 * p5 can display .gif, .jpg and .png images. Images may be displayed
57981 * in 2D and 3D space. Before an image is used, it must be loaded with the
57982 * loadImage() function. The p5.Image class contains fields for the width and
57983 * height of the image, as well as an array called pixels[] that contains the
57984 * values for every pixel in the image.
57985 * <br><br>
57986 * The methods described below allow easy access to the image's pixels and
57987 * alpha channel and simplify the process of compositing.
57988 * <br><br>
57989 * Before using the pixels[] array, be sure to use the loadPixels() method on
57990 * the image to make sure that the pixel data is properly loaded.
57991 * @example
57992 * <div><code>
57993 * function setup() {
57994 *   var img = createImage(100, 100); // same as new p5.Image(100, 100);
57995 *   img.loadPixels();
57996 *   createCanvas(100, 100);
57997 *   background(0);
57998 *
57999 *   // helper for writing color to array
58000 *   function writeColor(image, x, y, red, green, blue, alpha) {
58001 *     var index = (x + y * width) * 4;
58002 *     image.pixels[index] = red;
58003 *     image.pixels[index + 1] = green;
58004 *     image.pixels[index + 2] = blue;
58005 *     image.pixels[index + 3] = alpha;
58006 *   }
58007 *
58008 *   var x, y;
58009 *   // fill with random colors
58010 *   for (y = 0; y < img.height; y++) {
58011 *     for (x = 0; x < img.width; x++) {
58012 *       var red = random(255);
58013 *       var green = random(255);
58014 *       var blue = random(255);
58015 *       var alpha = 255;
58016 *       writeColor(img, x, y, red, green, blue, alpha);
58017 *     }
58018 *   }
58019 *
58020 *   // draw a red line
58021 *   y = 0;
58022 *   for (x = 0; x < img.width; x++) {
58023 *     writeColor(img, x, y, 255, 0, 0, 255);
58024 *   }
58025 *
58026 *   // draw a green line
58027 *   y = img.height - 1;
58028 *   for (x = 0; x < img.width; x++) {
58029 *     writeColor(img, x, y, 0, 255, 0, 255);
58030 *   }
58031 *
58032 *   img.updatePixels();
58033 *   image(img, 0, 0);
58034 * }
58035 * </code></div>
58036 *
58037 *
58038 * @class p5.Image
58039 * @param {Number} width
58040 * @param {Number} height
58041 */
58042p5.Image = function(width, height) {
58043  /**
58044   * Image width.
58045   * @property {Number} width
58046   * @readOnly
58047   * @example
58048   * <div><code>
58049   * var img;
58050   * function preload() {
58051   *   img = loadImage('assets/rockies.jpg');
58052   * }
58053   *
58054   * function setup() {
58055   *   createCanvas(100, 100);
58056   *   image(img, 0, 0);
58057   *   for (var i = 0; i < img.width; i++) {
58058   *     var c = img.get(i, img.height / 2);
58059   *     stroke(c);
58060   *     line(i, height / 2, i, height);
58061   *   }
58062   * }
58063   * </code></div>
58064   *
58065   * @alt
58066   * rocky mountains in top and horizontal lines in corresponding colors in bottom.
58067   *
58068   */
58069  this.width = width;
58070  /**
58071   * Image height.
58072   * @property {Number} height
58073   * @readOnly
58074   * @example
58075   * <div><code>
58076   * var img;
58077   * function preload() {
58078   *   img = loadImage('assets/rockies.jpg');
58079   * }
58080   *
58081   * function setup() {
58082   *   createCanvas(100, 100);
58083   *   image(img, 0, 0);
58084   *   for (var i = 0; i < img.height; i++) {
58085   *     var c = img.get(img.width / 2, i);
58086   *     stroke(c);
58087   *     line(0, i, width / 2, i);
58088   *   }
58089   * }
58090   * </code></div>
58091   *
58092   * @alt
58093   * rocky mountains on right and vertical lines in corresponding colors on left.
58094   *
58095   */
58096  this.height = height;
58097  this.canvas = document.createElement('canvas');
58098  this.canvas.width = this.width;
58099  this.canvas.height = this.height;
58100  this.drawingContext = this.canvas.getContext('2d');
58101  this._pixelDensity = 1;
58102  //used for webgl texturing only
58103  this._modified = false;
58104  /**
58105   * Array containing the values for all the pixels in the display window.
58106   * These values are numbers. This array is the size (include an appropriate
58107   * factor for pixelDensity) of the display window x4,
58108   * representing the R, G, B, A values in order for each pixel, moving from
58109   * left to right across each row, then down each column. Retina and other
58110   * high denisty displays may have more pixels[] (by a factor of
58111   * pixelDensity^2).
58112   * For example, if the image is 100x100 pixels, there will be 40,000. With
58113   * pixelDensity = 2, there will be 160,000. The first four values
58114   * (indices 0-3) in the array will be the R, G, B, A values of the pixel at
58115   * (0, 0). The second four values (indices 4-7) will contain the R, G, B, A
58116   * values of the pixel at (1, 0). More generally, to set values for a pixel
58117   * at (x, y):
58118   * ```javascript
58119   * var d = pixelDensity();
58120   * for (var i = 0; i < d; i++) {
58121   *   for (var j = 0; j < d; j++) {
58122   *     // loop over
58123   *     idx = 4 * ((y * d + j) * width * d + (x * d + i));
58124   *     pixels[idx] = r;
58125   *     pixels[idx+1] = g;
58126   *     pixels[idx+2] = b;
58127   *     pixels[idx+3] = a;
58128   *   }
58129   * }
58130   * ```
58131   * <br><br>
58132   * Before accessing this array, the data must loaded with the loadPixels()
58133   * function. After the array data has been modified, the updatePixels()
58134   * function must be run to update the changes.
58135   * @property {Number[]} pixels
58136   * @example
58137   * <div>
58138   * <code>
58139   * var img = createImage(66, 66);
58140   * img.loadPixels();
58141   * for (var i = 0; i < img.width; i++) {
58142   *   for (var j = 0; j < img.height; j++) {
58143   *     img.set(i, j, color(0, 90, 102));
58144   *   }
58145   * }
58146   * img.updatePixels();
58147   * image(img, 17, 17);
58148   * </code>
58149   * </div>
58150   * <div>
58151   * <code>
58152   * var pink = color(255, 102, 204);
58153   * var img = createImage(66, 66);
58154   * img.loadPixels();
58155   * for (var i = 0; i < 4 * (width * height / 2); i += 4) {
58156   *   img.pixels[i] = red(pink);
58157   *   img.pixels[i + 1] = green(pink);
58158   *   img.pixels[i + 2] = blue(pink);
58159   *   img.pixels[i + 3] = alpha(pink);
58160   * }
58161   * img.updatePixels();
58162   * image(img, 17, 17);
58163   * </code>
58164   * </div>
58165   *
58166   * @alt
58167   * 66x66 turquoise rect in center of canvas
58168   * 66x66 pink rect in center of canvas
58169   *
58170   */
58171  this.pixels = [];
58172};
58173
58174/**
58175 * Helper fxn for sharing pixel methods
58176 *
58177 */
58178p5.Image.prototype._setProperty = function(prop, value) {
58179  this[prop] = value;
58180  this.setModified(true);
58181};
58182
58183/**
58184 * Loads the pixels data for this image into the [pixels] attribute.
58185 *
58186 * @method loadPixels
58187 * @example
58188 * <div><code>
58189 * var myImage;
58190 * var halfImage;
58191 *
58192 * function preload() {
58193 *   myImage = loadImage('assets/rockies.jpg');
58194 * }
58195 *
58196 * function setup() {
58197 *   myImage.loadPixels();
58198 *   halfImage = 4 * width * height / 2;
58199 *   for (var i = 0; i < halfImage; i++) {
58200 *     myImage.pixels[i + halfImage] = myImage.pixels[i];
58201 *   }
58202 *   myImage.updatePixels();
58203 * }
58204 *
58205 * function draw() {
58206 *   image(myImage, 0, 0);
58207 * }
58208 * </code></div>
58209 *
58210 * @alt
58211 * 2 images of rocky mountains vertically stacked
58212 *
58213 */
58214p5.Image.prototype.loadPixels = function() {
58215  p5.Renderer2D.prototype.loadPixels.call(this);
58216  this.setModified(true);
58217};
58218
58219/**
58220 * Updates the backing canvas for this image with the contents of
58221 * the [pixels] array.
58222 *
58223 * @method updatePixels
58224 * @param {Integer} x x-offset of the target update area for the
58225 *                              underlying canvas
58226 * @param {Integer} y y-offset of the target update area for the
58227 *                              underlying canvas
58228 * @param {Integer} w height of the target update area for the
58229 *                              underlying canvas
58230 * @param {Integer} h height of the target update area for the
58231 *                              underlying canvas
58232 * @example
58233 * <div><code>
58234 * var myImage;
58235 * var halfImage;
58236 *
58237 * function preload() {
58238 *   myImage = loadImage('assets/rockies.jpg');
58239 * }
58240 *
58241 * function setup() {
58242 *   myImage.loadPixels();
58243 *   halfImage = 4 * width * height / 2;
58244 *   for (var i = 0; i < halfImage; i++) {
58245 *     myImage.pixels[i + halfImage] = myImage.pixels[i];
58246 *   }
58247 *   myImage.updatePixels();
58248 * }
58249 *
58250 * function draw() {
58251 *   image(myImage, 0, 0);
58252 * }
58253 * </code></div>
58254 *
58255 * @alt
58256 * 2 images of rocky mountains vertically stacked
58257 *
58258 */
58259/**
58260 * @method updatePixels
58261 */
58262p5.Image.prototype.updatePixels = function(x, y, w, h) {
58263  p5.Renderer2D.prototype.updatePixels.call(this, x, y, w, h);
58264  this.setModified(true);
58265};
58266
58267/**
58268 * Get a region of pixels from an image.
58269 *
58270 * If no params are passed, those whole image is returned,
58271 * if x and y are the only params passed a single pixel is extracted
58272 * if all params are passed a rectangle region is extracted and a p5.Image
58273 * is returned.
58274 *
58275 * Returns undefined if the region is outside the bounds of the image
58276 *
58277 * @method get
58278 * @param  {Number}               [x] x-coordinate of the pixel
58279 * @param  {Number}               [y] y-coordinate of the pixel
58280 * @param  {Number}               [w] width
58281 * @param  {Number}               [h] height
58282 * @return {Number[]|Color|p5.Image}  color of pixel at x,y in array format
58283 *                                    [R, G, B, A] or p5.Image
58284 * @example
58285 * <div><code>
58286 * var myImage;
58287 * var c;
58288 *
58289 * function preload() {
58290 *   myImage = loadImage('assets/rockies.jpg');
58291 * }
58292 *
58293 * function setup() {
58294 *   background(myImage);
58295 *   noStroke();
58296 *   c = myImage.get(60, 90);
58297 *   fill(c);
58298 *   rect(25, 25, 50, 50);
58299 * }
58300 *
58301 * //get() returns color here
58302 * </code></div>
58303 *
58304 * @alt
58305 * image of rocky mountains with 50x50 green rect in front
58306 *
58307 */
58308p5.Image.prototype.get = function(x, y, w, h) {
58309  return p5.Renderer2D.prototype.get.call(this, x, y, w, h);
58310};
58311
58312/**
58313 * Set the color of a single pixel or write an image into
58314 * this p5.Image.
58315 *
58316 * Note that for a large number of pixels this will
58317 * be slower than directly manipulating the pixels array
58318 * and then calling updatePixels().
58319 *
58320 * @method set
58321 * @param {Number}              x x-coordinate of the pixel
58322 * @param {Number}              y y-coordinate of the pixel
58323 * @param {Number|Number[]|Object}   a grayscale value | pixel array |
58324 *                                a p5.Color | image to copy
58325 * @example
58326 * <div>
58327 * <code>
58328 * var img = createImage(66, 66);
58329 * img.loadPixels();
58330 * for (var i = 0; i < img.width; i++) {
58331 *   for (var j = 0; j < img.height; j++) {
58332 *     img.set(i, j, color(0, 90, 102, (i % img.width) * 2));
58333 *   }
58334 * }
58335 * img.updatePixels();
58336 * image(img, 17, 17);
58337 * image(img, 34, 34);
58338 * </code>
58339 * </div>
58340 *
58341 * @alt
58342 * 2 gradated dark turquoise rects fade left. 1 center 1 bottom right of canvas
58343 *
58344 */
58345p5.Image.prototype.set = function(x, y, imgOrCol) {
58346  p5.Renderer2D.prototype.set.call(this, x, y, imgOrCol);
58347  this.setModified(true);
58348};
58349
58350/**
58351 * Resize the image to a new width and height. To make the image scale
58352 * proportionally, use 0 as the value for the wide or high parameter.
58353 * For instance, to make the width of an image 150 pixels, and change
58354 * the height using the same proportion, use resize(150, 0).
58355 *
58356 * @method resize
58357 * @param {Number} width the resized image width
58358 * @param {Number} height the resized image height
58359 * @example
58360 * <div><code>
58361 * var img;
58362 *
58363 * function preload() {
58364 *   img = loadImage('assets/rockies.jpg');
58365 * }
58366
58367 * function draw() {
58368 *   image(img, 0, 0);
58369 * }
58370 *
58371 * function mousePressed() {
58372 *   img.resize(50, 100);
58373 * }
58374 * </code></div>
58375 *
58376 * @alt
58377 * image of rocky mountains. zoomed in
58378 *
58379 */
58380p5.Image.prototype.resize = function(width, height) {
58381  // Copy contents to a temporary canvas, resize the original
58382  // and then copy back.
58383  //
58384  // There is a faster approach that involves just one copy and swapping the
58385  // this.canvas reference. We could switch to that approach if (as i think
58386  // is the case) there an expectation that the user would not hold a
58387  // reference to the backing canvas of a p5.Image. But since we do not
58388  // enforce that at the moment, I am leaving in the slower, but safer
58389  // implementation.
58390
58391  // auto-resize
58392  if (width === 0 && height === 0) {
58393    width = this.canvas.width;
58394    height = this.canvas.height;
58395  } else if (width === 0) {
58396    width = this.canvas.width * height / this.canvas.height;
58397  } else if (height === 0) {
58398    height = this.canvas.height * width / this.canvas.width;
58399  }
58400
58401  width = Math.floor(width);
58402  height = Math.floor(height);
58403
58404  var tempCanvas = document.createElement('canvas');
58405  tempCanvas.width = width;
58406  tempCanvas.height = height;
58407  // prettier-ignore
58408  tempCanvas.getContext('2d').drawImage(
58409    this.canvas,
58410    0, 0, this.canvas.width, this.canvas.height,
58411    0, 0, tempCanvas.width, tempCanvas.height
58412  );
58413
58414  // Resize the original canvas, which will clear its contents
58415  this.canvas.width = this.width = width;
58416  this.canvas.height = this.height = height;
58417
58418  //Copy the image back
58419
58420  // prettier-ignore
58421  this.drawingContext.drawImage(
58422    tempCanvas,
58423    0, 0, width, height,
58424    0, 0, width, height
58425  );
58426
58427  if (this.pixels.length > 0) {
58428    this.loadPixels();
58429  }
58430
58431  this.setModified(true);
58432};
58433
58434/**
58435 * Copies a region of pixels from one image to another. If no
58436 * srcImage is specified this is used as the source. If the source
58437 * and destination regions aren't the same size, it will
58438 * automatically resize source pixels to fit the specified
58439 * target region.
58440 *
58441 * @method copy
58442 * @param  {p5.Image|p5.Element} srcImage source image
58443 * @param  {Integer} sx X coordinate of the source's upper left corner
58444 * @param  {Integer} sy Y coordinate of the source's upper left corner
58445 * @param  {Integer} sw source image width
58446 * @param  {Integer} sh source image height
58447 * @param  {Integer} dx X coordinate of the destination's upper left corner
58448 * @param  {Integer} dy Y coordinate of the destination's upper left corner
58449 * @param  {Integer} dw destination image width
58450 * @param  {Integer} dh destination image height
58451 * @example
58452 * <div><code>
58453 * var photo;
58454 * var bricks;
58455 * var x;
58456 * var y;
58457 *
58458 * function preload() {
58459 *   photo = loadImage('assets/rockies.jpg');
58460 *   bricks = loadImage('assets/bricks.jpg');
58461 * }
58462 *
58463 * function setup() {
58464 *   x = bricks.width / 2;
58465 *   y = bricks.height / 2;
58466 *   photo.copy(bricks, 0, 0, x, y, 0, 0, x, y);
58467 *   image(photo, 0, 0);
58468 * }
58469 * </code></div>
58470 *
58471 * @alt
58472 * image of rocky mountains and smaller image on top of bricks at top left
58473 *
58474 */
58475/**
58476 * @method copy
58477 * @param  {Integer} sx
58478 * @param  {Integer} sy
58479 * @param  {Integer} sw
58480 * @param  {Integer} sh
58481 * @param  {Integer} dx
58482 * @param  {Integer} dy
58483 * @param  {Integer} dw
58484 * @param  {Integer} dh
58485 */
58486p5.Image.prototype.copy = function() {
58487  var srcImage, sx, sy, sw, sh, dx, dy, dw, dh;
58488  if (arguments.length === 9) {
58489    srcImage = arguments[0];
58490    sx = arguments[1];
58491    sy = arguments[2];
58492    sw = arguments[3];
58493    sh = arguments[4];
58494    dx = arguments[5];
58495    dy = arguments[6];
58496    dw = arguments[7];
58497    dh = arguments[8];
58498  } else if (arguments.length === 8) {
58499    srcImage = this;
58500    sx = arguments[0];
58501    sy = arguments[1];
58502    sw = arguments[2];
58503    sh = arguments[3];
58504    dx = arguments[4];
58505    dy = arguments[5];
58506    dw = arguments[6];
58507    dh = arguments[7];
58508  } else {
58509    throw new Error('Signature not supported');
58510  }
58511  p5.Renderer2D._copyHelper(this, srcImage, sx, sy, sw, sh, dx, dy, dw, dh);
58512};
58513
58514/**
58515 * Masks part of an image from displaying by loading another
58516 * image and using it's alpha channel as an alpha channel for
58517 * this image.
58518 *
58519 * @method mask
58520 * @param {p5.Image} srcImage source image
58521 * @example
58522 * <div><code>
58523 * var photo, maskImage;
58524 * function preload() {
58525 *   photo = loadImage('assets/rockies.jpg');
58526 *   maskImage = loadImage('assets/mask2.png');
58527 * }
58528 *
58529 * function setup() {
58530 *   createCanvas(100, 100);
58531 *   photo.mask(maskImage);
58532 *   image(photo, 0, 0);
58533 * }
58534 * </code></div>
58535 *
58536 * @alt
58537 * image of rocky mountains with white at right
58538 *
58539 *
58540 * http://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/
58541 *
58542 */
58543// TODO: - Accept an array of alpha values.
58544//       - Use other channels of an image. p5 uses the
58545//       blue channel (which feels kind of arbitrary). Note: at the
58546//       moment this method does not match native processings original
58547//       functionality exactly.
58548p5.Image.prototype.mask = function(p5Image) {
58549  if (p5Image === undefined) {
58550    p5Image = this;
58551  }
58552  var currBlend = this.drawingContext.globalCompositeOperation;
58553
58554  var scaleFactor = 1;
58555  if (p5Image instanceof p5.Renderer) {
58556    scaleFactor = p5Image._pInst._pixelDensity;
58557  }
58558
58559  var copyArgs = [
58560    p5Image,
58561    0,
58562    0,
58563    scaleFactor * p5Image.width,
58564    scaleFactor * p5Image.height,
58565    0,
58566    0,
58567    this.width,
58568    this.height
58569  ];
58570
58571  this.drawingContext.globalCompositeOperation = 'destination-in';
58572  p5.Image.prototype.copy.apply(this, copyArgs);
58573  this.drawingContext.globalCompositeOperation = currBlend;
58574  this.setModified(true);
58575};
58576
58577/**
58578 * Applies an image filter to a p5.Image
58579 *
58580 * @method filter
58581 * @param  {Constant} filterType  either THRESHOLD, GRAY, OPAQUE, INVERT,
58582 *                                POSTERIZE, BLUR, ERODE, DILATE or BLUR.
58583 *                                See Filters.js for docs on
58584 *                                each available filter
58585 * @param  {Number} [filterParam] an optional parameter unique
58586 *                                to each filter, see above
58587 * @example
58588 * <div><code>
58589 * var photo1;
58590 * var photo2;
58591 *
58592 * function preload() {
58593 *   photo1 = loadImage('assets/rockies.jpg');
58594 *   photo2 = loadImage('assets/rockies.jpg');
58595 * }
58596 *
58597 * function setup() {
58598 *   photo2.filter('gray');
58599 *   image(photo1, 0, 0);
58600 *   image(photo2, width / 2, 0);
58601 * }
58602 * </code></div>
58603 *
58604 * @alt
58605 * 2 images of rocky mountains left one in color, right in black and white
58606 *
58607 */
58608p5.Image.prototype.filter = function(operation, value) {
58609  Filters.apply(this.canvas, Filters[operation.toLowerCase()], value);
58610  this.setModified(true);
58611};
58612
58613/**
58614 * Copies a region of pixels from one image to another, using a specified
58615 * blend mode to do the operation.
58616 *
58617 * @method blend
58618 * @param  {p5.Image} srcImage source image
58619 * @param  {Integer} sx X coordinate of the source's upper left corner
58620 * @param  {Integer} sy Y coordinate of the source's upper left corner
58621 * @param  {Integer} sw source image width
58622 * @param  {Integer} sh source image height
58623 * @param  {Integer} dx X coordinate of the destination's upper left corner
58624 * @param  {Integer} dy Y coordinate of the destination's upper left corner
58625 * @param  {Integer} dw destination image width
58626 * @param  {Integer} dh destination image height
58627 * @param  {Constant} blendMode the blend mode. either
58628 *     BLEND, DARKEST, LIGHTEST, DIFFERENCE,
58629 *     MULTIPLY, EXCLUSION, SCREEN, REPLACE, OVERLAY, HARD_LIGHT,
58630 *     SOFT_LIGHT, DODGE, BURN, ADD or NORMAL.
58631 *
58632 * Available blend modes are: normal | multiply | screen | overlay |
58633 *            darken | lighten | color-dodge | color-burn | hard-light |
58634 *            soft-light | difference | exclusion | hue | saturation |
58635 *            color | luminosity
58636 *
58637 *
58638 * http://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/
58639 * @example
58640 * <div><code>
58641 * var mountains;
58642 * var bricks;
58643 *
58644 * function preload() {
58645 *   mountains = loadImage('assets/rockies.jpg');
58646 *   bricks = loadImage('assets/bricks_third.jpg');
58647 * }
58648 *
58649 * function setup() {
58650 *   mountains.blend(bricks, 0, 0, 33, 100, 67, 0, 33, 100, ADD);
58651 *   image(mountains, 0, 0);
58652 *   image(bricks, 0, 0);
58653 * }
58654 * </code></div>
58655 * <div><code>
58656 * var mountains;
58657 * var bricks;
58658 *
58659 * function preload() {
58660 *   mountains = loadImage('assets/rockies.jpg');
58661 *   bricks = loadImage('assets/bricks_third.jpg');
58662 * }
58663 *
58664 * function setup() {
58665 *   mountains.blend(bricks, 0, 0, 33, 100, 67, 0, 33, 100, DARKEST);
58666 *   image(mountains, 0, 0);
58667 *   image(bricks, 0, 0);
58668 * }
58669 * </code></div>
58670 * <div><code>
58671 * var mountains;
58672 * var bricks;
58673 *
58674 * function preload() {
58675 *   mountains = loadImage('assets/rockies.jpg');
58676 *   bricks = loadImage('assets/bricks_third.jpg');
58677 * }
58678 *
58679 * function setup() {
58680 *   mountains.blend(bricks, 0, 0, 33, 100, 67, 0, 33, 100, LIGHTEST);
58681 *   image(mountains, 0, 0);
58682 *   image(bricks, 0, 0);
58683 * }
58684 * </code></div>
58685 *
58686 * @alt
58687 * image of rocky mountains. Brick images on left and right. Right overexposed
58688 * image of rockies. Brickwall images on left and right. Right mortar transparent
58689 * image of rockies. Brickwall images on left and right. Right translucent
58690 *
58691 */
58692/**
58693 * @method blend
58694 * @param  {Integer} sx
58695 * @param  {Integer} sy
58696 * @param  {Integer} sw
58697 * @param  {Integer} sh
58698 * @param  {Integer} dx
58699 * @param  {Integer} dy
58700 * @param  {Integer} dw
58701 * @param  {Integer} dh
58702 * @param  {Constant} blendMode
58703 */
58704p5.Image.prototype.blend = function() {
58705  p5.prototype.blend.apply(this, arguments);
58706  this.setModified(true);
58707};
58708
58709/**
58710 * helper method for web GL mode to indicate that an image has been
58711 * changed or unchanged since last upload. gl texture upload will
58712 * set this value to false after uploading the texture.
58713 * @method setModified
58714 * @param {boolean} val sets whether or not the image has been
58715 * modified.
58716 * @private
58717 */
58718p5.Image.prototype.setModified = function(val) {
58719  this._modified = val; //enforce boolean?
58720};
58721
58722/**
58723 * helper method for web GL mode to figure out if the image
58724 * has been modified and might need to be re-uploaded to texture
58725 * memory between frames.
58726 * @method isModified
58727 * @private
58728 * @return {boolean} a boolean indicating whether or not the
58729 * image has been updated or modified since last texture upload.
58730 */
58731p5.Image.prototype.isModified = function() {
58732  return this._modified;
58733};
58734
58735/**
58736 * Saves the image to a file and force the browser to download it.
58737 * Accepts two strings for filename and file extension
58738 * Supports png (default) and jpg.
58739 *
58740 * @method save
58741 * @param {String} filename give your file a name
58742 * @param  {String} extension 'png' or 'jpg'
58743 * @example
58744 * <div><code>
58745 * var photo;
58746 *
58747 * function preload() {
58748 *   photo = loadImage('assets/rockies.jpg');
58749 * }
58750 *
58751 * function draw() {
58752 *   image(photo, 0, 0);
58753 * }
58754 *
58755 * function keyTyped() {
58756 *   if (key === 's') {
58757 *     photo.save('photo', 'png');
58758 *   }
58759 * }
58760 * </code></div>
58761 *
58762 * @alt
58763 * image of rocky mountains.
58764 *
58765 */
58766p5.Image.prototype.save = function(filename, extension) {
58767  p5.prototype.saveCanvas(this.canvas, filename, extension);
58768};
58769
58770module.exports = p5.Image;
58771
58772},{"../core/core":22,"./filters":41}],45:[function(_dereq_,module,exports){
58773/**
58774 * @module Image
58775 * @submodule Pixels
58776 * @for p5
58777 * @requires core
58778 */
58779
58780'use strict';
58781
58782var p5 = _dereq_('../core/core');
58783var Filters = _dereq_('./filters');
58784_dereq_('../color/p5.Color');
58785
58786/**
58787 * <a href='https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference
58788 * /Global_Objects/Uint8ClampedArray' target='_blank'>Uint8ClampedArray</a>
58789 * containing the values for all the pixels in the display window.
58790 * These values are numbers. This array is the size (include an appropriate
58791 * factor for pixelDensity) of the display window x4,
58792 * representing the R, G, B, A values in order for each pixel, moving from
58793 * left to right across each row, then down each column. Retina and other
58794 * high density displays will have more pixels[] (by a factor of
58795 * pixelDensity^2).
58796 * For example, if the image is 100x100 pixels, there will be 40,000. On a
58797 * retina display, there will be 160,000.
58798 * <br><br>
58799 * The first four values (indices 0-3) in the array will be the R, G, B, A
58800 * values of the pixel at (0, 0). The second four values (indices 4-7) will
58801 * contain the R, G, B, A values of the pixel at (1, 0). More generally, to
58802 * set values for a pixel at (x, y):
58803 * ```javascript
58804 * var d = pixelDensity();
58805 * for (var i = 0; i < d; i++) {
58806 *   for (var j = 0; j < d; j++) {
58807 *     // loop over
58808 *     idx = 4 * ((y * d + j) * width * d + (x * d + i));
58809 *     pixels[idx] = r;
58810 *     pixels[idx+1] = g;
58811 *     pixels[idx+2] = b;
58812 *     pixels[idx+3] = a;
58813 *   }
58814 * }
58815 * ```
58816 * <p>While the above method is complex, it is flexible enough to work with
58817 * any pixelDensity. Note that set() will automatically take care of
58818 * setting all the appropriate values in pixels[] for a given (x, y) at
58819 * any pixelDensity, but the performance may not be as fast when lots of
58820 * modifications are made to the pixel array.
58821 * <br><br>
58822 * Before accessing this array, the data must loaded with the loadPixels()
58823 * function. After the array data has been modified, the updatePixels()
58824 * function must be run to update the changes.
58825 * <br><br>
58826 * Note that this is not a standard javascript array.  This means that
58827 * standard javascript functions such as <code>slice()</code> or
58828 * <code>arrayCopy()</code> do not
58829 * work.</p>
58830 *
58831 * @property {Number[]} pixels
58832 * @example
58833 * <div>
58834 * <code>
58835 * var pink = color(255, 102, 204);
58836 * loadPixels();
58837 * var d = pixelDensity();
58838 * var halfImage = 4 * (width * d) * (height / 2 * d);
58839 * for (var i = 0; i < halfImage; i += 4) {
58840 *   pixels[i] = red(pink);
58841 *   pixels[i + 1] = green(pink);
58842 *   pixels[i + 2] = blue(pink);
58843 *   pixels[i + 3] = alpha(pink);
58844 * }
58845 * updatePixels();
58846 * </code>
58847 * </div>
58848 *
58849 * @alt
58850 * top half of canvas pink, bottom grey
58851 *
58852 */
58853p5.prototype.pixels = [];
58854
58855/**
58856 * Copies a region of pixels from one image to another, using a specified
58857 * blend mode to do the operation.
58858 *
58859 * @method blend
58860 * @param  {p5.Image} srcImage source image
58861 * @param  {Integer} sx X coordinate of the source's upper left corner
58862 * @param  {Integer} sy Y coordinate of the source's upper left corner
58863 * @param  {Integer} sw source image width
58864 * @param  {Integer} sh source image height
58865 * @param  {Integer} dx X coordinate of the destination's upper left corner
58866 * @param  {Integer} dy Y coordinate of the destination's upper left corner
58867 * @param  {Integer} dw destination image width
58868 * @param  {Integer} dh destination image height
58869 * @param  {Constant} blendMode the blend mode. either
58870 *     BLEND, DARKEST, LIGHTEST, DIFFERENCE,
58871 *     MULTIPLY, EXCLUSION, SCREEN, REPLACE, OVERLAY, HARD_LIGHT,
58872 *     SOFT_LIGHT, DODGE, BURN, ADD or NORMAL.
58873 *
58874 * @example
58875 * <div><code>
58876 * var img0;
58877 * var img1;
58878 *
58879 * function preload() {
58880 *   img0 = loadImage('assets/rockies.jpg');
58881 *   img1 = loadImage('assets/bricks_third.jpg');
58882 * }
58883 *
58884 * function setup() {
58885 *   background(img0);
58886 *   image(img1, 0, 0);
58887 *   blend(img1, 0, 0, 33, 100, 67, 0, 33, 100, LIGHTEST);
58888 * }
58889 * </code></div>
58890 * <div><code>
58891 * var img0;
58892 * var img1;
58893 *
58894 * function preload() {
58895 *   img0 = loadImage('assets/rockies.jpg');
58896 *   img1 = loadImage('assets/bricks_third.jpg');
58897 * }
58898 *
58899 * function setup() {
58900 *   background(img0);
58901 *   image(img1, 0, 0);
58902 *   blend(img1, 0, 0, 33, 100, 67, 0, 33, 100, DARKEST);
58903 * }
58904 * </code></div>
58905 * <div><code>
58906 * var img0;
58907 * var img1;
58908 *
58909 * function preload() {
58910 *   img0 = loadImage('assets/rockies.jpg');
58911 *   img1 = loadImage('assets/bricks_third.jpg');
58912 * }
58913 *
58914 * function setup() {
58915 *   background(img0);
58916 *   image(img1, 0, 0);
58917 *   blend(img1, 0, 0, 33, 100, 67, 0, 33, 100, ADD);
58918 * }
58919 * </code></div>
58920 *
58921 * @alt
58922 * image of rocky mountains. Brick images on left and right. Right overexposed
58923 * image of rockies. Brickwall images on left and right. Right mortar transparent
58924 * image of rockies. Brickwall images on left and right. Right translucent
58925 *
58926 *
58927 */
58928/**
58929 * @method blend
58930 * @param  {Integer} sx
58931 * @param  {Integer} sy
58932 * @param  {Integer} sw
58933 * @param  {Integer} sh
58934 * @param  {Integer} dx
58935 * @param  {Integer} dy
58936 * @param  {Integer} dw
58937 * @param  {Integer} dh
58938 * @param  {Constant} blendMode
58939 */
58940p5.prototype.blend = function() {
58941  p5._validateParameters('blend', arguments);
58942  if (this._renderer) {
58943    this._renderer.blend.apply(this._renderer, arguments);
58944  } else {
58945    p5.Renderer2D.prototype.blend.apply(this, arguments);
58946  }
58947};
58948
58949/**
58950 * Copies a region of the canvas to another region of the canvas
58951 * and copies a region of pixels from an image used as the srcImg parameter
58952 * into the canvas srcImage is specified this is used as the source. If
58953 * the source and destination regions aren't the same size, it will
58954 * automatically resize source pixels to fit the specified
58955 * target region.
58956 *
58957 * @method copy
58958 * @param  {p5.Image|p5.Element} srcImage source image
58959 * @param  {Integer} sx X coordinate of the source's upper left corner
58960 * @param  {Integer} sy Y coordinate of the source's upper left corner
58961 * @param  {Integer} sw source image width
58962 * @param  {Integer} sh source image height
58963 * @param  {Integer} dx X coordinate of the destination's upper left corner
58964 * @param  {Integer} dy Y coordinate of the destination's upper left corner
58965 * @param  {Integer} dw destination image width
58966 * @param  {Integer} dh destination image height
58967 *
58968 * @example
58969 * <div><code>
58970 * var img;
58971 *
58972 * function preload() {
58973 *   img = loadImage('assets/rockies.jpg');
58974 * }
58975 *
58976 * function setup() {
58977 *   background(img);
58978 *   copy(img, 7, 22, 10, 10, 35, 25, 50, 50);
58979 *   stroke(255);
58980 *   noFill();
58981 *   // Rectangle shows area being copied
58982 *   rect(7, 22, 10, 10);
58983 * }
58984 * </code></div>
58985 *
58986 * @alt
58987 * image of rocky mountains. Brick images on left and right. Right overexposed
58988 * image of rockies. Brickwall images on left and right. Right mortar transparent
58989 * image of rockies. Brickwall images on left and right. Right translucent
58990 *
58991 */
58992/**
58993 * @method copy
58994 * @param  {Integer} sx
58995 * @param  {Integer} sy
58996 * @param  {Integer} sw
58997 * @param  {Integer} sh
58998 * @param  {Integer} dx
58999 * @param  {Integer} dy
59000 * @param  {Integer} dw
59001 * @param  {Integer} dh
59002 */
59003p5.prototype.copy = function() {
59004  p5._validateParameters('copy', arguments);
59005  p5.Renderer2D.prototype.copy.apply(this._renderer, arguments);
59006};
59007
59008/**
59009 * Applies a filter to the canvas.
59010 * <br><br>
59011 *
59012 * The presets options are:
59013 * <br><br>
59014 *
59015 * THRESHOLD
59016 * Converts the image to black and white pixels depending if they are above or
59017 * below the threshold defined by the level parameter. The parameter must be
59018 * between 0.0 (black) and 1.0 (white). If no level is specified, 0.5 is used.
59019 * <br><br>
59020 *
59021 * GRAY
59022 * Converts any colors in the image to grayscale equivalents. No parameter
59023 * is used.
59024 * <br><br>
59025 *
59026 * OPAQUE
59027 * Sets the alpha channel to entirely opaque. No parameter is used.
59028 * <br><br>
59029 *
59030 * INVERT
59031 * Sets each pixel to its inverse value. No parameter is used.
59032 * <br><br>
59033 *
59034 * POSTERIZE
59035 * Limits each channel of the image to the number of colors specified as the
59036 * parameter. The parameter can be set to values between 2 and 255, but
59037 * results are most noticeable in the lower ranges.
59038 * <br><br>
59039 *
59040 * BLUR
59041 * Executes a Gaussian blur with the level parameter specifying the extent
59042 * of the blurring. If no parameter is used, the blur is equivalent to
59043 * Gaussian blur of radius 1. Larger values increase the blur.
59044 * <br><br>
59045 *
59046 * ERODE
59047 * Reduces the light areas. No parameter is used.
59048 * <br><br>
59049 *
59050 * DILATE
59051 * Increases the light areas. No parameter is used.
59052 *
59053 * @method filter
59054 * @param  {Constant} filterType  either THRESHOLD, GRAY, OPAQUE, INVERT,
59055 *                                POSTERIZE, BLUR, ERODE, DILATE or BLUR.
59056 *                                See Filters.js for docs on
59057 *                                each available filter
59058 * @param  {Number} [filterParam] an optional parameter unique
59059 *                                to each filter, see above
59060 *
59061 * @example
59062 * <div>
59063 * <code>
59064 * var img;
59065 * function preload() {
59066 *   img = loadImage('assets/bricks.jpg');
59067 * }
59068 * function setup() {
59069 *   image(img, 0, 0);
59070 *   filter(THRESHOLD);
59071 * }
59072 * </code>
59073 * </div>
59074 *
59075 * <div>
59076 * <code>
59077 * var img;
59078 * function preload() {
59079 *   img = loadImage('assets/bricks.jpg');
59080 * }
59081 * function setup() {
59082 *   image(img, 0, 0);
59083 *   filter(GRAY);
59084 * }
59085 * </code>
59086 * </div>
59087 *
59088 * <div>
59089 * <code>
59090 * var img;
59091 * function preload() {
59092 *   img = loadImage('assets/bricks.jpg');
59093 * }
59094 * function setup() {
59095 *   image(img, 0, 0);
59096 *   filter(OPAQUE);
59097 * }
59098 * </code>
59099 * </div>
59100 *
59101 * <div>
59102 * <code>
59103 * var img;
59104 * function preload() {
59105 *   img = loadImage('assets/bricks.jpg');
59106 * }
59107 * function setup() {
59108 *   image(img, 0, 0);
59109 *   filter(INVERT);
59110 * }
59111 * </code>
59112 * </div>
59113 *
59114 * <div>
59115 * <code>
59116 * var img;
59117 * function preload() {
59118 *   img = loadImage('assets/bricks.jpg');
59119 * }
59120 * function setup() {
59121 *   image(img, 0, 0);
59122 *   filter(POSTERIZE, 3);
59123 * }
59124 * </code>
59125 * </div>
59126 *
59127 * <div>
59128 * <code>
59129 * var img;
59130 * function preload() {
59131 *   img = loadImage('assets/bricks.jpg');
59132 * }
59133 * function setup() {
59134 *   image(img, 0, 0);
59135 *   filter(DILATE);
59136 * }
59137 * </code>
59138 * </div>
59139 *
59140 * <div>
59141 * <code>
59142 * var img;
59143 * function preload() {
59144 *   img = loadImage('assets/bricks.jpg');
59145 * }
59146 * function setup() {
59147 *   image(img, 0, 0);
59148 *   filter(BLUR, 3);
59149 * }
59150 * </code>
59151 * </div>
59152 *
59153 * <div>
59154 * <code>
59155 * var img;
59156 * function preload() {
59157 *   img = loadImage('assets/bricks.jpg');
59158 * }
59159 * function setup() {
59160 *   image(img, 0, 0);
59161 *   filter(ERODE);
59162 * }
59163 * </code>
59164 * </div>
59165 *
59166 * @alt
59167 * black and white image of a brick wall.
59168 * greyscale image of a brickwall
59169 * image of a brickwall
59170 * jade colored image of a brickwall
59171 * red and pink image of a brickwall
59172 * image of a brickwall
59173 * blurry image of a brickwall
59174 * image of a brickwall
59175 * image of a brickwall with less detail
59176 *
59177 */
59178p5.prototype.filter = function(operation, value) {
59179  p5._validateParameters('filter', arguments);
59180  if (this.canvas !== undefined) {
59181    Filters.apply(this.canvas, Filters[operation.toLowerCase()], value);
59182  } else {
59183    Filters.apply(this.elt, Filters[operation.toLowerCase()], value);
59184  }
59185};
59186
59187/**
59188 * Returns an array of [R,G,B,A] values for any pixel or grabs a section of
59189 * an image. If no parameters are specified, the entire image is returned.
59190 * Use the x and y parameters to get the value of one pixel. Get a section of
59191 * the display window by specifying additional w and h parameters. When
59192 * getting an image, the x and y parameters define the coordinates for the
59193 * upper-left corner of the image, regardless of the current imageMode().
59194 * <br><br>
59195 * If the pixel requested is outside of the image window, [0,0,0,255] is
59196 * returned. To get the numbers scaled according to the current color ranges
59197 * and taking into account colorMode, use getColor instead of get.
59198 * <br><br>
59199 * Getting the color of a single pixel with get(x, y) is easy, but not as fast
59200 * as grabbing the data directly from pixels[]. The equivalent statement to
59201 * get(x, y) using pixels[] with pixel density d is
59202 * <code>
59203 * var x, y, d; // set these to the coordinates
59204 * var off = (y * width + x) * d * 4;
59205 * var components = [
59206 *   pixels[off],
59207 *   pixels[off + 1],
59208 *   pixels[off + 2],
59209 *   pixels[off + 3]
59210 * ];
59211 * print(components);
59212 * </code>
59213 * <br><br>
59214 * See the reference for pixels[] for more information.
59215 *
59216 * @method get
59217 * @param  {Number}         [x] x-coordinate of the pixel
59218 * @param  {Number}         [y] y-coordinate of the pixel
59219 * @param  {Number}         [w] width
59220 * @param  {Number}         [h] height
59221 * @return {Number[]|p5.Image}  values of pixel at x,y in array format
59222 *                              [R, G, B, A] or p5.Image
59223 * @example
59224 * <div>
59225 * <code>
59226 * var img;
59227 * function preload() {
59228 *   img = loadImage('assets/rockies.jpg');
59229 * }
59230 * function setup() {
59231 *   image(img, 0, 0);
59232 *   var c = get();
59233 *   image(c, width / 2, 0);
59234 * }
59235 * </code>
59236 * </div>
59237 *
59238 * <div>
59239 * <code>
59240 * var img;
59241 * function preload() {
59242 *   img = loadImage('assets/rockies.jpg');
59243 * }
59244 * function setup() {
59245 *   image(img, 0, 0);
59246 *   var c = get(50, 90);
59247 *   fill(c);
59248 *   noStroke();
59249 *   rect(25, 25, 50, 50);
59250 * }
59251 * </code>
59252 * </div>
59253 *
59254 * @alt
59255 * 2 images of the rocky mountains, side-by-side
59256 * Image of the rocky mountains with 50x50 green rect in center of canvas
59257 *
59258 */
59259p5.prototype.get = function(x, y, w, h) {
59260  return this._renderer.get(x, y, w, h);
59261};
59262
59263/**
59264 * Loads the pixel data for the display window into the pixels[] array. This
59265 * function must always be called before reading from or writing to pixels[].
59266 * Note that only changes made with set() or direct manipulation of pixels[]
59267 * will occur.
59268 *
59269 * @method loadPixels
59270 * @example
59271 * <div>
59272 * <code>
59273 * var img;
59274 * function preload() {
59275 *   img = loadImage('assets/rockies.jpg');
59276 * }
59277 *
59278 * function setup() {
59279 *   image(img, 0, 0);
59280 *   var d = pixelDensity();
59281 *   var halfImage = 4 * (img.width * d) * (img.height * d / 2);
59282 *   loadPixels();
59283 *   for (var i = 0; i < halfImage; i++) {
59284 *     pixels[i + halfImage] = pixels[i];
59285 *   }
59286 *   updatePixels();
59287 * }
59288 * </code>
59289 * </div>
59290 *
59291 * @alt
59292 * two images of the rocky mountains. one on top, one on bottom of canvas.
59293 *
59294 */
59295p5.prototype.loadPixels = function() {
59296  p5._validateParameters('loadPixels', arguments);
59297  this._renderer.loadPixels();
59298};
59299
59300/**
59301 * <p>Changes the color of any pixel, or writes an image directly to the
59302 * display window.</p>
59303 * <p>The x and y parameters specify the pixel to change and the c parameter
59304 * specifies the color value. This can be a p5.Color object, or [R, G, B, A]
59305 * pixel array. It can also be a single grayscale value.
59306 * When setting an image, the x and y parameters define the coordinates for
59307 * the upper-left corner of the image, regardless of the current imageMode().
59308 * </p>
59309 * <p>
59310 * After using set(), you must call updatePixels() for your changes to appear.
59311 * This should be called once all pixels have been set, and must be called before
59312 * calling .get() or drawing the image.
59313 * </p>
59314 * <p>Setting the color of a single pixel with set(x, y) is easy, but not as
59315 * fast as putting the data directly into pixels[]. Setting the pixels[]
59316 * values directly may be complicated when working with a retina display,
59317 * but will perform better when lots of pixels need to be set directly on
59318 * every loop.</p>
59319 * <p>See the reference for pixels[] for more information.</p>
59320 *
59321 * @method set
59322 * @param {Number}              x x-coordinate of the pixel
59323 * @param {Number}              y y-coordinate of the pixel
59324 * @param {Number|Number[]|Object} c insert a grayscale value | a pixel array |
59325 *                                a p5.Color object | a p5.Image to copy
59326 * @example
59327 * <div>
59328 * <code>
59329 * var black = color(0);
59330 * set(30, 20, black);
59331 * set(85, 20, black);
59332 * set(85, 75, black);
59333 * set(30, 75, black);
59334 * updatePixels();
59335 * </code>
59336 * </div>
59337 *
59338 * <div>
59339 * <code>
59340 * for (var i = 30; i < width - 15; i++) {
59341 *   for (var j = 20; j < height - 25; j++) {
59342 *     var c = color(204 - j, 153 - i, 0);
59343 *     set(i, j, c);
59344 *   }
59345 * }
59346 * updatePixels();
59347 * </code>
59348 * </div>
59349 *
59350 * <div>
59351 * <code>
59352 * var img;
59353 * function preload() {
59354 *   img = loadImage('assets/rockies.jpg');
59355 * }
59356 *
59357 * function setup() {
59358 *   set(0, 0, img);
59359 *   updatePixels();
59360 *   line(0, 0, width, height);
59361 *   line(0, height, width, 0);
59362 * }
59363 * </code>
59364 * </div>
59365 *
59366 * @alt
59367 * 4 black points in the shape of a square middle-right of canvas.
59368 * square with orangey-brown gradient lightening at bottom right.
59369 * image of the rocky mountains. with lines like an 'x' through the center.
59370 */
59371p5.prototype.set = function(x, y, imgOrCol) {
59372  this._renderer.set(x, y, imgOrCol);
59373};
59374/**
59375 * Updates the display window with the data in the pixels[] array.
59376 * Use in conjunction with loadPixels(). If you're only reading pixels from
59377 * the array, there's no need to call updatePixels() — updating is only
59378 * necessary to apply changes. updatePixels() should be called anytime the
59379 * pixels array is manipulated or set() is called, and only changes made with
59380 * set() or direct changes to pixels[] will occur.
59381 *
59382 * @method updatePixels
59383 * @param  {Number} [x]    x-coordinate of the upper-left corner of region
59384 *                         to update
59385 * @param  {Number} [y]    y-coordinate of the upper-left corner of region
59386 *                         to update
59387 * @param  {Number} [w]    width of region to update
59388 * @param  {Number} [h]    height of region to update
59389 * @example
59390 * <div>
59391 * <code>
59392 * var img;
59393 * function preload() {
59394 *   img = loadImage('assets/rockies.jpg');
59395 * }
59396 *
59397 * function setup() {
59398 *   image(img, 0, 0);
59399 *   var d = pixelDensity();
59400 *   var halfImage = 4 * (img.width * d) * (img.height * d / 2);
59401 *   loadPixels();
59402 *   for (var i = 0; i < halfImage; i++) {
59403 *     pixels[i + halfImage] = pixels[i];
59404 *   }
59405 *   updatePixels();
59406 * }
59407 * </code>
59408 * </div>
59409 * @alt
59410 * two images of the rocky mountains. one on top, one on bottom of canvas.
59411 */
59412p5.prototype.updatePixels = function(x, y, w, h) {
59413  p5._validateParameters('updatePixels', arguments);
59414  // graceful fail - if loadPixels() or set() has not been called, pixel
59415  // array will be empty, ignore call to updatePixels()
59416  if (this.pixels.length === 0) {
59417    return;
59418  }
59419  this._renderer.updatePixels(x, y, w, h);
59420};
59421
59422module.exports = p5;
59423
59424},{"../color/p5.Color":16,"../core/core":22,"./filters":41}],46:[function(_dereq_,module,exports){
59425/**
59426 * @module IO
59427 * @submodule Input
59428 * @for p5
59429 * @requires core
59430 */
59431
59432/* globals Request: false */
59433/* globals Headers: false */
59434
59435'use strict';
59436
59437var p5 = _dereq_('../core/core');
59438_dereq_('whatwg-fetch');
59439_dereq_('es6-promise').polyfill();
59440var fetchJsonp = _dereq_('fetch-jsonp');
59441_dereq_('../core/error_helpers');
59442
59443/**
59444 * Loads a JSON file from a file or a URL, and returns an Object.
59445 * Note that even if the JSON file contains an Array, an Object will be
59446 * returned with index numbers as keys.
59447 *
59448 * This method is asynchronous, meaning it may not finish before the next
59449 * line in your sketch is executed. JSONP is supported via a polyfill and 
59449you
59450 * can pass in as the second argument an object with definitions of the json
59451 * callback following the syntax specified <a href="https://github.com/camsong/
59452 * fetch-jsonp">here</a>.
59453 *
59454 * @method loadJSON
59455 * @param  {String}        path       name of the file or url to load
59456 * @param  {Object}        [jsonpOptions] options object for jsonp related settings
59457 * @param  {String}        [datatype] "json" or "jsonp"
59458 * @param  {function}      [callback] function to be executed after
59459 *                                    loadJSON() completes, data is passed
59460 *                                    in as first argument
59461 * @param  {function}      [errorCallback] function to be executed if
59462 *                                    there is an error, response is passed
59463 *                                    in as first argument
59464 * @return {Object|Array}             JSON data
59465 * @example
59466 *
59467 * <p>Calling loadJSON() inside preload() guarantees to complete the
59468 * operation before setup() and draw() are called.</p>
59469 *
59470 * <div><code>
59471 * // Examples use USGS Earthquake API:
59472 * //   https://earthquake.usgs.gov/fdsnws/event/1/#methods
59473 * var earthquakes;
59474 * function preload() {
59475 *   // Get the most recent earthquake in the database
59476 *   var url =
59477    'https://earthquake.usgs.gov/earthquakes/feed/v1.0/' +
59478 *     'summary/all_day.geojson';
59479 *   earthquakes = loadJSON(url);
59480 * }
59481 *
59482 * function setup() {
59483 *   noLoop();
59484 * }
59485 *
59486 * function draw() {
59487 *   background(200);
59488 *   // Get the magnitude and name of the earthquake out of the loaded JSON
59489 *   var earthquakeMag = earthquakes.features[0].properties.mag;
59490 *   var earthquakeName = earthquakes.features[0].properties.place;
59491 *   ellipse(width / 2, height / 2, earthquakeMag * 10, earthquakeMag * 10);
59492 *   textAlign(CENTER);
59493 *   text(earthquakeName, 0, height - 30, width, 30);
59494 * }
59495 * </code></div>
59496 *
59497 *
59498 * <p>Outside of preload(), you may supply a callback function to handle the
59499 * object:</p>
59500 * <div><code>
59501 * function setup() {
59502 *   noLoop();
59503 *   var url =
59504    'https://earthquake.usgs.gov/earthquakes/feed/v1.0/' +
59505 *     'summary/all_day.geojson';
59506 *   loadJSON(url, drawEarthquake);
59507 * }
59508 *
59509 * function draw() {
59510 *   background(200);
59511 * }
59512 *
59513 * function drawEarthquake(earthquakes) {
59514 *   // Get the magnitude and name of the earthquake out of the loaded JSON
59515 *   var earthquakeMag = earthquakes.features[0].properties.mag;
59516 *   var earthquakeName = earthquakes.features[0].properties.place;
59517 *   ellipse(width / 2, height / 2, earthquakeMag * 10, earthquakeMag * 10);
59518 *   textAlign(CENTER);
59519 *   text(earthquakeName, 0, height - 30, width, 30);
59520 * }
59521 * </code></div>
59522 *
59523 * @alt
59524 * 50x50 ellipse that changes from black to white depending on the current humidity
59525 * 50x50 ellipse that changes from black to white depending on the current humidity
59526 *
59527 */
59528/**
59529 * @method loadJSON
59530 * @param  {String}        path
59531 * @param  {String}        datatype
59532 * @param  {function}      [callback]
59533 * @param  {function}      [errorCallback]
59534 * @return {Object|Array}
59535 */
59536/**
59537 * @method loadJSON
59538 * @param  {String}        path
59539 * @param  {function}      callback
59540 * @param  {function}      [errorCallback]
59541 * @return {Object|Array}
59542 */
59543p5.prototype.loadJSON = function() {
59544  p5._validateParameters('loadJSON', arguments);
59545  var path = arguments[0];
59546  var callback;
59547  var errorCallback;
59548  var options;
59549
59550  var ret = {}; // object needed for preload
59551  var t = 'json';
59552
59553  // check for explicit data type argument
59554  for (var i = 1; i < arguments.length; i++) {
59555    var arg = arguments[i];
59556    if (typeof arg === 'string') {
59557      if (arg === 'jsonp' || arg === 'json') {
59558        t = arg;
59559      }
59560    } else if (typeof arg === 'function') {
59561      if (!callback) {
59562        callback = arg;
59563      } else {
59564        errorCallback = arg;
59565      }
59566    } else if (typeof arg === 'object' && arg.hasOwnProperty('jsonpCallback')) {
59567      t = 'jsonp';
59568      options = arg;
59569    }
59570  }
59571
59572  var self = this;
59573  this.httpDo(
59574    path,
59575    'GET',
59576    options,
59577    t,
59578    function(resp) {
59579      for (var k in resp) {
59580        ret[k] = resp[k];
59581      }
59582      if (typeof callback !== 'undefined') {
59583        callback(resp);
59584      }
59585
59586      self._decrementPreload();
59587    },
59588    errorCallback
59589  );
59590
59591  return ret;
59592};
59593
59594/**
59595 * Reads the contents of a file and creates a String array of its individual
59596 * lines. If the name of the file is used as the parameter, as in the above
59597 * example, the file must be located in the sketch directory/folder.
59598 * <br><br>
59599 * Alternatively, the file maybe be loaded from anywhere on the local
59600 * computer using an absolute path (something that starts with / on Unix and
59601 * Linux, or a drive letter on Windows), or the filename parameter can be a
59602 * URL for a file found on a network.
59603 * <br><br>
59604 * This method is asynchronous, meaning it may not finish before the next
59605 * line in your sketch is executed.
59606 *
59607 * @method loadStrings
59608 * @param  {String}   filename   name of the file or url to load
59609 * @param  {function} [callback] function to be executed after loadStrings()
59610 *                               completes, Array is passed in as first
59611 *                               argument
59612 * @param  {function} [errorCallback] function to be executed if
59613 *                               there is an error, response is passed
59614 *                               in as first argument
59615 * @return {String[]}            Array of Strings
59616 * @example
59617 *
59618 * <p>Calling loadStrings() inside preload() guarantees to complete the
59619 * operation before setup() and draw() are called.</p>
59620 *
59621 * <div><code>
59622 * var result;
59623 * function preload() {
59624 *   result = loadStrings('assets/test.txt');
59625 * }
59626
59627 * function setup() {
59628 *   background(200);
59629 *   var ind = floor(random(result.length));
59630 *   text(result[ind], 10, 10, 80, 80);
59631 * }
59632 * </code></div>
59633 *
59634 * <p>Outside of preload(), you may supply a callback function to handle the
59635 * object:</p>
59636 *
59637 * <div><code>
59638 * function setup() {
59639 *   loadStrings('assets/test.txt', pickString);
59640 * }
59641 *
59642 * function pickString(result) {
59643 *   background(200);
59644 *   var ind = floor(random(result.length));
59645 *   text(result[ind], 10, 10, 80, 80);
59646 * }
59647 * </code></div>
59648 *
59649 * @alt
59650 * randomly generated text from a file, for example "i smell like butter"
59651 * randomly generated text from a file, for example "i have three feet"
59652 *
59653 */
59654p5.prototype.loadStrings = function() {
59655  p5._validateParameters('loadStrings', arguments);
59656
59657  var ret = [];
59658  var callback, errorCallback;
59659
59660  for (var i = 1; i < arguments.length; i++) {
59661    var arg = arguments[i];
59662    if (typeof arg === 'function') {
59663      if (typeof callback === 'undefined') {
59664        callback = arg;
59665      } else if (typeof errorCallback === 'undefined') {
59666        errorCallback = arg;
59667      }
59668    }
59669  }
59670
59671  var self = this;
59672  p5.prototype.httpDo.call(
59673    this,
59674    arguments[0],
59675    'GET',
59676    'text',
59677    function(data) {
59678      var arr = data.match(/[^\r\n]+/g);
59679      for (var k in arr) {
59680        ret[k] = arr[k];
59681      }
59682
59683      if (typeof callback !== 'undefined') {
59684        callback(ret);
59685      }
59686
59687      self._decrementPreload();
59688    },
59689    errorCallback
59690  );
59691
59692  return ret;
59693};
59694
59695/**
59696 * <p>Reads the contents of a file or URL and creates a p5.Table object with
59697 * its values. If a file is specified, it must be located in the sketch's
59698 * "data" folder. The filename parameter can also be a URL to a file found
59699 * online. By default, the file is assumed to be comma-separated (in CSV
59700 * format). Table only looks for a header row if the 'header' option is
59701 * included.</p>
59702 *
59703 * <p>Possible options include:
59704 * <ul>
59705 * <li>csv - parse the table as comma-separated values</li>
59706 * <li>tsv - parse the table as tab-separated values</li>
59707 * <li>header - this table has a header (title) row</li>
59708 * </ul>
59709 * </p>
59710 *
59711 * <p>When passing in multiple options, pass them in as separate parameters,
59712 * seperated by commas. For example:
59713 * <br><br>
59714 * <code>
59715 * loadTable('my_csv_file.csv', 'csv', 'header');
59716 * </code>
59717 * </p>
59718 *
59719 * <p> All files loaded and saved use UTF-8 encoding.</p>
59720 *
59721 * <p>This method is asynchronous, meaning it may not finish before the next
59722 * line in your sketch is executed. Calling loadTable() inside preload()
59723 * guarantees to complete the operation before setup() and draw() are called.
59724 * <p>Outside of preload(), you may supply a callback function to handle the
59725 * object:</p>
59726 * </p>
59727 *
59728 * @method loadTable
59729 * @param  {String}         filename   name of the file or URL to load
59730 * @param  {String}         options  "header" "csv" "tsv"
59731 * @param  {function}       [callback] function to be executed after
59732 *                                     loadTable() completes. On success, the
59733 *                                     Table object is passed in as the
59734 *                                     first argument.
59735 * @param  {function}  [errorCallback] function to be executed if
59736 *                                     there is an error, response is passed
59737 *                                     in as first argument
59738 * @return {Object}
59738                    Table object containing data
59739 *
59740 * @example
59741 * <div class="norender">
59742 * <code>
59743 * // Given the following CSV file called "mammals.csv"
59744 * // located in the project's "assets" folder:
59745 * //
59746 * // id,species,name
59747 * // 0,Capra hircus,Goat
59748 * // 1,Panthera pardus,Leopard
59749 * // 2,Equus zebra,Zebra
59750 *
59751 * var table;
59752 *
59753 * function preload() {
59754 *   //my table is comma separated value "csv"
59755 *   //and has a header specifying the columns labels
59756 *   table = loadTable('assets/mammals.csv', 'csv', 'header');
59757 *   //the file can be remote
59758 *   //table = loadTable("http://p5js.org/reference/assets/mammals.csv",
59759 *   //                  "csv", "header");
59760 * }
59761 *
59762 * function setup() {
59763 *   //count the columns
59764 *   print(table.getRowCount() + ' total rows in table');
59765 *   print(table.getColumnCount() + ' total columns in table');
59766 *
59767 *   print(table.getColumn('name'));
59768 *   //["Goat", "Leopard", "Zebra"]
59769 *
59770 *   //cycle through the table
59771 *   for (var r = 0; r < table.getRowCount(); r++)
59772 *     for (var c = 0; c < table.getColumnCount(); c++) {
59773 *       print(table.getString(r, c));
59774 *     }
59775 * }
59776 * </code>
59777 * </div>
59778 *
59779 * @alt
59780 * randomly generated text from a file, for example "i smell like butter"
59781 * randomly generated text from a file, for example "i have three feet"
59782 *
59783 */
59784/**
59785 * @method loadTable
59786 * @param  {String}         filename
59787 * @param  {function}       [callback]
59788 * @param  {function}  [errorCallback]
59789 * @return {Object}
59790 */
59791p5.prototype.loadTable = function(path) {
59792  var callback;
59793  var errorCallback;
59794  var options = [];
59795  var header = false;
59796  var ext = path.substring(path.lastIndexOf('.') + 1, path.length);
59797  var sep = ',';
59798  var separatorSet = false;
59799
59800  if (ext === 'tsv') {
59801    //Only need to check extension is tsv because csv is default
59802    sep = '\t';
59803  }
59804
59805  for (var i = 1; i < arguments.length; i++) {
59806    if (typeof arguments[i] === 'function') {
59807      if (typeof callback === 'undefined') {
59808        callback = arguments[i];
59809      } else if (typeof errorCallback === 'undefined') {
59810        errorCallback = arguments[i];
59811      }
59812    } else if (typeof arguments[i] === 'string') {
59813      options.push(arguments[i]);
59814      if (arguments[i] === 'header') {
59815        header = true;
59816      }
59817      if (arguments[i] === 'csv') {
59818        if (separatorSet) {
59819          throw new Error('Cannot set multiple separator types.');
59820        } else {
59821          sep = ',';
59822          separatorSet = true;
59823        }
59824      } else if (arguments[i] === 'tsv') {
59825        if (separatorSet) {
59826          throw new Error('Cannot set multiple separator types.');
59827        } else {
59828          sep = '\t';
59829          separatorSet = true;
59830        }
59831      }
59832    }
59833  }
59834
59835  var t = new p5.Table();
59836
59837  var self = this;
59838  this.httpDo(
59839    path,
59840    'GET',
59841    'text',
59842    function(resp) {
59843      var state = {};
59844
59845      // define constants
59846      var PRE_TOKEN = 0,
59847        MID_TOKEN = 1,
59848        POST_TOKEN = 2,
59849        POST_RECORD = 4;
59850
59851      var QUOTE = '"',
59852        CR = '\r',
59853        LF = '\n';
59854
59855      var records = [];
59856      var offset = 0;
59857      var currentRecord = null;
59858      var currentChar;
59859
59860      var tokenBegin = function() {
59861        state.currentState = PRE_TOKEN;
59862        state.token = '';
59863      };
59864
59865      var tokenEnd = function() {
59866        currentRecord.push(state.token);
59867        tokenBegin();
59868      };
59869
59870      var recordBegin = function() {
59871        state.escaped = false;
59872        currentRecord = [];
59873        tokenBegin();
59874      };
59875
59876      var recordEnd = function() {
59877        state.currentState = POST_RECORD;
59878        records.push(currentRecord);
59879        currentRecord = null;
59880      };
59881
59882      for (;;) {
59883        currentChar = resp[offset++];
59884
59885        // EOF
59886        if (currentChar == null) {
59887          if (state.escaped) {
59888            throw new Error('Unclosed quote in file.');
59889          }
59890          if (currentRecord) {
59891            tokenEnd();
59892            recordEnd();
59893            break;
59894          }
59895        }
59896        if (currentRecord === null) {
59897          recordBegin();
59898        }
59899
59900        // Handle opening quote
59901        if (state.currentState === PRE_TOKEN) {
59902          if (currentChar === QUOTE) {
59903            state.escaped = true;
59904            state.currentState = MID_TOKEN;
59905            continue;
59906          }
59907          state.currentState = MID_TOKEN;
59908        }
59909
59910        // mid-token and escaped, look for sequences and end quote
59911        if (state.currentState === MID_TOKEN && state.escaped) {
59912          if (currentChar === QUOTE) {
59913            if (resp[offset] === QUOTE) {
59914              state.token += QUOTE;
59915              offset++;
59916            } else {
59917              state.escaped = false;
59918              state.currentState = POST_TOKEN;
59919            }
59920          } else if (currentChar === CR) {
59921            continue;
59922          } else {
59923            state.token += currentChar;
59924          }
59925          continue;
59926        }
59927
59928        // fall-through: mid-token or post-token, not escaped
59929        if (currentChar === CR) {
59930          if (resp[offset] === LF) {
59931            offset++;
59932          }
59933          tokenEnd();
59934          recordEnd();
59935        } else if (currentChar === LF) {
59936          tokenEnd();
59937          recordEnd();
59938        } else if (currentChar === sep) {
59939          tokenEnd();
59940        } else if (state.currentState === MID_TOKEN) {
59941          state.token += currentChar;
59942        }
59943      }
59944
59945      // set up column names
59946      if (header) {
59947        t.columns = records.shift();
59948      } else {
59949        for (i = 0; i < records[0].length; i++) {
59950          t.columns[i] = 'null';
59951        }
59952      }
59953      var row;
59954      for (i = 0; i < records.length; i++) {
59955        //Handles row of 'undefined' at end of some CSVs
59956        if (records[i].length === 1) {
59957          if (records[i][0] === 'undefined' || records[i][0] === '') {
59958            continue;
59959          }
59960        }
59961        row = new p5.TableRow();
59962        row.arr = records[i];
59963        row.obj = makeObject(records[i], t.columns);
59964        t.addRow(row);
59965      }
59966      if (typeof callback === 'function') {
59967        callback(t);
59968      }
59969
59970      self._decrementPreload();
59971    },
59972    function(err) {
59973      // Error handling
59974      p5._friendlyFileLoadError(2, path);
59975
59976      if (errorCallback) {
59977        errorCallback(err);
59978      } else {
59979        throw err;
59980      }
59981    }
59982  );
59983
59984  return t;
59985};
59986
59987// helper function to turn a row into a JSON object
59988function makeObject(row, headers) {
59989  var ret = {};
59990  headers = headers || [];
59991  if (typeof headers === 'undefined') {
59992    for (var j = 0; j < row.length; j++) {
59993      headers[j.toString()] = j;
59994    }
59995  }
59996  for (var i = 0; i < headers.length; i++) {
59997    var key = headers[i];
59998    var val = row[i];
59999    ret[key] = val;
60000  }
60001  return ret;
60002}
60003
60004function parseXML(two) {
60005  var one = new p5.XML();
60006  var children = two.childNodes;
60007  if (children && children.length) {
60008    for (var i = 0; i < children.length; i++) {
60009      var node = parseXML(children[i]);
60010      one.addChild(node);
60011    }
60012    one.setName(two.nodeName);
60013    one._setCont(two.textContent);
60014    one._setAttributes(two);
60015    for (var j = 0; j < one.children.length; j++) {
60016      one.children[j].parent = one;
60017    }
60018    return one;
60019  } else {
60020    one.setName(two.nodeName);
60021    one._setCont(two.textContent);
60022    one._setAttributes(two);
60023    return one;
60024  }
60025}
60026
60027/**
60028 * Reads the contents of a file and creates an XML object with its values.
60029 * If the name of the file is used as the parameter, as in the above example,
60030 * the file must be located in the sketch directory/folder.
60031 *
60032 * Alternatively, the file maybe be loaded from anywhere on the local
60033 * computer using an absolute path (something that starts with / on Unix and
60034 * Linux, or a drive letter on Windows), or the filename parameter can be a
60035 * URL for a file found on a network.
60036 *
60037 * This method is asynchronous, meaning it may not finish before the next
60038 * line in your sketch is executed. Calling loadXML() inside preload()
60039 * guarantees to complete the operation before setup() and draw() are called.
60040 *
60041 * Outside of preload(), you may supply a callback function to handle the
60042 * object.
60043 *
60044 * @method loadXML
60045 * @param  {String}   filename   name of the file or URL to load
60046 * @param  {function} [callback] function to be executed after loadXML()
60047 *                               completes, XML object is passed in as
60048 *                               first argument
60049 * @param  {function} [errorCallback] function to be executed if
60050 *                               there is an error, response is passed
60051 *                               in as first argument
60052 * @return {Object}              XML object containing data
60053 * @example
60054 * <div class='norender'><code>
60055 * // The following short XML file called "mammals.xml" is parsed
60056 * // in the code below.
60057 * //
60058 * // <?xml version="1.0"?>
60059 * // &lt;mammals&gt;
60060 * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
60061 * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
60062 * //   &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
60063 * // &lt;/mammals&gt;
60064 *
60065 * var xml;
60066 *
60067 * function preload() {
60068 *   xml = loadXML('assets/mammals.xml');
60069 * }
60070 *
60071 * function setup() {
60072 *   var children = xml.getChildren('animal');
60073 *
60074 *   for (var i = 0; i < children.length; i++) {
60075 *     var id = children[i].getNum('id');
60076 *     var coloring = children[i].getString('species');
60077 *     var name = children[i].getContent();
60078 *     print(id + ', ' + coloring + ', ' + name);
60079 *   }
60080 * }
60081 *
60082 * // Sketch prints:
60083 * // 0, Capra hircus, Goat
60084 * // 1, Panthera pardus, Leopard
60085 * // 2, Equus zebra, Zebra
60086 * </code></div>
60087 *
60088 * @alt
60089 * no image displayed
60090 *
60091 */
60092p5.prototype.loadXML = function() {
60093  var ret = {};
60094  var callback, errorCallback;
60095
60096  for (var i = 1; i < arguments.length; i++) {
60097    var arg = arguments[i];
60098    if (typeof arg === 'function') {
60099      if (typeof callback === 'undefined') {
60100        callback = arg;
60101      } else if (typeof errorCallback === 'undefined') {
60102        errorCallback = arg;
60103      }
60104    }
60105  }
60106
60107  var self = this;
60108  this.httpDo(
60109    arguments[0],
60110    'GET',
60111    'xml',
60112    function(xml) {
60113      for (var key in xml) {
60114        ret[key] = xml[key];
60115      }
60116      if (typeof callback !== 'undefined') {
60117        callback(ret);
60118      }
60119
60120      self._decrementPreload();
60121    },
60122    errorCallback
60123  );
60124
60125  return ret;
60126};
60127
60128/**
60129 * @method loadBytes
60130 * @param {string}   file            name of the file or URL to load
60131 * @param {function} [callback]      function to be executed after loadBytes()
60132 *                                    completes
60133 * @param {function} [errorCallback] function to be executed if there
60134 *                                    is an error
60135 * @returns {Object} an object whose 'bytes' property will be the loaded buffer
60136 *
60137 * @example
60138 * <div class='norender'><code>
60139 * var data;
60140 *
60141 * function preload() {
60142 *   data = loadBytes('assets/mammals.xml');
60143 * }
60144 *
60145 * function setup() {
60146 *   for (var i = 0; i < 5; i++) {
60147 *     console.log(data.bytes[i].toString(16));
60148 *   }
60149 * }
60150 * </code></div>
60151 *
60152 * @alt
60153 * no image displayed
60154 *
60155 */
60156p5.prototype.loadBytes = function(file, callback, errorCallback) {
60157  var ret = {};
60158
60159  var self = this;
60160  this.httpDo(
60161    file,
60162    'GET',
60163    'arrayBuffer',
60164    function(arrayBuffer) {
60165      ret.bytes = new Uint8Array(arrayBuffer);
60166
60167      if (typeof callback === 'function') {
60168        callback(ret);
60169      }
60170
60171      self._decrementPreload();
60172    },
60173    errorCallback
60174  );
60175  return ret;
60176};
60177
60178/**
60179 * Method for executing an HTTP GET request. If data type is not specified,
60180 * p5 will try to guess based on the URL, defaulting to text. This is equivalent to
60181 * calling <code>httpDo(path, 'GET')</code>. The 'binary' datatype will return
60182 * a Blob object, and the 'arrayBuffer' datatype will return an ArrayBuffer
60183 * which can be used to initialize typed arrays (such as Uint8Array).
60184 *
60185 * @method httpGet
60186 * @param  {String}        path       name of the file or url to load
60187 * @param  {String}        [datatype] "json", "jsonp", "binary", "arrayBuffer",
60188 *                                    "xml", or "text"
60189 * @param  {Object|Boolean} [data]    param data passed sent with request
60190 * @param  {function}      [callback] function to be executed after
60191 *                                    httpGet() completes, data is passed in
60192 *                                    as first argument
60193 * @param  {function}      [errorCallback] function to be executed if
60194 *                                    there is an error, response is passed
60195 *                                    in as first argument
60196 * @example
60197 * <div class='norender'><code>
60198 * // Examples use USGS Earthquake API:
60199 * //   https://earthquake.usgs.gov/fdsnws/event/1/#methods
60200 * var earthquakes;
60201 * function preload() {
60202 *   // Get the most recent earthquake in the database
60203 *   var url =
60204    'https://earthquake.usgs.gov/fdsnws/event/1/query?' +
60205 *     'format=geojson&limit=1&orderby=time';
60206 *   httpGet(url, 'jsonp', false, function(response) {
60207 *     // when the HTTP request completes, populate the variable that holds the
60208 *     // earthquake data used in the visualization.
60209 *     earthquakes = response;
60210 *   });
60211 * }
60212 *
60213 * function draw() {
60214 *   if (!earthquakes) {
60215 *     // Wait until the earthquake data has loaded before drawing.
60216 *     return;
60217 *   }
60218 *   background(200);
60219 *   // Get the magnitude and name of the earthquake out of the loaded JSON
60220 *   var earthquakeMag = earthquakes.features[0].properties.mag;
60221 *   var earthquakeName = earthquakes.features[0].properties.place;
60222 *   ellipse(width / 2, height / 2, earthquakeMag * 10, earthquakeMag * 10);
60223 *   textAlign(CENTER);
60224 *   text(earthquakeName, 0, height - 30, width, 30);
60225 *   noLoop();
60226 * }
60227 * </code></div>
60228 */
60229/**
60230 * @method httpGet
60231 * @param  {String}        path
60232 * @param  {Object|Boolean} data
60233 * @param  {function}      [callback]
60234 * @param  {function}      [errorCallback]
60235 */
60236/**
60237 * @method httpGet
60238 * @param  {String}        path
60239 * @param  {function}      callback
60240 * @param  {function}      [errorCallback]
60241 */
60242p5.prototype.httpGet = function() {
60243  p5._validateParameters('httpGet', arguments);
60244
60245  var args = Array.prototype.slice.call(arguments);
60246  args.splice(1, 0, 'GET');
60247  p5.prototype.httpDo.apply(this, args);
60248};
60249
60250/**
60251 * Method for executing an HTTP POST request. If data type is not specified,
60252 * p5 will try to guess based on the URL, defaulting to text. This is equivalent to
60253 * calling <code>httpDo(path, 'POST')</code>.
60254 *
60255 * @method httpPost
60256 * @param  {String}        path       name of the file or url to load
60257 * @param  {String}        [datatype] "json", "jsonp", "xml", or "text".
60258 *                                    If omitted, httpPost() will guess.
60259 * @param  {Object|Boolean} [data]    param data passed sent with request
60260 * @param  {function}      [callback] function to be executed after
60261 *                                    httpPost() completes, data is passed in
60262 *                                    as first argument
60263 * @param  {function}      [errorCallback] function to be executed if
60264 *                                    there is an error, response is passed
60265 *                                    in as first argument
60266 *
60267 * @example
60268 * <div>
60269 * <code>
60270 * // Examples use jsonplaceholder.typicode.com for a Mock Data API
60271 *
60272 * var url = 'https://jsonplaceholder.typicode.com/posts';
60273 * var postData = { userId: 1, title: 'p5 Clicked!', body: 'p5.js is way cool.' };
60274 *
60275 * function setup() {
60276 *   createCanvas(800, 800);
60277 * }
60278 *
60279 * function mousePressed() {
60280 *   // Pick new random color values
60281 *   var r = random(255);
60282 *   var g = random(255);
60283 *   var b = random(255);
60284 *
60285 *   httpPost(url, 'json', postData, function(result) {
60286 *     strokeWeight(2);
60287 *     stroke(r, g, b);
60288 *     fill(r, g, b, 127);
60289 *     ellipse(mouseX, mouseY, 200, 200);
60290 *     text(result.body, mouseX, mouseY);
60291 *   });
60292 * }
60293 * </code>
60294 * </div>
60295 *
60296 *
60297 * <div><code>
60298 * var url = 'https://invalidURL'; // A bad URL that will cause errors
60299 * var postData = { title: 'p5 Clicked!', body: 'p5.js is way cool.' };
60300 *
60301 * function setup() {
60302 *   createCanvas(800, 800);
60303 * }
60304 *
60305 * function mousePressed() {
60306 *   // Pick new random color values
60307 *   var r = random(255);
60308 *   var g = random(255);
60309 *   var b = random(255);
60310 *
60311 *   httpPost(
60312 *     url,
60313 *     'json',
60314 *     postData,
60315 *     function(result) {
60316 *       // ... won't be called
60317 *     },
60318 *     function(error) {
60319 *       strokeWeight(2);
60320 *       stroke(r, g, b);
60321 *       fill(r, g, b, 127);
60322 *       text(error.toString(), mouseX, mouseY);
60323 *     }
60324 *   );
60325 * }
60326 * </code></div>
60327 *
60328 */
60329/**
60330 * @method httpPost
60331 * @param  {String}        path
60332 * @param  {Object|Boolean} data
60333 * @param  {function}      [callback]
60334 * @param  {function}      [errorCallback]
60335 */
60336/**
60337 * @method httpPost
60338 * @param  {String}        path
60339 * @param  {function}      callback
60340 * @param  {function}      [errorCallback]
60341 */
60342p5.prototype.httpPost = function() {
60343  p5._validateParameters('httpPost', arguments);
60344
60345  var args = Array.prototype.slice.call(arguments);
60346  args.splice(1, 0, 'POST');
60347  p5.prototype.httpDo.apply(this, args);
60348};
60349
60350/**
60351 * Method for executing an HTTP request. If data type is not specified,
60352 * p5 will try to guess based on the URL, defaulting to text.<br><br>
60353 * For more advanced use, you may also pass in the path as the first argument
60354 * and a object as the second argument, the signature follows the one specified
60355 * in the Fetch API specification.
60356 *
60357 * @method httpDo
60358 * @param  {String}        path       name of the file or url to load
60359 * @param  {String}        [method]   either "GET", "POST", or "PUT",
60360 *                                    defaults to "GET"
60361 * @param  {String}        [datatype] "json", "jsonp", "xml", or "text"
60362 * @param  {Object}        [data]     param data passed sent with request
60363 * @param  {function}      [callback] function to be executed after
60364 *                                    httpGet() completes, data is passed in
60365 *                                    as first argument
60366 * @param  {function}      [errorCallback] function to be executed if
60367 *                                    there is an error, response is passed
60368 *                                    in as first argument
60369 *
60370 *
60371 * @example
60372 * <div>
60373 * <code>
60374 * // Examples use USGS Earthquake API:
60375 * // https://earthquake.usgs.gov/fdsnws/event/1/#methods
60376 *
60377 * // displays an animation of all USGS earthquakes
60378 * var earthquakes;
60379 * var eqFeatureIndex = 0;
60380 *
60381 * function preload() {
60382 *   var url = 'https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson';
60383 *   httpDo(
60384 *     url,
60385 *     {
60386 *       method: 'GET',
60387 *       // Other Request options, like special headers for apis
60388 *       headers: { authorization: 'Bearer secretKey' }
60389 *     },
60390 *     function(res) {
60391 *       earthquakes = res;
60392 *     }
60393 *   );
60394 * }
60395 *
60396 * function draw() {
60397 *   // wait until the data is loaded
60398 *   if (!earthquakes || !earthquakes.features[eqFeatureIndex]) {
60399 *     return;
60400 *   }
60401 *   clear();
60402 *
60403 *   var feature = earthquakes.features[eqFeatureIndex];
60404 *   var mag = feature.properties.mag;
60405 *   var rad = mag / 11 * ((width + height) / 2);
60406 *   fill(255, 0, 0, 100);
60407 *   ellipse(width / 2 + random(-2, 2), height / 2 + random(-2, 2), rad, rad);
60408 *
60409 *   if (eqFeatureIndex >= earthquakes.features.length) {
60410 *     eqFeatureIndex = 0;
60411 *   } else {
60412 *     eqFeatureIndex += 1;
60413 *   }
60414 * }
60415 * </code>
60416 * </div>
60417 */
60418/**
60419 * @method httpDo
60420 * @param  {String}        path
60421 * @param  {Object}        options   Request object options as documented in the
60422 *                                    "fetch" API
60423 * <a href="https://developer.mozilla.org/en/docs/Web/API/Fetch_API">reference</a>
60424 * @param  {function}      [callback]
60425 * @param  {function}      [errorCallback]
60426 */
60427p5.prototype.httpDo = function() {
60428  var type;
60429  var callback;
60430  var errorCallback;
60431  var request;
60432  var jsonpOptions = {};
60433  var cbCount = 0;
60434  var contentType = 'text/plain';
60435  // Trim the callbacks off the end to get an idea of how many arguments are passed
60436  for (var i = arguments.length - 1; i > 0; i--) {
60437    if (typeof arguments[i] === 'function') {
60438      cbCount++;
60439    } else {
60440      break;
60441    }
60442  }
60443  // The number of arguments minus callbacks
60444  var argsCount = arguments.length - cbCount;
60445  var path = arguments[0];
60446  if (
60447    argsCount === 2 &&
60448    typeof path === 'string' &&
60449    typeof arguments[1] === 'object'
60450  ) {
60451    // Intended for more advanced use, pass in Request parameters directly
60452    request = new Request(path, arguments[1]);
60453    callback = arguments[2];
60454    errorCallback = arguments[3];
60455  } else {
60456    // Provided with arguments
60457    var method = 'GET';
60458    var data;
60459
60460    for (var j = 1; j < arguments.length; j++) {
60461      var a = arguments[j];
60462      if (typeof a === 'string') {
60463        if (a === 'GET' || a === 'POST' || a === 'PUT' || a === 'DELETE') {
60464          method = a;
60465        } else if (
60466          a === 'json' ||
60467          a === 'jsonp' ||
60468          a === 'binary' ||
60469          a === 'arrayBuffer' ||
60470          a === 'xml' ||
60471          a === 'text'
60472        ) {
60473          type = a;
60474        } else {
60475          data = a;
60476        }
60477      } else if (typeof a === 'number') {
60478        data = a.toString();
60479      } else if (typeof a === 'object') {
60480        if (a.hasOwnProperty('jsonpCallback')) {
60481          for (var attr in a) {
60482            jsonpOptions[attr] = a[attr];
60483          }
60484        } else {
60485          data = JSON.stringify(a);
60486          contentType = 'application/json';
60487        }
60488      } else if (typeof a === 'function') {
60489        if (!callback) {
60490          callback = a;
60491        } else {
60492          errorCallback = a;
60493        }
60494      }
60495    }
60496
60497    request = new Request(path, {
60498      method: method,
60499      mode: 'cors',
60500      body: data,
60501      headers: new Headers({
60502        'Content-Type': contentType
60503      })
60504    });
60505  }
60506
60507  // do some sort of smart type checking
60508  if (!type) {
60509    if (path.indexOf('json') !== -1) {
60510      type = 'json';
60511    } else if (path.indexOf('xml') !== -1) {
60512      type = 'xml';
60513    } else {
60514      type = 'text';
60515    }
60516  }
60517
60518  (type === 'jsonp' ? fetchJsonp(path, jsonpOptions) : fetch(request))
60519    .then(function(res) {
60520      if (!res.ok) throw res;
60521
60522      switch (type) {
60523        case 'json':
60524          return res.json();
60525        case 'binary':
60526          return res.blob();
60527        case 'arrayBuffer':
60528          return res.arrayBuffer();
60529        case 'xml':
60530          return res.text().then(function(text) {
60531            var parser = new DOMParser();
60532            var xml = parser.parseFromString(text, 'text/xml');
60533            return parseXML(xml.documentElement);
60534          });
60535        default:
60536          return res.text();
60537      }
60538    })
60539    .then(callback || function() {})
60540    .catch(errorCallback || console.error);
60541};
60542
60543/**
60544 * @module IO
60545 * @submodule Output
60546 * @for p5
60547 */
60548
60549window.URL = window.URL || window.webkitURL;
60550
60551// private array of p5.PrintWriter objects
60552p5.prototype._pWriters = [];
60553
60554/**
60555 * @method createWriter
60556 * @param {String} name name of the file to be created
60557 * @param {String} [extension]
60558 * @return {p5.PrintWriter}
60559 * @example
60560 * <div>
60561 * <code>
60562 * createButton('save')
60563 *   .position(10, 10)
60564 *   .mousePressed(function() {
60565 *     var writer = createWriter('squares.txt');
60566 *     for (var i = 0; i < 10; i++) {
60567 *       writer.print(i * i);
60568 *     }
60569 *     writer.close();
60570 *     writer.clear();
60571 *   });
60572 * </code>
60573 * </div>
60574 */
60575p5.prototype.createWriter = function(name, extension) {
60576  var newPW;
60577  // check that it doesn't already exist
60578  for (var i in p5.prototype._pWriters) {
60579    if (p5.prototype._pWriters[i].name === name) {
60580      // if a p5.PrintWriter w/ this name already exists...
60581      // return p5.prototype._pWriters[i]; // return it w/ contents intact.
60582      // or, could return a new, empty one with a unique name:
60583      newPW = new p5.PrintWriter(name + this.millis(), extension);
60584      p5.prototype._pWriters.push(newPW);
60585      return newPW;
60586    }
60587  }
60588  newPW = new p5.PrintWriter(name, extension);
60589  p5.prototype._pWriters.push(newPW);
60590  return newPW;
60591};
60592
60593/**
60594 *  @class p5.PrintWriter
60595 *  @param  {String}     filename
60596 *  @param  {String}     [extension]
60597 */
60598p5.PrintWriter = function(filename, extension) {
60599  var self = this;
60600  this.name = filename;
60601  this.content = '';
60602  //Changed to write because it was being overloaded by function below.
60603  /**
60604   * Writes data to the PrintWriter stream
60605   * @method write
60606   * @param {Array} data all data to be written by the PrintWriter
60607   * @example
60608   * <div class="norender notest">
60609   * <code>
60610   * // creates a file called 'newFile.txt'
60611   * var writer = createWriter('newFile.txt');
60612   * // write 'Hello world!'' to the file
60613   * writer.write(['Hello world!']);
60614   * // close the PrintWriter and save the file
60615   * writer.close();
60616   * </code>
60617   * </div>
60618   * <div class='norender notest'>
60619   * <code>
60620   * // creates a file called 'newFile2.txt'
60621   * var writer = createWriter('newFile2.txt');
60622   * // write 'apples,bananas,123' to the file
60623   * writer.write(['apples', 'bananas', 123]);
60624   * // close the PrintWriter and save the file
60625   * writer.close();
60626   * </code>
60627   * </div>
60628   * <div class='norender notest'>
60629   * <code>
60630   * // creates a file called 'newFile3.txt'
60631   * var writer = createWriter('newFile3.txt');
60632   * // write 'My name is: Teddy' to the file
60633   * writer.write('My name is:');
60634   * writer.write(' Teddy');
60635   * // close the PrintWriter and save the file
60636   * writer.close();
60637   * </code>
60638   * </div>
60639   */
60640  this.write = function(data) {
60641    this.content += data;
60642  };
60643  /**
60644   * Writes data to the PrintWriter stream, and adds a new line at the end
60645   * @method print
60646   * @param {Array} data all data to be printed by the PrintWriter
60647   * @example
60648   * <div class='norender notest'>
60649   * <code>
60650   * // creates a file called 'newFile.txt'
60651   * var writer = createWriter('newFile.txt');
60652   * // creates a file containing
60653   * //  My name is:
60654   * //  Teddy
60655   * writer.print('My name is:');
60656   * writer.print('Teddy');
60657   * // close the PrintWriter and save the file
60658   * writer.close();
60659   * </code>
60660   * </div>
60661   * <div class='norender notest'>
60662   * <code>
60663   * var writer;
60664   *
60665   * function setup() {
60666   *   createCanvas(400, 400);
60667   *   // create a PrintWriter
60668   *   writer = createWriter('newFile.txt');
60669   * }
60670   *
60671   * function draw() {
60672   *   // print all mouseX and mouseY coordinates to the stream
60673   *   writer.print([mouseX, mouseY]);
60674   * }
60675   *
60676   * function mouseClicked() {
60677   *   // close the PrintWriter and save the file
60678   *   writer.close();
60679   * }
60680   * </code>
60681   * </div>
60682   */
60683  this.print = function(data) {
60684    this.content += data + '\n';
60685  };
60686  /**
60687   * Clears the data already written to the PrintWriter object
60688   * @method clear
60689   * @example
60690   * <div class ="norender notest"><code>
60691   * // create writer object
60692   * var writer = createWriter('newFile.txt');
60693   * writer.write(['clear me']);
60694   * // clear writer object here
60695   * writer.clear();
60696   * // close writer
60697   * writer.close();
60698   * </code></div>
60699   *
60700   */
60701  this.clear = function() {
60702    this.content = '';
60703  };
60704  /**
60705   * Closes the PrintWriter
60706   * @method close
60707   * @example
60708   * <div class="norender notest">
60709   * <code>
60710   * // create a file called 'newFile.txt'
60711   * var writer = createWriter('newFile.txt');
60712   * // close the PrintWriter and save the file
60713   * writer.close();
60714   * </code>
60715   * </div>
60716   * <div class='norender notest'>
60717   * <code>
60718   * // create a file called 'newFile2.txt'
60719   * var writer = createWriter('newFile2.txt');
60720   * // write some data to the file
60721   * writer.write([100, 101, 102]);
60722   * // close the PrintWriter and save the file
60723   * writer.close();
60724   * </code>
60725   * </div>
60726   */
60727  this.close = function() {
60728    // convert String to Array for the writeFile Blob
60729    var arr = [];
60730    arr.push(this.content);
60731    p5.prototype.writeFile(arr, filename, extension);
60732    // remove from _pWriters array and delete self
60733    for (var i in p5.prototype._pWriters) {
60734      if (p5.prototype._pWriters[i].name === this.name) {
60735        // remove from _pWriters array
60736        p5.prototype._pWriters.splice(i, 1);
60737      }
60738    }
60739    self.clear();
60740    self = {};
60741  };
60742};
60743
60744/**
60745 * @module IO
60746 * @submodule Output
60747 * @for p5
60748 */
60749
60750// object, filename, options --> saveJSON, saveStrings,
60751// filename, [extension] [canvas] --> saveImage
60752
60753/**
60754 *  <p>Save an image, text, json, csv, wav, or html. Prompts download to
60755 *  the client's computer. <b>Note that it is not recommended to call save()
60756 *  within draw if it's looping, as the save() function will open a new save
60757 *  dialog every frame.</b></p>
60758 *  <p>The default behavior is to save the canvas as an image. You can
60759 *  optionally specify a filename.
60760 *  For example:</p>
60761 * <pre class='language-javascript'><code>
60762 * save();
60763 * save('myCanvas.jpg'); // save a specific canvas with a filename
60764 * </code></pre>
60765 *
60766 *  <p>Alternately, the first parameter can be a pointer to a canvas
60767 *  p5.Element, an Array of Strings,
60768 *  an Array of JSON, a JSON object, a p5.Table, a p5.Image, or a
60769 *  p5.SoundFile (requires p5.sound). The second parameter is a filename
60770 *  (including extension). The third parameter is for options specific
60771 *  to this type of object. This method will save a file that fits the
60772 *  given paramaters. For example:</p>
60773 *
60774 * <pre class='language-javascript'><code>
60775 * // Saves canvas as an image
60776 * save('myCanvas.jpg');
60777 *
60778 * // Saves pImage as a png image
60779 * var img = createImage(10, 10);
60780 * save(img, 'my.png');
60781 *
60782 * // Saves canvas as an image
60783 * var cnv = createCanvas(100, 100);
60784 * save(cnv, 'myCanvas.jpg');
60785 *
60786 * // Saves p5.Renderer object as an image
60787 * var gb = createGraphics(100, 100);
60788 * save(gb, 'myGraphics.jpg');
60789 *
60790 * var myTable = new p5.Table();
60791 *
60792 * // Saves table as html file
60793 * save(myTable, 'myTable.html');
60794 *
60795 * // Comma Separated Values
60796 * save(myTable, 'myTable.csv');
60797 *
60798 * // Tab Separated Values
60799 * save(myTable, 'myTable.tsv');
60800 *
60801 * var myJSON = { a: 1, b: true };
60802 *
60803 * // Saves pretty JSON
60804 * save(myJSON, 'my.json');
60805 *
60806 * // Optimizes JSON filesize
60807 * save(myJSON, 'my.json', true);
60808 *
60809 * // Saves array of strings to a text file with line breaks after each item
60810 * var arrayOfStrings = ['a', 'b'];
60811 * save(arrayOfStrings, 'my.txt');
60812 * </code></pre>
60813 *
60814 *  @method save
60815 *  @param  {Object|String} [objectOrFilename]  If filename is provided, will
60816 *                                             save canvas as an image with
60817 *                                             either png or jpg extension
60818 *                                             depending on the filename.
60819 *                                             If object is provided, will
60820 *                                             save depending on the object
60821 *                                             and filename (see examples
60822 *                                             above).
60823 *  @param  {String} [filename] If an object is provided as the first
60824 *                               parameter, then the second parameter
60825 *                               indicates the filename,
60826 *                               and should include an appropriate
60827 *                               file extension (see examples above).
60828 *  @param  {Boolean|String} [options]  Additional options depend on
60829 *                            filetype. For example, when saving JSON,
60830 *                            <code>true</code> indicates that the
60831 *                            output will be optimized for filesize,
60832 *                            rather than readability.
60833 */
60834p5.prototype.save = function(object, _filename, _options) {
60835  // parse the arguments and figure out which things we are saving
60836  var args = arguments;
60837  // =================================================
60838  // OPTION 1: saveCanvas...
60839
60840  // if no arguments are provided, save canvas
60841  var cnv = this._curElement.elt;
60842  if (args.length === 0) {
60843    p5.prototype.saveCanvas(cnv);
60844    return;
60845  } else if (args[0] instanceof p5.Renderer || args[0] instanceof p5.Graphics) {
60846    // otherwise, parse the arguments
60847
60848    // if first param is a p5Graphics, then saveCanvas
60849    p5.prototype.saveCanvas(args[0].elt, args[1], args[2]);
60850    return;
60851  } else if (args.length === 1 && typeof args[0] === 'string') {
60852    // if 1st param is String and only one arg, assume it is canvas filename
60853    p5.prototype.saveCanvas(cnv, args[0]);
60854  } else {
60855    // =================================================
60856    // OPTION 2: extension clarifies saveStrings vs. saveJSON
60857    var extension = _checkFileExtension(args[1], args[2])[1];
60858    switch (extension) {
60859      case 'json':
60860        p5.prototype.saveJSON(args[0], args[1], args[2]);
60861        return;
60862      case 'txt':
60863        p5.prototype.saveStrings(args[0], args[1], args[2]);
60864        return;
60865      // =================================================
60866      // OPTION 3: decide based on object...
60867      default:
60868        if (args[0] instanceof Array) {
60869          p5.prototype.saveStrings(args[0], args[1], args[2]);
60870        } else if (args[0] instanceof p5.Table) {
60871          p5.prototype.saveTable(args[0], args[1], args[2]);
60872        } else if (args[0] instanceof p5.Image) {
60873          p5.prototype.saveCanvas(args[0].canvas, args[1]);
60874        } else if (args[0] instanceof p5.SoundFile) {
60875          p5.prototype.saveSound(args[0], args[1], args[2], args[3]);
60876        }
60877    }
60878  }
60879};
60880
60881/**
60882 *  Writes the contents of an Array or a JSON object to a .json file.
60883 *  The file saving process and location of the saved file will
60884 *  vary between web browsers.
60885 *
60886 *  @method saveJSON
60887 *  @param  {Array|Object} json
60888 *  @param  {String} filename
60889 *  @param  {Boolean} [optimize]   If true, removes line breaks
60890 *                                 and spaces from the output
60891 *                                 file to optimize filesize
60892 *                                 (but not readability).
60893 *  @example
60894 * <div><code>
60895 * var json = {}; // new  JSON Object
60896 *
60897 * json.id = 0;
60898 * json.species = 'Panthera leo';
60899 * json.name = 'Lion';
60900 *
60901 * createButton('save')
60902 *   .position(10, 10)
60903 *   .mousePressed(function() {
60904 *     saveJSON(json, 'lion.json');
60905 *   });
60906 *
60907 * // saves the following to a file called "lion.json":
60908 * // {
60909 * //   "id": 0,
60910 * //   "species": "Panthera leo",
60911 * //   "name": "Lion"
60912 * // }
60913 * </code></div>
60914 *
60915 * @alt
60916 * no image displayed
60917 *
60918 */
60919p5.prototype.saveJSON = function(json, filename, opt) {
60920  p5._validateParameters('saveJSON', arguments);
60921  var stringify;
60922  if (opt) {
60923    stringify = JSON.stringify(json);
60924  } else {
60925    stringify = JSON.stringify(json, undefined, 2);
60926  }
60927  this.saveStrings(stringify.split('\n'), filename, 'json');
60928};
60929
60930p5.prototype.saveJSONObject = p5.prototype.saveJSON;
60931p5.prototype.saveJSONArray = p5.prototype.saveJSON;
60932
60933/**
60934 *  Writes an array of Strings to a text file, one line per String.
60935 *  The file saving process and location of the saved file will
60936 *  vary between web browsers.
60937 *
60938 *  @method saveStrings
60939 *  @param  {String[]} list   string array to be written
60940 *  @param  {String} filename filename for output
60941 *  @param  {String} [extension] the filename's extension
60942 *  @example
60943 * <div><code>
60944 * var words = 'apple bear cat dog';
60945 *
60946 * // .split() outputs an Array
60947 * var list = split(words, ' ');
60948 *
60949 * createButton('save')
60950 *   .position(10, 10)
60951 *   .mousePressed(function() {
60952 *     saveStrings(list, 'nouns.txt');
60953 *   });
60954 *
60955 * // Saves the following to a file called 'nouns.txt':
60956 * //
60957 * // apple
60958 * // bear
60959 * // cat
60960 * // dog
60961 * </code></div>
60962 *
60963 * @alt
60964 * no image displayed
60965 *
60966 */
60967p5.prototype.saveStrings = function(list, filename, extension) {
60968  p5._validateParameters('saveStrings', arguments);
60969  var ext = extension || 'txt';
60970  var pWriter = this.createWriter(filename, ext);
60971  for (var i = 0; i < list.length; i++) {
60972    if (i < list.length - 1) {
60973      pWriter.print(list[i]);
60974    } else {
60975      pWriter.print(list[i]);
60976    }
60977  }
60978  pWriter.close();
60979  pWriter.clear();
60980};
60981
60982// =======
60983// HELPERS
60984// =======
60985
60986function escapeHelper(content) {
60987  return content
60988    .replace(/&/g, '&amp;')
60989    .replace(/</g, '&lt;')
60990    .replace(/>/g, '&gt;')
60991    .replace(/"/g, '&quot;')
60992    .replace(/'/g, '&#039;');
60993}
60994
60995/**
60996 *  Writes the contents of a Table object to a file. Defaults to a
60997 *  text file with comma-separated-values ('csv') but can also
60998 *  use tab separation ('tsv'), or generate an HTML table ('html').
60999 *  The file saving process and location of the saved file will
61000 *  vary between web browsers.
61001 *
61002 *  @method saveTable
61003 *  @param  {p5.Table} Table  the Table object to save to a file
61004 *  @param  {String} filename the filename to which the Table should be saved
61005 *  @param  {String} [options]  can be one of "tsv", "csv", or "html"
61006 *  @example
61007 *  <div><code>
61008 * var table;
61009 *
61010 * function setup() {
61011 *   table = new p5.Table();
61012 *
61013 *   table.addColumn('id');
61014 *   table.addColumn('species');
61015 *   table.addColumn('name');
61016 *
61017 *   var newRow = table.addRow();
61018 *   newRow.setNum('id', table.getRowCount() - 1);
61019 *   newRow.setString('species', 'Panthera leo');
61020 *   newRow.setString('name', 'Lion');
61021 *
61022 *   // To save, un-comment next line then click 'run'
61023 *   // saveTable(table, 'new.csv');
61024 * }
61025 *
61026 * // Saves the following to a file called 'new.csv':
61027 * // id,species,name
61028 * // 0,Panthera leo,Lion
61029 * </code></div>
61030 *
61031 * @alt
61032 * no image displayed
61033 *
61034 */
61035p5.prototype.saveTable = function(table, filename, options) {
61036  p5._validateParameters('saveTable', arguments);
61037  var ext;
61038  if (options === undefined) {
61039    ext = filename.substring(filename.lastIndexOf('.') + 1, filename.length);
61040  } else {
61041    ext = options;
61042  }
61043  var pWriter = this.createWriter(filename, ext);
61044
61045  var header = table.columns;
61046
61047  var sep = ','; // default to CSV
61048  if (ext === 'tsv') {
61049    sep = '\t';
61050  }
61051  if (ext !== 'html') {
61052    // make header if it has values
61053    if (header[0] !== '0') {
61054      for (var h = 0; h < header.length; h++) {
61055        if (h < header.length - 1) {
61056          pWriter.write(header[h] + sep);
61057        } else {
61058          pWriter.write(header[h]);
61059        }
61060      }
61061      pWriter.write('\n');
61062    }
61063
61064    // make rows
61065    for (var i = 0; i < table.rows.length; i++) {
61066      var j;
61067      for (j = 0; j < table.rows[i].arr.length; j++) {
61068        if (j < table.rows[i].arr.length - 1) {
61069          pWriter.write(table.rows[i].arr[j] + sep);
61070        } else if (i < table.rows.length - 1) {
61071          pWriter.write(table.rows[i].arr[j]);
61072        } else {
61073          pWriter.write(table.rows[i].arr[j]);
61074        }
61075      }
61076      pWriter.write('\n');
61077    }
61078  } else {
61079    // otherwise, make HTML
61080    pWriter.print('<html>');
61081    pWriter.print('<head>');
61082    var str = '  <meta http-equiv="content-type" content';
61083    str += '="text/html;charset=utf-8" />';
61084    pWriter.print(str);
61085    pWriter.print('</head>');
61086
61087    pWriter.print('<body>');
61088    pWriter.print('  <table>');
61089
61090    // make header if it has values
61091    if (header[0] !== '0') {
61092      pWriter.print('    <tr>');
61093      for (var k = 0; k < header.length; k++) {
61094        var e = escapeHelper(header[k]);
61095        pWriter.print('      <td>' + e);
61096        pWriter.print('      </td>');
61097      }
61098      pWriter.print('    </tr>');
61099    }
61100
61101    // make rows
61102    for (var row = 0; row < table.rows.length; row++) {
61103      pWriter.print('    <tr>');
61104      for (var col = 0; col < table.columns.length; col++) {
61105        var entry = table.rows[row].getString(col);
61106        var htmlEntry = escapeHelper(entry);
61107        pWriter.print('      <td>' + htmlEntry);
61108        pWriter.print('      </td>');
61109      }
61110      pWriter.print('    </tr>');
61111    }
61112    pWriter.print('  </table>');
61113    pWriter.print('</body>');
61114    pWriter.print('</html>');
61115  }
61116  // close and clear the pWriter
61117  pWriter.close();
61118  pWriter.clear();
61119}; // end saveTable()
61120
61121/**
61122 *  Generate a blob of file data as a url to prepare for download.
61123 *  Accepts an array of data, a filename, and an extension (optional).
61124 *  This is a private function because it does not do any formatting,
61125 *  but it is used by saveStrings, saveJSON, saveTable etc.
61126 *
61127 *  @param  {Array} dataToDownload
61128 *  @param  {String} filename
61129 *  @param  {String} [extension]
61130 *  @private
61131 */
61132p5.prototype.writeFile = function(dataToDownload, filename, extension) {
61133  var type = 'application/octet-stream';
61134  if (p5.prototype._isSafari()) {
61135    type = 'text/plain';
61136  }
61137  var blob = new Blob(dataToDownload, {
61138    type: type
61139  });
61140  p5.prototype.downloadFile(blob, filename, extension);
61141};
61142
61143/**
61144 *  Forces download. Accepts a url to filedata/blob, a filename,
61145 *  and an extension (optional).
61146 *  This is a private function because it does not do any formatting,
61147 *  but it is used by saveStrings, saveJSON, saveTable etc.
61148 *
61149 *  @method downloadFile
61150 *  @private
61151 *  @param  {String|Blob} data    either an href generated by createObjectURL,
61152 *                                or a Blob object containing the data
61153 *  @param  {String} [filename]
61154 *  @param  {String} [extension]
61155 */
61156p5.prototype.downloadFile = function(data, fName, extension) {
61157  var fx = _checkFileExtension(fName, extension);
61158  var filename = fx[0];
61159
61160  if (data instanceof Blob) {
61161    var fileSaver = _dereq_('file-saver');
61162    fileSaver.saveAs(data, filename);
61163    return;
61164  }
61165
61166  var a = document.createElement('a');
61167  a.href = data;
61168  a.download = filename;
61169
61170  // Firefox requires the link to be added to the DOM before click()
61171  a.onclick = function(e) {
61172    destroyClickedElement(e);
61173    e.stopPropagation();
61174  };
61175
61176  a.style.display = 'none';
61177  document.body.appendChild(a);
61178
61179  // Safari will open this file in the same page as a confusing Blob.
61180  if (p5.prototype._isSafari()) {
61181    var aText = 'Hello, Safari user! To download this file...\n';
61182    aText += '1. Go to File --> Save As.\n';
61183    aText += '2. Choose "Page Source" as the Format.\n';
61184    aText += '3. Name it with this extension: ."' + fx[1] + '"';
61185    alert(aText);
61186  }
61187  a.click();
61188};
61189
61190/**
61191 *  Returns a file extension, or another string
61192 *  if the provided parameter has no extension.
61193 *
61194 *  @param   {String} filename
61195 *  @param   {String} [extension]
61196 *  @return  {String[]} [fileName, fileExtension]
61197 *
61198 *  @private
61199 */
61200function _checkFileExtension(filename, extension) {
61201  if (!extension || extension === true || extension === 'true') {
61202    extension = '';
61203  }
61204  if (!filename) {
61205    filename = 'untitled';
61206  }
61207  var ext = '';
61208  // make sure the file will have a name, see if filename needs extension
61209  if (filename && filename.indexOf('.') > -1) {
61210    ext = filename.split('.').pop();
61211  }
61212  // append extension if it doesn't exist
61213  if (extension) {
61214    if (ext !== extension) {
61215      ext = extension;
61216      filename = filename + '.' + ext;
61217    }
61218  }
61219  return [filename, ext];
61220}
61221p5.prototype._checkFileExtension = _checkFileExtension;
61222
61223/**
61224 *  Returns true if the browser is Safari, false if not.
61225 *  Safari makes trouble for downloading files.
61226 *
61227 *  @return  {Boolean} [description]
61228 *  @private
61229 */
61230p5.prototype._isSafari = function() {
61231  var x = Object.prototype.toString.call(window.HTMLElement);
61232  return x.indexOf('Constructor') > 0;
61233};
61234
61235/**
61236 *  Helper function, a callback for download that deletes
61237 *  an invisible anchor element from the DOM once the file
61238 *  has been automatically downloaded.
61239 *
61240 *  @private
61241 */
61242function destroyClickedElement(event) {
61243  document.body.removeChild(event.target);
61244}
61245
61246module.exports = p5;
61247
61248},{"../core/core":22,"../core/error_helpers":25,"es6-promise":5,"fetch-jsonp":6,"file-saver":7,"whatwg-fetch":12}],47:[function(_dereq_,module,exports){
61249/**
61250 * @module IO
61251 * @submodule Table
61252 * @requires core
61253 */
61254
61255'use strict';
61256
61257var p5 = _dereq_('../core/core');
61258
61259/**
61260 *  Table Options
61261 *  <p>Generic class for handling tabular data, typically from a
61262 *  CSV, TSV, or other sort of spreadsheet file.</p>
61263 *  <p>CSV files are
61264 *  <a href="http://en.wikipedia.org/wiki/Comma-separated_values">
61265 *  comma separated values</a>, often with the data in quotes. TSV
61266 *  files use tabs as separators, and usually don't bother with the
61267 *  quotes.</p>
61268 *  <p>File names should end with .csv if they're comma separated.</p>
61269 *  <p>A rough "spec" for CSV can be found
61270 *  <a href="http://tools.ietf.org/html/rfc4180">here</a>.</p>
61271 *  <p>To load files, use the loadTable method.</p>
61272 *  <p>To save tables to your computer, use the save method
61273 *   or the saveTable method.</p>
61274 *
61275 *  Possible options include:
61276 *  <ul>
61277 *  <li>csv - parse the table as comma-separated values
61278 *  <li>tsv - parse the table as tab-separated values
61279 *  <li>header - this table has a header (title) row
61280 *  </ul>
61281 */
61282
61283/**
61284 *  Table objects store data with multiple rows and columns, much
61285 *  like in a traditional spreadsheet. Tables can be generated from
61286 *  scratch, dynamically, or using data from an existing file.
61287 *
61288 *  @class p5.Table
61289 *  @constructor
61290 *  @param  {p5.TableRow[]}     [rows] An array of p5.TableRow objects
61291 */
61292p5.Table = function(rows) {
61293  /**
61294   *  @property columns {String[]}
61295   */
61296  this.columns = [];
61297
61298  /**
61299   *  @property rows {p5.TableRow[]}
61300   */
61301  this.rows = [];
61302};
61303
61304/**
61305 *  Use addRow() to add a new row of data to a p5.Table object. By default,
61306 *  an empty row is created. Typically, you would store a reference to
61307 *  the new row in a TableRow object (see newRow in the example above),
61308 *  and then set individual values using set().
61309 *
61310 *  If a p5.TableRow object is included as a parameter, then that row is
61311 *  duplicated and added to the table.
61312 *
61313 *  @method  addRow
61314 *  @param   {p5.TableRow} [row] row to be added to the table
61315 *
61316 * @example
61317 * <div class="norender">
61318 * <code>
61319 * // Given the CSV file "mammals.csv"
61320 * // in the project's "assets" folder:
61321 * //
61322 * // id,species,name
61323 * // 0,Capra hircus,Goat
61324 * // 1,Panthera pardus,Leopard
61325 * // 2,Equus zebra,Zebra
61326 *
61327 * var table;
61328 *
61329 * function preload() {
61330 *   //my table is comma separated value "csv"
61331 *   //and has a header specifying the columns labels
61332 *   table = loadTable('assets/mammals.csv', 'csv', 'header');
61333 * }
61334 *
61335 * function setup() {
61336 *   //add a row
61337 *   var newRow = table.addRow();
61338 *   newRow.setString('id', table.getRowCount() - 1);
61339 *   newRow.setString('species', 'Canis Lupus');
61340 *   newRow.setString('name', 'Wolf');
61341 *
61342 *   //print the results
61343 *   for (var r = 0; r < table.getRowCount(); r++)
61344 *     for (var c = 0; c < table.getColumnCount(); c++)
61345 *       print(table.getString(r, c));
61346 * }
61347 * </code>
61348 * </div>
61349 *
61350 * @alt
61351 * no image displayed
61352 *
61353 */
61354p5.Table.prototype.addRow = function(row) {
61355  // make sure it is a valid TableRow
61356  var r = row || new p5.TableRow();
61357
61358  if (typeof r.arr === 'undefined' || typeof r.obj === 'undefined') {
61359    //r = new p5.prototype.TableRow(r);
61360    throw 'invalid TableRow: ' + r;
61361  }
61362  r.table = this;
61363  this.rows.push(r);
61364  return r;
61365};
61366
61367/**
61368 * Removes a row from the table object.
61369 *
61370 * @method  removeRow
61371 * @param   {Integer} id ID number of the row to remove
61372 *
61373 * @example
61374 * <div class="norender">
61375 * <code>
61376 * // Given the CSV file "mammals.csv"
61377 * // in the project's "assets" folder:
61378 * //
61379 * // id,species,name
61380 * // 0,Capra hircus,Goat
61381 * // 1,Panthera pardus,Leopard
61382 * // 2,Equus zebra,Zebra
61383 *
61384 * var table;
61385 *
61386 * function preload() {
61387 *   //my table is comma separated value "csv"
61388 *   //and has a header specifying the columns labels
61389 *   table = loadTable('assets/mammals.csv', 'csv', 'header');
61390 * }
61391 *
61392 * function setup() {
61393 *   //remove the first row
61394 *   table.removeRow(0);
61395 *
61396 *   //print the results
61397 *   for (var r = 0; r < table.getRowCount(); r++)
61398 *     for (var c = 0; c < table.getColumnCount(); c++)
61399 *       print(table.getString(r, c));
61400 * }
61401 * </code>
61402 * </div>
61403 *
61404 * @alt
61405 * no image displayed
61406 *
61407 */
61408p5.Table.prototype.removeRow = function(id) {
61409  this.rows[id].table = null; // remove reference to table
61410  var chunk = this.rows.splice(id + 1, this.rows.length);
61411  this.rows.pop();
61412  this.rows = this.rows.concat(chunk);
61413};
61414
61415/**
61416 * Returns a reference to the specified p5.TableRow. The reference
61417 * can then be used to get and set values of the selected row.
61418 *
61419 * @method  getRow
61420 * @param  {Integer}   rowID ID number of the row to get
61421 * @return {p5.TableRow} p5.TableRow object
61422 *
61423 * @example
61424 * <div class="norender">
61425 * <code>
61426 * // Given the CSV file "mammals.csv"
61427 * // in the project's "assets" folder:
61428 * //
61429 * // id,species,name
61430 * // 0,Capra hircus,Goat
61431 * // 1,Panthera pardus,Leopard
61432 * // 2,Equus zebra,Zebra
61433 *
61434 * var table;
61435 *
61436 * function preload() {
61437 *   //my table is comma separated value "csv"
61438 *   //and has a header specifying the columns labels
61439 *   table = loadTable('assets/mammals.csv', 'csv', 'header');
61440 * }
61441 *
61442 * function setup() {
61443 *   var row = table.getRow(1);
61444 *   //print it column by column
61445 *   //note: a row is an object, not an array
61446 *   for (var c = 0; c < table.getColumnCount(); c++) {
61447 *     print(row.getString(c));
61448 *   }
61449 * }
61450 * </code>
61451 * </div>
61452 *
61453 *@alt
61454 * no image displayed
61455 *
61456 */
61457p5.Table.prototype.getRow = function(r) {
61458  return this.rows[r];
61459};
61460
61461/**
61462 *  Gets all rows from the table. Returns an array of p5.TableRows.
61463 *
61464 *  @method  getRows
61465 *  @return {p5.TableRow[]}   Array of p5.TableRows
61466 *
61467 * @example
61468 * <div class="norender">
61469 * <code>
61470 * // Given the CSV file "mammals.csv"
61471 * // in the project's "assets" folder:
61472 * //
61473 * // id,species,name
61474 * // 0,Capra hircus,Goat
61475 * // 1,Panthera pardus,Leopard
61476 * // 2,Equus zebra,Zebra
61477 *
61478 * var table;
61479 *
61480 * function preload() {
61481 *   //my table is comma separated value "csv"
61482 *   //and has a header specifying the columns labels
61483 *   table = loadTable('assets/mammals.csv', 'csv', 'header');
61484 * }
61485 *
61486 * function setup() {
61487 *   var rows = table.getRows();
61488 *
61489 *   //warning: rows is an array of objects
61490 *   for (var r = 0; r < rows.length; r++) {
61491 *     rows[r].set('name', 'Unicorn');
61492 *   }
61493 *
61494 *   //print the results
61495 *   for (r = 0; r < table.getRowCount(); r++)
61496 *     for (var c = 0; c < table.getColumnCount(); c++)
61497 *       print(table.getString(r, c));
61498 * }
61499 * </code>
61500 * </div>
61501 *
61502 * @alt
61503 * no image displayed
61504 *
61505 */
61506p5.Table.prototype.getRows = function() {
61507  return this.rows;
61508};
61509
61510/**
61511 *  Finds the first row in the Table that contains the value
61512 *  provided, and returns a reference to that row. Even if
61513 *  multiple rows are possible matches, only the first matching
61514 *  row is returned. The column to search may be specified by
61515 *  either its ID or title.
61516 *
61517 *  @method  findRow
61518 *  @param  {String} value  The value to match
61519 *  @param  {Integer|String} column ID number or title of the
61520 *                                 column to search
61521 *  @return {p5.TableRow}
61522 *
61523 * @example
61524 * <div class="norender">
61525 * <code>
61526 * // Given the CSV file "mammals.csv"
61527 * // in the project's "assets" folder:
61528 * //
61529 * // id,species,name
61530 * // 0,Capra hircus,Goat
61531 * // 1,Panthera pardus,Leopard
61532 * // 2,Equus zebra,Zebra
61533 *
61534 * var table;
61535 *
61536 * function preload() {
61537 *   //my table is comma separated value "csv"
61538 *   //and has a header specifying the columns labels
61539 *   table = loadTable('assets/mammals.csv', 'csv', 'header');
61540 * }
61541 *
61542 * function setup() {
61543 *   //find the animal named zebra
61544 *   var row = table.findRow('Zebra', 'name');
61545 *   //find the corresponding species
61546 *   print(row.getString('species'));
61547 * }
61548 * </code>
61549 * </div>
61550 *
61551 * @alt
61552 * no image displayed
61553 *
61554 */
61555p5.Table.prototype.findRow = function(value, column) {
61556  // try the Object
61557  if (typeof column === 'string') {
61558    for (var i = 0; i < this.rows.length; i++) {
61559      if (this.rows[i].obj[column] === value) {
61560        return this.rows[i];
61561      }
61562    }
61563  } else {
61564    // try the Array
61565    for (var j = 0; j < this.rows.length; j++) {
61566      if (this.rows[j].arr[column] === value) {
61567        return this.rows[j];
61568      }
61569    }
61570  }
61571  // otherwise...
61572  return null;
61573};
61574
61575/**
61576 *  Finds the rows in the Table that contain the value
61577 *  provided, and returns references to those rows. Returns an
61578 *  Array, so for must be used to iterate through all the rows,
61579 *  as shown in the example above. The column to search may be
61580 *  specified by either its ID or title.
61581 *
61582 *  @method  findRows
61583 *  @param  {String} value  The value to match
61584 *  @param  {Integer|String} column ID number or title of the
61585 *                                 column to search
61586 *  @return {p5.TableRow[]}        An Array of TableRow objects
61587 *
61588 * @example
61589 * <div class="norender">
61590 * <code>
61591 * // Given the CSV file "mammals.csv"
61592 * // in the project's "assets" folder:
61593 * //
61594 * // id,species,name
61595 * // 0,Capra hircus,Goat
61596 * // 1,Panthera pardus,Leopard
61597 * // 2,Equus zebra,Zebra
61598 *
61599 * var table;
61600 *
61601 * function preload() {
61602 *   //my table is comma separated value "csv"
61603 *   //and has a header specifying the columns labels
61604 *   table = loadTable('assets/mammals.csv', 'csv', 'header');
61605 * }
61606 *
61607 * function setup() {
61608 *   //add another goat
61609 *   var newRow = table.addRow();
61610 *   newRow.setString('id', table.getRowCount() - 1);
61611 *   newRow.setString('species', 'Scape Goat');
61612 *   newRow.setString('name', 'Goat');
61613 *
61614 *   //find the rows containing animals named Goat
61615 *   var rows = table.findRows('Goat', 'name');
61616 *   print(rows.length + ' Goats found');
61617 * }
61618 * </code>
61619 * </div>
61620 *
61621 *@alt
61622 * no image displayed
61623 *
61624 */
61625p5.Table.prototype.findRows = function(value, column) {
61626  var ret = [];
61627  if (typeof column === 'string') {
61628    for (var i = 0; i < this.rows.length; i++) {
61629      if (this.rows[i].obj[column] === value) {
61630        ret.push(this.rows[i]);
61631      }
61632    }
61633  } else {
61634    // try the Array
61635    for (var j = 0; j < this.rows.length; j++) {
61636      if (this.rows[j].arr[column] === value) {
61637        ret.push(this.rows[j]);
61638      }
61639    }
61640  }
61641  return ret;
61642};
61643
61644/**
61645 * Finds the first row in the Table that matches the regular
61646 * expression provided, and returns a reference to that row.
61647 * Even if multiple rows are possible matches, only the first
61648 * matching row is returned. The column to search may be
61649 * specified by either its ID or title.
61650 *
61651 * @method  matchRow
61652 * @param  {String|RegExp} regexp The regular expression to match
61653 * @param  {String|Integer} column The column ID (number) or
61654 *                                  title (string)
61655 * @return {p5.TableRow}        TableRow object
61656 *
61657 * @example
61658 * <div class="norender">
61659 * <code>
61660 * // Given the CSV file "mammals.csv"
61661 * // in the project's "assets" folder:
61662 * //
61663 * // id,species,name
61664 * // 0,Capra hircus,Goat
61665 * // 1,Panthera pardus,Leopard
61666 * // 2,Equus zebra,Zebra
61667 *
61668 * var table;
61669 *
61670 * function preload() {
61671 *   //my table is comma separated value "csv"
61672 *   //and has a header specifying the columns labels
61673 *   table = loadTable('assets/mammals.csv', 'csv', 'header');
61674 * }
61675 *
61676 * function setup() {
61677 *   //Search using specified regex on a given column, return TableRow object
61678 *   var mammal = table.matchRow(new RegExp('ant'), 1);
61679 *   print(mammal.getString(1));
61680 *   //Output "Panthera pardus"
61681 * }
61682 * </code>
61683 * </div>
61684 *
61685 */
61686p5.Table.prototype.matchRow = function(regexp, column) {
61687  if (typeof column === 'number') {
61688    for (var j = 0; j < this.rows.length; j++) {
61689      if (this.rows[j].arr[column].match(regexp)) {
61690        return this.rows[j];
61691      }
61692    }
61693  } else {
61694    for (var i = 0; i < this.rows.length; i++) {
61695      if (this.rows[i].obj[column].match(regexp)) {
61696        return this.rows[i];
61697      }
61698    }
61699  }
61700  return null;
61701};
61702
61703/**
61704 * Finds the rows in the Table that match the regular expression provided,
61705 * and returns references to those rows. Returns an array, so for must be
61706 * used to iterate through all the rows, as shown in the example. The
61707 * column to search may be specified by either its ID or title.
61708 *
61709 * @method  matchRows
61710 * @param  {String} regexp The regular expression to match
61711 * @param  {String|Integer} [column] The column ID (number) or
61712 *                                  title (string)
61713 * @return {p5.TableRow[]}          An Array of TableRow objects
61714 * @example
61715 * <div class="norender">
61716 * <code>
61717 * var table;
61718 *
61719 * function setup() {
61720 *   table = new p5.Table();
61721 *
61722 *   table.addColumn('name');
61723 *   table.addColumn('type');
61724 *
61725 *   var newRow = table.addRow();
61726 *   newRow.setString('name', 'Lion');
61727 *   newRow.setString('type', 'Mammal');
61728 *
61729 *   newRow = table.addRow();
61730 *   newRow.setString('name', 'Snake');
61731 *   newRow.setString('type', 'Reptile');
61732 *
61733 *   newRow = table.addRow();
61734 *   newRow.setString('name', 'Mosquito');
61735 *   newRow.setString('type', 'Insect');
61736 *
61737 *   newRow = table.addRow();
61738 *   newRow.setString('name', 'Lizard');
61739 *   newRow.setString('type', 'Reptile');
61740 *
61741 *   var rows = table.matchRows('R.*', 'type');
61742 *   for (var i = 0; i < rows.length; i++) {
61743 *     print(rows[i].getString('name') + ': ' + rows[i].getString('type'));
61744 *   }
61745 * }
61746 * // Sketch prints:
61747 * // Snake: Reptile
61748 * // Lizard: Reptile
61749 * </code>
61750 * </div>
61751 */
61752p5.Table.prototype.matchRows = function(regexp, column) {
61753  var ret = [];
61754  if (typeof column === 'number') {
61755    for (var j = 0; j < this.rows.length; j++) {
61756      if (this.rows[j].arr[column].match(regexp)) {
61757        ret.push(this.rows[j]);
61758      }
61759    }
61760  } else {
61761    for (var i = 0; i < this.rows.length; i++) {
61762      if (this.rows[i].obj[column].match(regexp)) {
61763        ret.push(this.rows[i]);
61764      }
61765    }
61766  }
61767  return ret;
61768};
61769
61770/**
61771 *  Retrieves all values in the specified column, and returns them
61772 *  as an array. The column may be specified by either its ID or title.
61773 *
61774 *  @method  getColumn
61775 *  @param  {String|Number} column String or Number of the column to return
61776 *  @return {Array}       Array of column values
61777 *
61778 * @example
61779 * <div class="norender">
61780 * <code>
61781 * // Given the CSV file "mammals.csv"
61782 * // in the project's "assets" folder:
61783 * //
61784 * // id,species,name
61785 * // 0,Capra hircus,Goat
61786 * // 1,Panthera pardus,Leopard
61787 * // 2,Equus zebra,Zebra
61788 *
61789 * var table;
61790 *
61791 * function preload() {
61792 *   //my table is comma separated value "csv"
61793 *   //and has a header specifying the columns labels
61794 *   table = loadTable('assets/mammals.csv', 'csv', 'header');
61795 * }
61796 *
61797 * function setup() {
61798 *   //getColumn returns an array that can be printed directly
61799 *   print(table.getColumn('species'));
61800 *   //outputs ["Capra hircus", "Panthera pardus", "Equus zebra"]
61801 * }
61802 * </code>
61803 * </div>
61804 *
61805 *@alt
61806 * no image displayed
61807 *
61808 */
61809p5.Table.prototype.getColumn = function(value) {
61810  var ret = [];
61811  if (typeof value === 'string') {
61812    for (var i = 0; i < this.rows.length; i++) {
61813      ret.push(this.rows[i].obj[value]);
61814    }
61815  } else {
61816    for (var j = 0; j < this.rows.length; j++) {
61817      ret.push(this.rows[j].arr[value]);
61818    }
61819  }
61820  return ret;
61821};
61822
61823/**
61824 *  Removes all rows from a Table. While all rows are removed,
61825 *  columns and column titles are maintained.
61826 *
61827 *  @method  clearRows
61828 *
61829 * @example
61830 * <div class="norender">
61831 * <code>
61832 * // Given the CSV file "mammals.csv"
61833 * // in the project's "assets" folder:
61834 * //
61835 * // id,species,name
61836 * // 0,Capra hircus,Goat
61837 * // 1,Panthera pardus,Leopard
61838 * // 2,Equus zebra,Zebra
61839 *
61840 * var table;
61841 *
61842 * function preload() {
61843 *   //my table is comma separated value "csv"
61844 *   //and has a header specifying the columns labels
61845 *   table = loadTable('assets/mammals.csv', 'csv', 'header');
61846 * }
61847 *
61848 * function setup() {
61849 *   table.clearRows();
61850 *   print(table.getRowCount() + ' total rows in table');
61851 *   print(table.getColumnCount() + ' total columns in table');
61852 * }
61853 * </code>
61854 * </div>
61855 *
61856 *@alt
61857 * no image displayed
61858 *
61859 */
61860p5.Table.prototype.clearRows = function() {
61861  delete this.rows;
61862  this.rows = [];
61863};
61864
61865/**
61866 *  Use addColumn() to add a new column to a Table object.
61867 *  Typically, you will want to specify a title, so the column
61868 *  may be easily referenced later by name. (If no title is
61869 *  specified, the new column's title will be null.)
61870 *
61871 *  @method  addColumn
61872 *  @param {String} [title] title of the given column
61873 *
61874 * @example
61875 * <div class="norender">
61876 * <code>
61877 * // Given the CSV file "mammals.csv"
61878 * // in the project's "assets" folder:
61879 * //
61880 * // id,species,name
61881 * // 0,Capra hircus,Goat
61882 * // 1,Panthera pardus,Leopard
61883 * // 2,Equus zebra,Zebra
61884 *
61885 * var table;
61886 *
61887 * function preload() {
61888 *   //my table is comma separated value "csv"
61889 *   //and has a header specifying the columns labels
61890 *   table = loadTable('assets/mammals.csv', 'csv', 'header');
61891 * }
61892 *
61893 * function setup() {
61894 *   table.addColumn('carnivore');
61895 *   table.set(0, 'carnivore', 'no');
61896 *   table.set(1, 'carnivore', 'yes');
61897 *   table.set(2, 'carnivore', 'no');
61898 *
61899 *   //print the results
61900 *   for (var r = 0; r < table.getRowCount(); r++)
61901 *     for (var c = 0; c < table.getColumnCount(); c++)
61902 *       print(table.getString(r, c));
61903 * }
61904 * </code>
61905 * </div>
61906 *
61907 *@alt
61908 * no image displayed
61909 *
61910 */
61911p5.Table.prototype.addColumn = function(title) {
61912  var t = title || null;
61913  this.columns.push(t);
61914};
61915
61916/**
61917 *  Returns the total number of columns in a Table.
61918 *
61919 *  @method  getColumnCount
61920 *  @return {Integer} Number of columns in this table
61921 * @example
61922 * <div>
61923 * <code>
61924 * // given the cvs file "blobs.csv" in /assets directory
61925 * // ID, Name, Flavor, Shape, Color
61926 * // Blob1, Blobby, Sweet, Blob, Pink
61927 * // Blob2, Saddy, Savory, Blob, Blue
61928 *
61929 * var table;
61930 *
61931 * function preload() {
61932 *   table = loadTable('assets/blobs.csv');
61933 * }
61934 *
61935 * function setup() {
61936 *   createCanvas(200, 100);
61937 *   textAlign(CENTER);
61938 *   background(255);
61939 * }
61940 *
61941 * function draw() {
61942 *   var numOfColumn = table.getColumnCount();
61943 *   text('There are ' + numOfColumn + ' columns in the table.', 100, 50);
61944 * }
61945 * </code>
61946 * </div>
61947 */
61948p5.Table.prototype.getColumnCount = function() {
61949  return this.columns.length;
61950};
61951
61952/**
61953 *  Returns the total number of rows in a Table.
61954 *
61955 *  @method  getRowCount
61956 *  @return {Integer} Number of rows in this table
61957 * @example
61958 * <div>
61959 * <code>
61960 * // given the cvs file "blobs.csv" in /assets directory
61961 * //
61962 * // ID, Name, Flavor, Shape, Color
61963 * // Blob1, Blobby, Sweet, Blob, Pink
61964 * // Blob2, Saddy, Savory, Blob, Blue
61965 *
61966 * var table;
61967 *
61968 * function preload() {
61969 *   table = loadTable('assets/blobs.csv');
61970 * }
61971 *
61972 * function setup() {
61973 *   createCanvas(200, 100);
61974 *   textAlign(CENTER);
61975 *   background(255);
61976 * }
61977 *
61978 * function draw() {
61979 *   text('There are ' + table.getRowCount() + ' rows in the table.', 100, 50);
61980 * }
61981 * </code>
61982 * </div>
61983 */
61984p5.Table.prototype.getRowCount = function() {
61985  return this.rows.length;
61986};
61987
61988/**
61989 *  <p>Removes any of the specified characters (or "tokens").</p>
61990 *
61991 *  <p>If no column is specified, then the values in all columns and
61992 *  rows are processed. A specific column may be referenced by
61993 *  either its ID or title.</p>
61994 *
61995 *  @method  removeTokens
61996 *  @param  {String} chars  String listing characters to be removed
61997 *  @param  {String|Integer} [column] Column ID (number)
61998 *                                   or name (string)
61999 *
62000 * @example
62001 * <div class="norender"><code>
62002 * function setup() {
62003 *   var table = new p5.Table();
62004 *
62005 *   table.addColumn('name');
62006 *   table.addColumn('type');
62007 *
62008 *   var newRow = table.addRow();
62009 *   newRow.setString('name', '   $Lion  ,');
62010 *   newRow.setString('type', ',,,Mammal');
62011 *
62012 *   newRow = table.addRow();
62013 *   newRow.setString('name', '$Snake  ');
62014 *   newRow.setString('type', ',,,Reptile');
62015 *
62016 *   table.removeTokens(',$ ');
62017 *   print(table.getArray());
62018 * }
62019 *
62020 * // prints:
62021 * //  0  "Lion"   "Mamal"
62022 * //  1  "Snake"  "Reptile"
62023 * </code></div>
62024 */
62025p5.Table.prototype.removeTokens = function(chars, column) {
62026  var escape = function(s) {
62027    return s.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
62028  };
62029  var charArray = [];
62030  for (var i = 0; i < chars.length; i++) {
62031    charArray.push(escape(chars.charAt(i)));
62032  }
62033  var regex = new RegExp(charArray.join('|'), 'g');
62034
62035  if (typeof column === 'undefined') {
62036    for (var c = 0; c < this.columns.length; c++) {
62037      for (var d = 0; d < this.rows.length; d++) {
62038        var s = this.rows[d].arr[c];
62039        s = s.replace(regex, '');
62040        this.rows[d].arr[c] = s;
62041        this.rows[d].obj[this.columns[c]] = s;
62042      }
62043    }
62044  } else if (typeof column === 'string') {
62045    for (var j = 0; j < this.rows.length; j++) {
62046      var val = this.rows[j].obj[column];
62047      val = val.replace(regex, '');
62048      this.rows[j].obj[column] = val;
62049      var pos = this.columns.indexOf(column);
62050      this.rows[j].arr[pos] = val;
62051    }
62052  } else {
62053    for (var k = 0; k < this.rows.length; k++) {
62054      var str = this.rows[k].arr[column];
62055      str = str.replace(regex, '');
62056      this.rows[k].arr[column] = str;
62057      this.rows[k].obj[this.columns[column]] = str;
62058    }
62059  }
62060};
62061
62062/**
62063 *  Trims leading and trailing whitespace, such as spaces and tabs,
62064 *  from String table values. If no column is specified, then the
62065 *  values in all columns and rows are trimmed. A specific column
62066 *  may be referenced by either its ID or title.
62067 *
62068 *  @method  trim
62069 *  @param  {String|Integer} [column] Column ID (number)
62070 *                                   or name (string)
62071 * @example
62072 * <div class="norender"><code>
62073 * function setup() {
62074 *   var table = new p5.Table();
62075 *
62076 *   table.addColumn('name');
62077 *   table.addColumn('type');
62078 *
62079 *   var newRow = table.addRow();
62080 *   newRow.setString('name', '   Lion  ,');
62081 *   newRow.setString('type', ' Mammal  ');
62082 *
62083 *   newRow = table.addRow();
62084 *   newRow.setString('name', '  Snake  ');
62085 *   newRow.setString('type', '  Reptile  ');
62086 *
62087 *   table.trim();
62088 *   print(table.getArray());
62089 * }
62090 *
62091 * // prints:
62092 * //  0  "Lion"   "Mamal"
62093 * //  1  "Snake"  "Reptile"
62094 * </code></div>
62095 */
62096p5.Table.prototype.trim = function(column) {
62097  var regex = new RegExp(' ', 'g');
62098
62099  if (typeof column === 'undefined') {
62100    for (var c = 0; c < this.columns.length; c++) {
62101      for (var d = 0; d < this.rows.length; d++) {
62102        var s = this.rows[d].arr[c];
62103        s = s.replace(regex, '');
62104        this.rows[d].arr[c] = s;
62105        this.rows[d].obj[this.columns[c]] = s;
62106      }
62107    }
62108  } else if (typeof column === 'string') {
62109    for (var j = 0; j < this.rows.length; j++) {
62110      var val = this.rows[j].obj[column];
62111      val = val.replace(regex, '');
62112      this.rows[j].obj[column] = val;
62113      var pos = this.columns.indexOf(column);
62114      this.rows[j].arr[pos] = val;
62115    }
62116  } else {
62117    for (var k = 0; k < this.rows.length; k++) {
62118      var str = this.rows[k].arr[column];
62119      str = str.replace(regex, '');
62120      this.rows[k].arr[column] = str;
62121      this.rows[k].obj[this.columns[column]] = str;
62122    }
62123  }
62124};
62125
62126/**
62127 *  Use removeColumn() to remove an existing column from a Table
62128 *  object. The column to be removed may be identified by either
62129 *  its title (a String) or its index value (an int).
62130 *  removeColumn(0) would remove the first column, removeColumn(1)
62131 *  would remove the second column, and so on.
62132 *
62133 *  @method  removeColumn
62134 *  @param  {String|Integer} column columnName (string) or ID (number)
62135 *
62136 * @example
62137 * <div class="norender">
62138 * <code>
62139 * // Given the CSV file "mammals.csv"
62140 * // in the project's "assets" folder:
62141 * //
62142 * // id,species,name
62143 * // 0,Capra hircus,Goat
62144 * // 1,Panthera pardus,Leopard
62145 * // 2,Equus zebra,Zebra
62146 *
62147 * var table;
62148 *
62149 * function preload() {
62150 *   //my table is comma separated value "csv"
62151 *   //and has a header specifying the columns labels
62152 *   table = loadTable('assets/mammals.csv', 'csv', 'header');
62153 * }
62154 *
62155 * function setup() {
62156 *   table.removeColumn('id');
62157 *   print(table.getColumnCount());
62158 * }
62159 * </code>
62160 * </div>
62161 *
62162 *@alt
62163 * no image displayed
62164 *
62165 */
62166p5.Table.prototype.removeColumn = function(c) {
62167  var cString;
62168  var cNumber;
62169  if (typeof c === 'string') {
62170    // find the position of c in the columns
62171    cString = c;
62172    cNumber = this.columns.indexOf(c);
62173    console.log('string');
62174  } else {
62175    cNumber = c;
62176    cString = this.columns[c];
62177  }
62178
62179  var chunk = this.columns.splice(cNumber + 1, this.columns.length);
62180  this.columns.pop();
62181  this.columns = this.columns.concat(chunk);
62182
62183  for (var i = 0; i < this.rows.length; i++) {
62184    var tempR = this.rows[i].arr;
62185    var chip = tempR.splice(cNumber + 1, tempR.length);
62186    tempR.pop();
62187    this.rows[i].arr = tempR.concat(chip);
62188    delete this.rows[i].obj[cString];
62189  }
62190};
62191
62192/**
62193 * Stores a value in the Table's specified row and column.
62194 * The row is specified by its ID, while the column may be specified
62195 * by either its ID or title.
62196 *
62197 * @method  set
62198 * @param {Integer} row row ID
62199 * @param {String|Integer} column column ID (Number)
62200 *                               or title (String)
62201 * @param {String|Number} value  value to assign
62202 *
62203 * @example
62204 * <div class="norender">
62205 * <code>
62206 * // Given the CSV file "mammals.csv"
62207 * // in the project's "assets" folder:
62208 * //
62209 * // id,species,name
62210 * // 0,Capra hircus,Goat
62211 * // 1,Panthera pardus,Leopard
62212 * // 2,Equus zebra,Zebra
62213 *
62214 * var table;
62215 *
62216 * function preload() {
62217 *   //my table is comma separated value "csv"
62218 *   //and has a header specifying the columns labels
62219 *   table = loadTable('assets/mammals.csv', 'csv', 'header');
62220 * }
62221 *
62222 * function setup() {
62223 *   table.set(0, 'species', 'Canis Lupus');
62224 *   table.set(0, 'name', 'Wolf');
62225 *
62226 *   //print the results
62227 *   for (var r = 0; r < table.getRowCount(); r++)
62228 *     for (var c = 0; c < table.getColumnCount(); c++)
62229 *       print(table.getString(r, c));
62230 * }
62231 * </code>
62232 * </div>
62233 *
62234 *@alt
62235 * no image displayed
62236 *
62237 */
62238p5.Table.prototype.set = function(row, column, value) {
62239  this.rows[row].set(column, value);
62240};
62241
62242/**
62243 * Stores a Float value in the Table's specified row and column.
62244 * The row is specified by its ID, while the column may be specified
62245 * by either its ID or title.
62246 *
62247 * @method setNum
62248 * @param {Integer} row row ID
62249 * @param {String|Integer} column column ID (Number)
62250 *                               or title (String)
62251 * @param {Number} value  value to assign
62252 *
62253 * @example
62254 * <div class="norender">
62255 * <code>
62256 * // Given the CSV file "mammals.csv"
62257 * // in the project's "assets" folder:
62258 * //
62259 * // id,species,name
62260 * // 0,Capra hircus,Goat
62261 * // 1,Panthera pardus,Leopard
62262 * // 2,Equus zebra,Zebra
62263 *
62264 * var table;
62265 *
62266 * function preload() {
62267 *   //my table is comma separated value "csv"
62268 *   //and has a header specifying the columns labels
62269 *   table = loadTable('assets/mammals.csv', 'csv', 'header');
62270 * }
62271 *
62272 * function setup() {
62273 *   table.setNum(1, 'id', 1);
62274 *
62275 *   print(table.getColumn(0));
62276 *   //["0", 1, "2"]
62277 * }
62278 * </code>
62279 * </div>
62280 *
62281 *@alt
62282 * no image displayed
62283 */
62284p5.Table.prototype.setNum = function(row, column, value) {
62285  this.rows[row].setNum(column, value);
62286};
62287
62288/**
62289 * Stores a String value in the Table's specified row and column.
62290 * The row is specified by its ID, while the column may be specified
62291 * by either its ID or title.
62292 *
62293 * @method  setString
62294 * @param {Integer} row row ID
62295 * @param {String|Integer} column column ID (Number)
62296 *                               or title (String)
62297 * @param {String} value  value to assign
62298 * @example
62299 * <div class="norender"><code>
62300 * // Given the CSV file "mammals.csv" in the project's "assets" folder:
62301 * //
62302 * // id,species,name
62303 * // 0,Capra hircus,Goat
62304 * // 1,Panthera pardus,Leopard
62305 * // 2,Equus zebra,Zebra
62306 *
62307 * var table;
62308 *
62309 * function preload() {
62310 *   //my table is comma separated value "csv"
62311 *   //and has a header specifying the columns labels
62312 *   table = loadTable('assets/mammals.csv', 'csv', 'header');
62313 * }
62314 *
62315 * function setup() {
62316 *   //add a row
62317 *   var newRow = table.addRow();
62318 *   newRow.setString('id', table.getRowCount() - 1);
62319 *   newRow.setString('species', 'Canis Lupus');
62320 *   newRow.setString('name', 'Wolf');
62321 *
62322 *   print(table.getArray());
62323 * }
62324 * </code></div>
62325 *
62326 * @alt
62327 * no image displayed
62328 */
62329p5.Table.prototype.setString = function(row, column, value) {
62330  this.rows[row].setString(column, value);
62331};
62332
62333/**
62334 * Retrieves a value from the Table's specified row and column.
62335 * The row is specified by its ID, while the column may be specified by
62336 * either its ID or title.
62337 *
62338 * @method  get
62339 * @param {Integer} row row ID
62340 * @param  {String|Integer} column columnName (string) or
62341 *                                   ID (number)
62342 * @return {String|Number}
62343 *
62344 * @example
62345 * <div class="norender">
62346 * <code>
62347 * // Given the CSV file "mammals.csv"
62348 * // in the project's "assets" folder:
62349 * //
62350 * // id,species,name
62351 * // 0,Capra hircus,Goat
62352 * // 1,Panthera pardus,Leopard
62353 * // 2,Equus zebra,Zebra
62354 *
62355 * var table;
62356 *
62357 * function preload() {
62358 *   //my table is comma separated value "csv"
62359 *   //and has a header specifying the columns labels
62360 *   table = loadTable('assets/mammals.csv', 'csv', 'header');
62361 * }
62362 *
62363 * function setup() {
62364 *   print(table.get(0, 1));
62365 *   //Capra hircus
62366 *   print(table.get(0, 'species'));
62367 *   //Capra hircus
62368 * }
62369 * </code>
62370 * </div>
62371 *
62372 *@alt
62373 * no image displayed
62374 *
62375 */
62376p5.Table.prototype.get = function(row, column) {
62377  return this.rows[row].get(column);
62378};
62379
62380/**
62381 * Retrieves a Float value from the Table's specified row and column.
62382 * The row is specified by its ID, while the column may be specified by
62383 * either its ID or title.
62384 *
62385 * @method  getNum
62386 * @param {Integer} row row ID
62387 * @param  {String|Integer} column columnName (string) or
62388 *                                   ID (number)
62389 * @return {Number}
62390 *
62391 * @example
62392 * <div class="norender">
62393 * <code>
62394 * // Given the CSV file "mammals.csv"
62395 * // in the project's "assets" folder:
62396 * //
62397 * // id,species,name
62398 * // 0,Capra hircus,Goat
62399 * // 1,Panthera pardus,Leopard
62400 * // 2,Equus zebra,Zebra
62401 *
62402 * var table;
62403 *
62404 * function preload() {
62405 *   //my table is comma separated value "csv"
62406 *   //and has a header specifying the columns labels
62407 *   table = loadTable('assets/mammals.csv', 'csv', 'header');
62408 * }
62409 *
62410 * function setup() {
62411 *   print(table.getNum(1, 0) + 100);
62412 *   //id 1 + 100 = 101
62413 * }
62414 * </code>
62415 * </div>
62416 *
62417 *@alt
62418 * no image displayed
62419 *
62420 */
62421p5.Table.prototype.getNum = function(row, column) {
62422  return this.rows[row].getNum(column);
62423};
62424
62425/**
62426 * Retrieves a String value from the Table's specified row and column.
62427 * The row is specified by its ID, while the column may be specified by
62428 * either its ID or title.
62429 *
62430 * @method  getString
62431 * @param {Integer} row row ID
62432 * @param  {String|Integer} column columnName (string) or
62433 *                                   ID (number)
62434 * @return {String}
62435 *
62436 * @example
62437 * <div class="norender">
62438 * <code>
62439 * // Given the CSV file "mammals.csv"
62440 * // in the project's "assets" folder:
62441 * //
62442 * // id,species,name
62443 * // 0,Capra hircus,Goat
62444 * // 1,Panthera pardus,Leopard
62445 * // 2,Equus zebra,Zebra
62446 *
62447 * var table;
62448 *
62449 * function preload() {
62450 *   // table is comma separated value "CSV"
62451 *   // and has specifiying header for column labels
62452 *   table = loadTable('assets/mammals.csv', 'csv', 'header');
62453 * }
62454 *
62455 * function setup() {
62456 *   print(table.getString(0, 0)); // 0
62457 *   print(table.getString(0, 1)); // Capra hircus
62458 *   print(table.getString(0, 2)); // Goat
62459 *   print(table.getString(1, 0)); // 1
62460 *   print(table.getString(1, 1)); // Panthera pardus
62461 *   print(table.getString(1, 2)); // Leopard
62462 *   print(table.getString(2, 0)); // 2
62463 *   print(table.getString(2, 1)); // Equus zebra
62464 *   print(table.getString(2, 2)); // Zebra
62465 * }
62466 * </code>
62467 * </div>
62468 *
62469 *@alt
62470 * no image displayed
62471 *
62472 */
62473
62474p5.Table.prototype.getString = function(row, column) {
62475  return this.rows[row].getString(column);
62476};
62477
62478/**
62479 * Retrieves all table data and returns as an object. If a column name is
62480 * passed in, each row object will be stored with that attribute as its
62481 * title.
62482 *
62483 * @method  getObject
62484 * @param {String} [headerColumn] Name of the column which should be used to
62485 *                              title each row object (optional)
62486 * @return {Object}
62487 *
62488 * @example
62489 * <div class="norender">
62490 * <code>
62491 * // Given the CSV file "mammals.csv"
62492 * // in the project's "assets" folder:
62493 * //
62494 * // id,species,name
62495 * // 0,Capra hircus,Goat
62496 * // 1,Panthera pardus,Leopard
62497 * // 2,Equus zebra,Zebra
62498 *
62499 * var table;
62500 *
62501 * function preload() {
62502 *   //my table is comma separated value "csv"
62503 *   //and has a header specifying the columns labels
62504 *   table = loadTable('assets/mammals.csv', 'csv', 'header');
62505 * }
62506 *
62507 * function setup() {
62508 *   var tableObject = table.getObject();
62509 *
62510 *   print(tableObject);
62511 *   //outputs an object
62512 * }
62513 * </code>
62514 * </div>
62515 *
62516 *@alt
62517 * no image displayed
62518 *
62519 */
62520p5.Table.prototype.getObject = function(headerColumn) {
62521  var tableObject = {};
62522  var obj, cPos, index;
62523
62524  for (var i = 0; i < this.rows.length; i++) {
62525    obj = this.rows[i].obj;
62526
62527    if (typeof headerColumn === 'string') {
62528      cPos = this.columns.indexOf(headerColumn); // index of columnID
62529      if (cPos >= 0) {
62530        index = obj[headerColumn];
62531        tableObject[index] = obj;
62532      } else {
62533        throw 'This table has no column named "' + headerColumn + '"';
62534      }
62535    } else {
62536      tableObject[i] = this.rows[i].obj;
62537    }
62538  }
62539  return tableObject;
62540};
62541
62542/**
62543 * Retrieves all table data and returns it as a multidimensional array.
62544 *
62545 * @method  getArray
62546 * @return {Array}
62547 *
62548 * @example
62549 * <div class="norender">
62550 * <code>
62551 * // Given the CSV file "mammals.csv"
62552 * // in the project's "assets" folder
62553 * //
62554 * // id,species,name
62555 * // 0,Capra hircus,Goat
62556 * // 1,Panthera pardus,Leoperd
62557 * // 2,Equus zebra,Zebra
62558 *
62559 * var table;
62560 *
62561 * function preload() {
62562 *   // table is comma separated value "CSV"
62563 *   // and has specifiying header for column labels
62564 *   table = loadTable('assets/mammals.csv', 'csv', 'header');
62565 * }
62566 *
62567 * function setup() {
62568 *   var tableArray = table.getArray();
62569 *   for (var i = 0; i < tableArray.length; i++) {
62570 *     print(tableArray[i]);
62571 *   }
62572 * }
62573 * </code>
62574 * </div>
62575 *
62576 *@alt
62577 * no image displayed
62578 *
62579 */
62580p5.Table.prototype.getArray = function() {
62581  var tableArray = [];
62582  for (var i = 0; i < this.rows.length; i++) {
62583    tableArray.push(this.rows[i].arr);
62584  }
62585  return tableArray;
62586};
62587
62588module.exports = p5;
62589
62590},{"../core/core":22}],48:[function(_dereq_,module,exports){
62591/**
62592 * @module IO
62593 * @submodule Table
62594 * @requires core
62595 */
62596
62597'use strict';
62598
62599var p5 = _dereq_('../core/core');
62600
62601/**
62602 *  A TableRow object represents a single row of data values,
62603 *  stored in columns, from a table.
62604 *
62605 *  A Table Row contains both an ordered array, and an unordered
62606 *  JSON object.
62607 *
62608 *  @class p5.TableRow
62609 *  @constructor
62610 *  @param {String} [str]       optional: populate the row with a
62611 *                              string of values, separated by the
62612 *                              separator
62613 *  @param {String} [separator] comma separated values (csv) by default
62614 */
62615p5.TableRow = function(str, separator) {
62616  var arr = [];
62617  var obj = {};
62618  if (str) {
62619    separator = separator || ',';
62620    arr = str.split(separator);
62621  }
62622  for (var i = 0; i < arr.length; i++) {
62623    var key = i;
62624    var val = arr[i];
62625    obj[key] = val;
62626  }
62627  this.arr = arr;
62628  this.obj = obj;
62629  this.table = null;
62630};
62631
62632/**
62633 *  Stores a value in the TableRow's specified column.
62634 *  The column may be specified by either its ID or title.
62635 *
62636 *  @method  set
62637 *  @param {String|Integer} column Column ID (Number)
62638 *                                or Title (String)
62639 *  @param {String|Number} value  The value to be stored
62640 *
62641 * @example
62642 * <div class="norender"><code>
62643 * // Given the CSV file "mammals.csv" in the project's "assets" folder:
62644 * //
62645 * // id,species,name
62646 * // 0,Capra hircus,Goat
62647 * // 1,Panthera pardus,Leopard
62648 * // 2,Equus zebra,Zebra
62649 *
62650 * var table;
62651 *
62652 * function preload() {
62653 *   //my table is comma separated value "csv"
62654 *   //and has a header specifying the columns labels
62655 *   table = loadTable('assets/mammals.csv', 'csv', 'header');
62656 * }
62657 *
62658 * function setup() {
62659 *   var rows = table.getRows();
62660 *   for (var r = 0; r < rows.length; r++) {
62661 *     rows[r].set('name', 'Unicorn');
62662 *   }
62663 *
62664 *   //print the results
62665 *   print(table.getArray());
62666 * }
62667 * </code></div>
62668 *
62669 * @alt
62670 * no image displayed
62671 */
62672p5.TableRow.prototype.set = function(column, value) {
62673  // if typeof column is string, use .obj
62674  if (typeof column === 'string') {
62675    var cPos = this.table.columns.indexOf(column); // index of columnID
62676    if (cPos >= 0) {
62677      this.obj[column] = value;
62678      this.arr[cPos] = value;
62679    } else {
62680      throw 'This table has no column named "' + column + '"';
62681    }
62682  } else {
62683    // if typeof column is number, use .arr
62684    if (column < this.table.columns.length) {
62685      this.arr[column] = value;
62686      var cTitle = this.table.columns[column];
62687      this.obj[cTitle] = value;
62688    } else {
62689      throw 'Column #' + column + ' is out of the range of this table';
62690    }
62691  }
62692};
62693
62694/**
62695 *  Stores a Float value in the TableRow's specified column.
62696 *  The column may be specified by either its ID or title.
62697 *
62698 *  @method  setNum
62699 *  @param {String|Integer} column Column ID (Number)
62700 *                                or Title (String)
62701 *  @param {Number|String} value  The value to be stored
62702 *                                as a Float
62703 * @example
62704 * <div class="norender"><code>
62705 * // Given the CSV file "mammals.csv" in the project's "assets" folder:
62706 * //
62707 * // id,species,name
62708 * // 0,Capra hircus,Goat
62709 * // 1,Panthera pardus,Leopard
62710 * // 2,Equus zebra,Zebra
62711 *
62712 * var table;
62713 *
62714 * function preload() {
62715 *   //my table is comma separated value "csv"
62716 *   //and has a header specifying the columns labels
62717 *   table = loadTable('assets/mammals.csv', 'csv', 'header');
62718 * }
62719 *
62720 * function setup() {
62721 *   var rows = table.getRows();
62722 *   for (var r = 0; r < rows.length; r++) {
62723 *     rows[r].setNum('id', r + 10);
62724 *   }
62725 *
62726 *   print(table.getArray());
62727 * }
62728 * </code></div>
62729 *
62730 * @alt
62731 * no image displayed
62732 */
62733p5.TableRow.prototype.setNum = function(column, value) {
62734  var floatVal = parseFloat(value);
62735  this.set(column, floatVal);
62736};
62737
62738/**
62739 *  Stores a String value in the TableRow's specified column.
62740 *  The column may be specified by either its ID or title.
62741 *
62742 *  @method  setString
62743 *  @param {String|Integer} column Column ID (Number)
62744 *                                or Title (String)
62745 *  @param {String|Number|Boolean|Object} value  The value to be stored
62746 *                                as a String
62747 * @example
62748 * <div class="norender"><code>
62749 * // Given the CSV file "mammals.csv" in the project's "assets" folder:
62750 * //
62751 * // id,species,name
62752 * // 0,Capra hircus,Goat
62753 * // 1,Panthera pardus,Leopard
62754 * // 2,Equus zebra,Zebra
62755 *
62756 * var table;
62757 *
62758 * function preload() {
62759 *   //my table is comma separated value "csv"
62760 *   //and has a header specifying the columns labels
62761 *   table = loadTable('assets/mammals.csv', 'csv', 'header');
62762 * }
62763 *
62764 * function setup() {
62765 *   var rows = table.getRows();
62766 *   for (var r = 0; r < rows.length; r++) {
62767 *     var name = rows[r].getString('name');
62768 *     rows[r].setString('name', 'A ' + name + ' named George');
62769 *   }
62770 *
62771 *   print(table.getArray());
62772 * }
62773 * </code></div>
62774 *
62775 * @alt
62776 * no image displayed
62777 */
62778p5.TableRow.prototype.setString = function(column, value) {
62779  var stringVal = value.toString();
62780  this.set(column, stringVal);
62781};
62782
62783/**
62784 *  Retrieves a value from the TableRow's specified column.
62785 *  The column may be specified by either its ID or title.
62786 *
62787 *  @method  get
62788 *  @param  {String|Integer} column columnName (string) or
62789 *                                   ID (number)
62790 *  @return {String|Number}
62791 *
62792 * @example
62793 * <div class="norender"><code>
62794 * // Given the CSV file "mammals.csv" in the project's "assets" folder:
62795 * //
62796 * // id,species,name
62797 * // 0,Capra hircus,Goat
62798 * // 1,Panthera pardus,Leopard
62799 * // 2,Equus zebra,Zebra
62800 *
62801 * var table;
62802 *
62803 * function preload() {
62804 *   //my table is comma separated value "csv"
62805 *   //and has a header specifying the columns labels
62806 *   table = loadTable('assets/mammals.csv', 'csv', 'header');
62807 * }
62808 *
62809 * function setup() {
62810 *   var names = [];
62811 *   var rows = table.getRows();
62812 *   for (var r = 0; r < rows.length; r++) {
62813 *     names.push(rows[r].get('name'));
62814 *   }
62815 *
62816 *   print(names);
62817 * }
62818 * </code></div>
62819 *
62820 * @alt
62821 * no image displayed
62822 */
62823p5.TableRow.prototype.get = function(column) {
62824  if (typeof column === 'string') {
62825    return this.obj[column];
62826  } else {
62827    return this.arr[column];
62828  }
62829};
62830
62831/**
62832 *  Retrieves a Float value from the TableRow's specified
62833 *  column. The column may be specified by either its ID or
62834 *  title.
62835 *
62836 *  @method  getNum
62837 *  @param  {String|Integer} column columnName (string) or
62838 *                                   ID (number)
62839 *  @return {Number}  Float Floating point number
62840 * @example
62841 * <div class="norender"><code>
62842 * // Given the CSV file "mammals.csv" in the project's "assets" folder:
62843 * //
62844 * // id,species,name
62845 * // 0,Capra hircus,Goat
62846 * // 1,Panthera pardus,Leopard
62847 * // 2,Equus zebra,Zebra
62848 *
62849 * var table;
62850 *
62851 * function preload() {
62852 *   //my table is comma separated value "csv"
62853 *   //and has a header specifying the columns labels
62854 *   table = loadTable('assets/mammals.csv', 'csv', 'header');
62855 * }
62856 *
62857 * function setup() {
62858 *   var rows = table.getRows();
62859 *   var minId = Infinity;
62860 *   var maxId = -Infinity;
62861 *   for (var r = 0; r < rows.length; r++) {
62862 *     var id = rows[r].getNum('id');
62863 *     minId = min(minId, id);
62864 *     maxId = min(maxId, id);
62865 *   }
62866 *   print('minimum id = ' + minId + ', maximum id = ' + maxId);
62867 * }
62868 * </code></div>
62869 *
62870 * @alt
62871 * no image displayed
62872 */
62873p5.TableRow.prototype.getNum = function(column) {
62874  var ret;
62875  if (typeof column === 'string') {
62876    ret = parseFloat(this.obj[column]);
62877  } else {
62878    ret = parseFloat(this.arr[column]);
62879  }
62880
62881  if (ret.toString() === 'NaN') {
62882    throw 'Error: ' + this.obj[column] + ' is NaN (Not a Number)';
62883  }
62884  return ret;
62885};
62886
62887/**
62888 *  Retrieves an String value from the TableRow's specified
62889 *  column. The column may be specified by either its ID or
62890 *  title.
62891 *
62892 *  @method  getString
62893 *  @param  {String|Integer} column columnName (string) or
62894 *                                   ID (number)
62895 *  @return {String}  String
62896 * @example
62897 * <div class="norender"><code>
62898 * // Given the CSV file "mammals.csv" in the project's "assets" folder:
62899 * //
62900 * // id,species,name
62901 * // 0,Capra hircus,Goat
62902 * // 1,Panthera pardus,Leopard
62903 * // 2,Equus zebra,Zebra
62904 *
62905 * var table;
62906 *
62907 * function preload() {
62908 *   //my table is comma separated value "csv"
62909 *   //and has a header specifying the columns labels
62910 *   table = loadTable('assets/mammals.csv', 'csv', 'header');
62911 * }
62912 *
62913 * function setup() {
62914 *   var rows = table.getRows();
62915 *   var longest = '';
62916 *   for (var r = 0; r < rows.length; r++) {
62917 *     var species = rows[r].getString('species');
62918 *     if (longest.length < species.length) {
62919 *       longest = species;
62920 *     }
62921 *   }
62922 *
62923 *   print('longest: ' + longest);
62924 * }
62925 * </code></div>
62926 *
62927 * @alt
62928 * no image displayed
62929 */
62930p5.TableRow.prototype.getString = function(column) {
62931  if (typeof column === 'string') {
62932    return this.obj[column].toString();
62933  } else {
62934    return this.arr[column].toString();
62935  }
62936};
62937
62938module.exports = p5;
62939
62940},{"../core/core":22}],49:[function(_dereq_,module,exports){
62941/**
62942 * @module IO
62943 * @submodule XML
62944 * @requires core
62945 */
62946
62947'use strict';
62948
62949var p5 = _dereq_('../core/core');
62950
62951/**
62952 * XML is a representation of an XML object, able to parse XML code. Use
62953 * loadXML() to load external XML files and create XML objects.
62954 *
62955 * @class p5.XML
62956 * @constructor
62957 * @example
62958 * <div class='norender'><code>
62959 * // The following short XML file called "mammals.xml" is parsed
62960 * // in the code below.
62961 * //
62962 * // <?xml version="1.0"?>
62963 * // &lt;mammals&gt;
62964 * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
62965 * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
62966 * //   &lt;animal id="2" species="Equus zebra">
62966Zebra&lt;/animal&gt;
62967 * // &lt;/mammals&gt;
62968 *
62969 * var xml;
62970 *
62971 * function preload() {
62972 *   xml = loadXML('assets/mammals.xml');
62973 * }
62974 *
62975 * function setup() {
62976 *   var children = xml.getChildren('animal');
62977 *
62978 *   for (var i = 0; i < children.length; i++) {
62979 *     var id = children[i].getNum('id');
62980 *     var coloring = children[i].getString('species');
62981 *     var name = children[i].getContent();
62982 *     print(id + ', ' + coloring + ', ' + name);
62983 *   }
62984 * }
62985 *
62986 * // Sketch prints:
62987 * // 0, Capra hircus, Goat
62988 * // 1, Panthera pardus, Leopard
62989 * // 2, Equus zebra, Zebra
62990 * </code></div>
62991 *
62992 * @alt
62993 * no image displayed
62994 *
62995 */
62996p5.XML = function() {
62997  this.name = null; //done
62998  this.attributes = {}; //done
62999  this.children = [];
63000  this.parent = null;
63001  this.content = null; //done
63002};
63003
63004/**
63005 * Gets a copy of the element's parent. Returns the parent as another
63006 * p5.XML object.
63007 *
63008 * @method getParent
63009 * @return {p5.XML}   element parent
63010 * @example
63011 * <div class='norender'><code>
63012 * // The following short XML file called "mammals.xml" is parsed
63013 * // in the code below.
63014 * //
63015 * // <?xml version="1.0"?>
63016 * // &lt;mammals&gt;
63017 * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
63018 * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
63019 * //   &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
63020 * // &lt;/mammals&gt;
63021 *
63022 * var xml;
63023 *
63024 * function preload() {
63025 *   xml = loadXML('assets/mammals.xml');
63026 * }
63027 *
63028 * function setup() {
63029 *   var children = xml.getChildren('animal');
63030 *   var parent = children[1].getParent();
63031 *   print(parent.getName());
63032 * }
63033 *
63034 * // Sketch prints:
63035 * // mammals
63036 * </code></div>
63037 */
63038p5.XML.prototype.getParent = function() {
63039  return this.parent;
63040};
63041
63042/**
63043 *  Gets the element's full name, which is returned as a String.
63044 *
63045 * @method getName
63046 * @return {String} the name of the node
63047 * @example&lt;animal
63048 * <div class='norender'><code>
63049 * // The following short XML file called "mammals.xml" is parsed
63050 * // in the code below.
63051 * //
63052 * // <?xml version="1.0"?>
63053 * // &lt;mammals&gt;
63054 * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
63055 * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
63056 * //   &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
63057 * // &lt;/mammals&gt;
63058 *
63059 * var xml;
63060 *
63061 * function preload() {
63062 *   xml = loadXML('assets/mammals.xml');
63063 * }
63064 *
63065 * function setup() {
63066 *   print(xml.getName());
63067 * }
63068 *
63069 * // Sketch prints:
63070 * // mammals
63071 * </code></div>
63072 */
63073p5.XML.prototype.getName = function() {
63074  return this.name;
63075};
63076
63077/**
63078 * Sets the element's name, which is specified as a String.
63079 *
63080 * @method setName
63081 * @param {String} the new name of the node
63082 * @example&lt;animal
63083 * <div class='norender'><code>
63084 * // The following short XML file called "mammals.xml" is parsed
63085 * // in the code below.
63086 * //
63087 * // <?xml version="1.0"?>
63088 * // &lt;mammals&gt;
63089 * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
63090 * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
63091 * //   &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
63092 * // &lt;/mammals&gt;
63093 *
63094 * var xml;
63095 *
63096 * function preload() {
63097 *   xml = loadXML('assets/mammals.xml');
63098 * }
63099 *
63100 * function setup() {
63101 *   print(xml.getName());
63102 *   xml.setName('fish');
63103 *   print(xml.getName());
63104 * }
63105 *
63106 * // Sketch prints:
63107 * // mammals
63108 * // fish
63109 * </code></div>
63110 */
63111p5.XML.prototype.setName = function(name) {
63112  this.name = name;
63113};
63114
63115/**
63116 * Checks whether or not the element has any children, and returns the result
63117 * as a boolean.
63118 *
63119 * @method hasChildren
63120 * @return {boolean}
63121 * @example&lt;animal
63122 * <div class='norender'><code>
63123 * // The following short XML file called "mammals.xml" is parsed
63124 * // in the code below.
63125 * //
63126 * // <?xml version="1.0"?>
63127 * // &lt;mammals&gt;
63128 * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
63129 * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
63130 * //   &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
63131 * // &lt;/mammals&gt;
63132 *
63133 * var xml;
63134 *
63135 * function preload() {
63136 *   xml = loadXML('assets/mammals.xml');
63137 * }
63138 *
63139 * function setup() {
63140 *   print(xml.hasChildren());
63141 * }
63142 *
63143 * // Sketch prints:
63144 * // true
63145 * </code></div>
63146 */
63147p5.XML.prototype.hasChildren = function() {
63148  return this.children.length > 0;
63149};
63150
63151/**
63152 * Get the names of all of the element's children, and returns the names as an
63153 * array of Strings. This is the same as looping through and calling getName()
63154 * on each child element individually.
63155 *
63156 * @method listChildren
63157 * @return {String[]} names of the children of the element
63158 * @example&lt;animal
63159 * <div class='norender'><code>
63160 * // The following short XML file called "mammals.xml" is parsed
63161 * // in the code below.
63162 * //
63163 * // <?xml version="1.0"?>
63164 * // &lt;mammals&gt;
63165 * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
63166 * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
63167 * //   &lt;animal id="2" species="Equus zebra">
63167Zebra&lt;/animal&gt;
63168 * // &lt;/mammals&gt;
63169 *
63170 * var xml;
63171 *
63172 * function preload() {
63173 *   xml = loadXML('assets/mammals.xml');
63174 * }
63175 *
63176 * function setup() {
63177 *   print(xml.listChildren());
63178 * }
63179 *
63180 * // Sketch prints:
63181 * // ["animal", "animal", "animal"]
63182 * </code></div>
63183 */
63184p5.XML.prototype.listChildren = function() {
63185  return this.children.map(function(c) {
63186    return c.name;
63187  });
63188};
63189
63190/**
63191 * Returns all of the element's children as an array of p5.XML objects. When
63192 * the name parameter is specified, then it will return all children that match
63193 * that name.
63194 *
63195 * @method getChildren
63196 * @param {String} [name] element name
63197 * @return {p5.XML[]} children of the element
63198 * @example&lt;animal
63199 * <div class='norender'><code>
63200 * // The following short XML file called "mammals.xml" is parsed
63201 * // in the code below.
63202 * //
63203 * // <?xml version="1.0"?>
63204 * // &lt;mammals&gt;
63205 * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
63206 * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
63207 * //   &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
63208 * // &lt;/mammals&gt;
63209 *
63210 * var xml;
63211 *
63212 * function preload() {
63213 *   xml = loadXML('assets/mammals.xml');
63214 * }
63215 *
63216 * function setup() {
63217 *   var animals = xml.getChildren('animal');
63218 *
63219 *   for (var i = 0; i < animals.length; i++) {
63220 *     print(animals[i].getContent());
63221 *   }
63222 * }
63223 *
63224 * // Sketch prints:
63225 * // "Goat"
63226 * // "Leopard"
63227 * // "Zebra"
63228 * </code></div>
63229 */
63230p5.XML.prototype.getChildren = function(param) {
63231  if (param) {
63232    return this.children.filter(function(c) {
63233      return c.name === param;
63234    });
63235  } else {
63236    return this.children;
63237  }
63238};
63239
63240/**
63241 * Returns the first of the element's children that matches the name parameter
63242 * or the child of the given index.It returns undefined if no matching
63243 * child is found.
63244 *
63245 * @method getChild
63246 * @param {String|Integer} name element name or index
63247 * @return {p5.XML}
63248 * @example&lt;animal
63249 * <div class='norender'><code>
63250 * // The following short XML file called "mammals.xml" is parsed
63251 * // in the code below.
63252 * //
63253 * // <?xml version="1.0"?>
63254 * // &lt;mammals&gt;
63255 * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
63256 * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
63257 * //   &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
63258 * // &lt;/mammals&gt;
63259 *
63260 * var xml;
63261 *
63262 * function preload() {
63263 *   xml = loadXML('assets/mammals.xml');
63264 * }
63265 *
63266 * function setup() {
63267 *   var firstChild = xml.getChild('animal');
63268 *   print(firstChild.getContent());
63269 * }
63270 *
63271 * // Sketch prints:
63272 * // "Goat"
63273 * </code></div>
63274 * <div class='norender'><code>
63275 * var xml;
63276 *
63277 * function preload() {
63278 *   xml = loadXML('assets/mammals.xml');
63279 * }
63280 *
63281 * function setup() {
63282 *   var secondChild = xml.getChild(1);
63283 *   print(secondChild.getContent());
63284 * }
63285 *
63286 * // Sketch prints:
63287 * // "Leopard"
63288 * </code></div>
63289 */
63290p5.XML.prototype.getChild = function(param) {
63291  if (typeof param === 'string') {
63292    for (var i = 0; i < this.children.length; i++) {
63293      var child = this.children[i];
63294      if (child.name === param) return child;
63295    }
63296  } else {
63297    return this.children[param];
63298  }
63299};
63300
63301/**
63302 * Appends a new child to the element. The child can be specified with
63303 * either a String, which will be used as the new tag's name, or as a
63304 * reference to an existing p5.XML object.
63305 * A reference to the newly created child is returned as an p5.XML object.
63306 *
63307 * @method addChild
63308 * @param {p5.XML} node a p5.XML Object which will be the child to be added
63309 * @example
63310 * <div class='norender'><code>
63311 * // The following short XML file called "mammals.xml" is parsed
63312 * // in the code below.
63313 * //
63314 * // <?xml version="1.0"?>
63315 * // &lt;mammals&gt;
63316 * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
63317 * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
63318 * //   &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
63319 * // &lt;/mammals&gt;
63320 *
63321 * var xml;
63322 *
63323 * function preload() {
63324 *   xml = loadXML('assets/mammals.xml');
63325 * }
63326 *
63327 * function setup() {
63328 *   var child = new p5.XML();
63329 *   child.setAttribute('id', '3');
63330 *   child.setAttribute('species', 'Ornithorhynchus anatinus');
63331 *   child.setContent('Platypus');
63332 *   xml.addChild(child);
63333 *
63334 *   var animals = xml.getChildren('animal');
63335 *   print(animals[animals.length - 1].getContent());
63336 * }
63337 *
63338 * // Sketch prints:
63339 * // "Goat"
63340 * // "Leopard"
63341 * // "Zebra"
63342 * </code></div>
63343 */
63344p5.XML.prototype.addChild = function(node) {
63345  if (node instanceof p5.XML) {
63346    this.children.push(node);
63347  } else {
63348    // PEND
63349  }
63350};
63351
63352/**
63353 * Removes the element specified by name or index.
63354 *
63355 * @method removeChild
63356 * @param {String|Integer} name element name or index
63357 * @example
63358 * <div class='norender'><code>
63359 * // The following short XML file called "mammals.xml" is parsed
63360 * // in the code below.
63361 * //
63362 * // <?xml version="1.0"?>
63363 * // &lt;mammals&gt;
63364 * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
63365 * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
63366 * //   &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
63367 * // &lt;/mammals&gt;
63368 *
63369 * var xml;
63370 *
63371 * function preload() {
63372 *   xml = loadXML('assets/mammals.xml');
63373 * }
63374 *
63375 * function setup() {
63376 *   xml.removeChild('animal');
63377 *   var children = xml.getChildren();
63378 *   for (var i = 0; i < children.length; i++) {
63379 *     print(children[i].getContent());
63380 *   }
63381 * }
63382 *
63383 * // Sketch prints:
63384 * // "Leopard"
63385 * // "Zebra"
63386 * </code></div>
63387 * <div class='norender'><code>
63388 * var xml;
63389 *
63390 * function preload() {
63391 *   xml = loadXML('assets/mammals.xml');
63392 * }
63393 *
63394 * function setup() {
63395 *   xml.removeChild(1);
63396 *   var children = xml.getChildren();
63397 *   for (var i = 0; i < children.length; i++) {
63398 *     print(children[i].getContent());
63399 *   }
63400 * }
63401 *
63402 * // Sketch prints:
63403 * // "Goat"
63404 * // "Zebra"
63405 * </code></div>
63406 */
63407p5.XML.prototype.removeChild = function(param) {
63408  var ind = -1;
63409  if (typeof param === 'string') {
63410    for (var i = 0; i < this.children.length; i++) {
63411      if (this.children[i].name === param) {
63412        ind = i;
63413        break;
63414      }
63415    }
63416  } else {
63417    ind = param;
63418  }
63419  if (ind !== -1) {
63420    this.children.splice(ind, 1);
63421  }
63422};
63423
63424/**
63425 * Counts the specified element's number of attributes, returned as an Number.
63426 *
63427 * @method getAttributeCount
63428 * @return {Integer}
63429 * @example
63430 * <div class='norender'><code>
63431 * // The following short XML file called "mammals.xml" is parsed
63432 * // in the code below.
63433 * //
63434 * // <?xml version="1.0"?>
63435 * // &lt;mammals&gt;
63436 * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
63437 * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
63438 * //   &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
63439 * // &lt;/mammals&gt;
63440 *
63441 * var xml;
63442 *
63443 * function preload() {
63444 *   xml = loadXML('assets/mammals.xml');
63445 * }
63446 *
63447 * function setup() {
63448 *   var firstChild = xml.getChild('animal');
63449 *   print(firstChild.getAttributeCount());
63450 * }
63451 *
63452 * // Sketch prints:
63453 * // 2
63454 * </code></div>
63455 */
63456p5.XML.prototype.getAttributeCount = function() {
63457  return Object.keys(this.attributes).length;
63458};
63459
63460/**
63461 * Gets all of the specified element's attributes, and returns them as an
63462 * array of Strings.
63463 *
63464 * @method listAttributes
63465 * @return {String[]} an array of strings containing the names of attributes
63466 * @example
63467 * <div class='norender'><code>
63468 * // The following short XML file called "mammals.xml" is parsed
63469 * // in the code below.
63470 * //
63471 * // <?xml version="1.0"?>
63472 * // &lt;mammals&gt;
63473 * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
63474 * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
63475 * //   &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
63476 * // &lt;/mammals&gt;
63477 *
63478 * var xml;
63479 *
63480 * function preload() {
63481 *   xml = loadXML('assets/mammals.xml');
63482 * }
63483 *
63484 * function setup() {
63485 *   var firstChild = xml.getChild('animal');
63486 *   print(firstChild.listAttributes());
63487 * }
63488 *
63489 * // Sketch prints:
63490 * // ["id", "species"]
63491 * </code></div>
63492 */
63493p5.XML.prototype.listAttributes = function() {
63494  return Object.keys(this.attributes);
63495};
63496
63497/**
63498 *  Checks whether or not an element has the specified attribute.
63499 *
63500 * @method hasAttribute
63501 * @param {String} the attribute to be checked
63502 * @return {boolean} true if attribute found else false
63503 * @example
63504 * <div class='norender'><code>
63505 * // The following short XML file called "mammals.xml" is parsed
63506 * // in the code below.
63507 * //
63508 * // <?xml version="1.0"?>
63509 * // &lt;mammals&gt;
63510 * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
63511 * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
63512 * //   &lt;animal id="2" species="Equus zebra">
63512Zebra&lt;/animal&gt;
63513 * // &lt;/mammals&gt;
63514 *
63515 * var xml;
63516 *
63517 * function preload() {
63518 *   xml = loadXML('assets/mammals.xml');
63519 * }
63520 *
63521 * function setup() {
63522 *   var firstChild = xml.getChild('animal');
63523 *   print(firstChild.hasAttribute('species'));
63524 *   print(firstChild.hasAttribute('color'));
63525 * }
63526 *
63527 * // Sketch prints:
63528 * // true
63529 * // false
63530 * </code></div>
63531 */
63532p5.XML.prototype.hasAttribute = function(name) {
63533  return this.attributes[name] ? true : false;
63534};
63535
63536/**
63537 * Returns an attribute value of the element as an Number. If the defaultValue
63538 * parameter is specified and the attribute doesn't exist, then defaultValue
63539 * is returned. If no defaultValue is specified and the attribute doesn't
63540 * exist, the value 0 is returned.
63541 *
63542 * @method getNum
63543 * @param {String} name            the non-null full name of the attribute
63544 * @param {Number} [defaultValue]  the default value of the attribute
63545 * @return {Number}
63546 * @example
63547 * <div class='norender'><code>
63548 * // The following short XML file called "mammals.xml" is parsed
63549 * // in the code below.
63550 * //
63551 * // <?xml version="1.0"?>
63552 * // &lt;mammals&gt;
63553 * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
63554 * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
63555 * //   &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
63556 * // &lt;/mammals&gt;
63557 *
63558 * var xml;
63559 *
63560 * function preload() {
63561 *   xml = loadXML('assets/mammals.xml');
63562 * }
63563 *
63564 * function setup() {
63565 *   var firstChild = xml.getChild('animal');
63566 *   print(firstChild.getNum('id'));
63567 * }
63568 *
63569 * // Sketch prints:
63570 * // 0
63571 * </code></div>
63572 */
63573p5.XML.prototype.getNum = function(name, defaultValue) {
63574  return Number(this.attributes[name]) || defaultValue || 0;
63575};
63576
63577/**
63578 * Returns an attribute value of the element as an String. If the defaultValue
63579 * parameter is specified and the attribute doesn't exist, then defaultValue
63580 * is returned. If no defaultValue is specified and the attribute doesn't
63581 * exist, null is returned.
63582 *
63583 * @method getString
63584 * @param {String} name            the non-null full name of the attribute
63585 * @param {Number} [defaultValue]  the default value of the attribute
63586 * @return {String}
63587 * @example
63588 * <div class='norender'><code>
63589 * // The following short XML file called "mammals.xml" is parsed
63590 * // in the code below.
63591 * //
63592 * // <?xml version="1.0"?>
63593 * // &lt;mammals&gt;
63594 * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
63595 * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
63596 * //   &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
63597 * // &lt;/mammals&gt;
63598 *
63599 * var xml;
63600 *
63601 * function preload() {
63602 *   xml = loadXML('assets/mammals.xml');
63603 * }
63604 *
63605 * function setup() {
63606 *   var firstChild = xml.getChild('animal');
63607 *   print(firstChild.getString('species'));
63608 * }
63609 *
63610 * // Sketch prints:
63611 * // "Capra hircus"
63612 * </code></div>
63613 */
63614p5.XML.prototype.getString = function(name, defaultValue) {
63615  return String(this.attributes[name]) || defaultValue || null;
63616};
63617
63618/**
63619 * Sets the content of an element's attribute. The first parameter specifies
63620 * the attribute name, while the second specifies the new content.
63621 *
63622 * @method setAttribute
63623 * @param {String} name            the full name of the attribute
63624 * @param {Number|String|Boolean} value  the value of the attribute
63625 * @example
63626 * <div class='norender'><code>
63627 * // The following short XML file called "mammals.xml" is parsed
63628 * // in the code below.
63629 * //
63630 * // <?xml version="1.0"?>
63631 * // &lt;mammals&gt;
63632 * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
63633 * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
63634 * //   &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
63635 * // &lt;/mammals&gt;
63636 *
63637 * var xml;
63638 *
63639 * function preload() {
63640 *   xml = loadXML('assets/mammals.xml');
63641 * }
63642 *
63643 * function setup() {
63644 *   var firstChild = xml.getChild('animal');
63645 *   print(firstChild.getString('species'));
63646 *   firstChild.setAttribute('species', 'Jamides zebra');
63647 *   print(firstChild.getString('species'));
63648 * }
63649 *
63650 * // Sketch prints:
63651 * // "Capra hircus"
63652 * // "Jamides zebra"
63653 * </code></div>
63654 */
63655p5.XML.prototype.setAttribute = function(name, value) {
63656  if (this.attributes[name]) {
63657    this.attributes[name] = value;
63658  }
63659};
63660
63661/**
63662 * Returns the content of an element. If there is no such content,
63663 * defaultValue is returned if specified, otherwise null is returned.
63664 *
63665 * @method getContent
63666 * @param {String} [defaultValue] value returned if no content is found
63667 * @return {String}
63668 * @example
63669 * <div class='norender'><code>
63670 * // The following short XML file called "mammals.xml" is parsed
63671 * // in the code below.
63672 * //
63673 * // <?xml version="1.0"?>
63674 * // &lt;mammals&gt;
63675 * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
63676 * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
63677 * //   &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
63678 * // &lt;/mammals&gt;
63679 *
63680 * var xml;
63681 *
63682 * function preload() {
63683 *   xml = loadXML('assets/mammals.xml');
63684 * }
63685 *
63686 * function setup() {
63687 *   var firstChild = xml.getChild('animal');
63688 *   print(firstChild.getContent());
63689 * }
63690 *
63691 * // Sketch prints:
63692 * // "Goat"
63693 * </code></div>
63694 */
63695p5.XML.prototype.getContent = function(defaultValue) {
63696  return this.content || defaultValue || null;
63697};
63698
63699/**
63700 * Sets the element's content.
63701 *
63702 * @method setContent
63703 * @param {String} text the new content
63704 * @example
63705 * <div class='norender'><code>
63706 * // The following short XML file called "mammals.xml" is parsed
63707 * // in the code below.
63708 * //
63709 * // <?xml version="1.0"?>
63710 * // &lt;mammals&gt;
63711 * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
63712 * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
63713 * //   &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
63714 * // &lt;/mammals&gt;
63715 *
63716 * var xml;
63717 *
63718 * function preload() {
63719 *   xml = loadXML('assets/mammals.xml');
63720 * }
63721 *
63722 * function setup() {
63723 *   var firstChild = xml.getChild('animal');
63724 *   print(firstChild.getContent());
63725 *   firstChild.setContent('Mountain Goat');
63726 *   print(firstChild.getContent());
63727 * }
63728 *
63729 * // Sketch prints:
63730 * // "Goat"
63731 * // "Mountain Goat"
63732 * </code></div>
63733 */
63734p5.XML.prototype.setContent = function(content) {
63735  if (!this.children.length) {
63736    this.content = content;
63737  }
63738};
63739
63740/* HELPERS */
63741/**
63742 * This method is called while the parsing of XML (when loadXML() is
63743 * called). The difference between this method and the setContent()
63744 * method defined later is that this one is used to set the content
63745 * when the node in question has more nodes under it and so on and
63746 * not directly text content. While in the other one is used when
63747 * the node in question directly has text inside it.
63748 *
63749 */
63750p5.XML.prototype._setCont = function(content) {
63751  var str;
63752  str = content;
63753  str = str.replace(/\s\s+/g, ',');
63754  //str = str.split(',');
63755  this.content = str;
63756};
63757
63758/**
63759 * This method is called while the parsing of XML (when loadXML() is
63760 * called). The XML node is passed and its attributes are stored in the
63761 * p5.XML's attribute Object.
63762 *
63763 */
63764p5.XML.prototype._setAttributes = function(node) {
63765  var att = {};
63766  var attributes = node.attributes;
63767  if (attributes) {
63768    for (var i = 0; i < attributes.length; i++) {
63769      var attribute = attributes[i];
63770      att[attribute.nodeName] = attribute.nodeValue;
63771    }
63772  }
63773  this.attributes = att;
63774};
63775
63776module.exports = p5;
63777
63778},{"../core/core":22}],50:[function(_dereq_,module,exports){
63779/**
63780 * @module Math
63781 * @submodule Calculation
63782 * @for p5
63783 * @requires core
63784 */
63785
63786'use strict';
63787
63788var p5 = _dereq_('../core/core');
63789
63790/**
63791 * Calculates the absolute value (magnitude) of a number. Maps to Math.abs().
63792 * The absolute value of a number is always positive.
63793 *
63794 * @method abs
63795 * @param  {Number} n number to compute
63796 * @return {Number}   absolute value of given number
63797 * @example
63798 * <div class = "norender"><code>
63799 * function setup() {
63800 *   var x = -3;
63801 *   var y = abs(x);
63802 *
63803 *   print(x); // -3
63804 *   print(y); // 3
63805 * }
63806 * </code></div>
63807 *
63808 * @alt
63809 * no image displayed
63810 *
63811 */
63812p5.prototype.abs = Math.abs;
63813
63814/**
63815 * Calculates the closest int value that is greater than or equal to the
63816 * value of the parameter. Maps to Math.ceil(). For example, ceil(9.03)
63817 * returns the value 10.
63818 *
63819 * @method ceil
63820 * @param  {Number} n number to round up
63821 * @return {Integer}
63821   rounded up number
63822 * @example
63823 * <div><code>
63824 * function draw() {
63825 *   background(200);
63826 *   // map, mouseX between 0 and 5.
63827 *   var ax = map(mouseX, 0, 100, 0, 5);
63828 *   var ay = 66;
63829 *
63830 *   //Get the ceiling of the mapped number.
63831 *   var bx = ceil(map(mouseX, 0, 100, 0, 5));
63832 *   var by = 33;
63833 *
63834 *   // Multiply the mapped numbers by 20 to more easily
63835 *   // see the changes.
63836 *   stroke(0);
63837 *   fill(0);
63838 *   line(0, ay, ax * 20, ay);
63839 *   line(0, by, bx * 20, by);
63840 *
63841 *   // Reformat the float returned by map and draw it.
63842 *   noStroke();
63843 *   text(nfc(ax, 2), ax, ay - 5);
63844 *   text(nfc(bx, 1), bx, by - 5);
63845 * }
63846 * </code></div>
63847 *
63848 * @alt
63849 * 2 horizontal lines & number sets. increase with mouse x. bottom to 2 decimals
63850 *
63851 */
63852p5.prototype.ceil = Math.ceil;
63853
63854/**
63855 * Constrains a value between a minimum and maximum value.
63856 *
63857 * @method constrain
63858 * @param  {Number} n    number to constrain
63859 * @param  {Number} low  minimum limit
63860 * @param  {Number} high maximum limit
63861 * @return {Number}      constrained number
63862 * @example
63863 * <div><code>
63864 * function draw() {
63865 *   background(200);
63866 *
63867 *   var leftWall = 25;
63868 *   var rightWall = 75;
63869 *
63870 *   // xm is just the mouseX, while
63871 *   // xc is the mouseX, but constrained
63872 *   // between the leftWall and rightWall!
63873 *   var xm = mouseX;
63874 *   var xc = constrain(mouseX, leftWall, rightWall);
63875 *
63876 *   // Draw the walls.
63877 *   stroke(150);
63878 *   line(leftWall, 0, leftWall, height);
63879 *   line(rightWall, 0, rightWall, height);
63880 *
63881 *   // Draw xm and xc as circles.
63882 *   noStroke();
63883 *   fill(150);
63884 *   ellipse(xm, 33, 9, 9); // Not Constrained
63885 *   fill(0);
63886 *   ellipse(xc, 66, 9, 9); // Constrained
63887 * }
63888 * </code></div>
63889 *
63890 * @alt
63891 * 2 vertical lines. 2 ellipses move with mouse X 1 does not move passed lines
63892 *
63893 */
63894p5.prototype.constrain = function(n, low, high) {
63895  p5._validateParameters('constrain', arguments);
63896  return Math.max(Math.min(n, high), low);
63897};
63898
63899/**
63900 * Calculates the distance between two points.
63901 *
63902 * @method dist
63903 * @param  {Number} x1 x-coordinate of the first point
63904 * @param  {Number} y1 y-coordinate of the first point
63905 * @param  {Number} x2 x-coordinate of the second point
63906 * @param  {Number} y2 y-coordinate of the second point
63907 * @return {Number}    distance between the two points
63908 *
63909 * @example
63910 * <div><code>
63911 * // Move your mouse inside the canvas to see the
63912 * // change in distance between two points!
63913 * function draw() {
63914 *   background(200);
63915 *   fill(0);
63916 *
63917 *   var x1 = 10;
63918 *   var y1 = 90;
63919 *   var x2 = mouseX;
63920 *   var y2 = mouseY;
63921 *
63922 *   line(x1, y1, x2, y2);
63923 *   ellipse(x1, y1, 7, 7);
63924 *   ellipse(x2, y2, 7, 7);
63925 *
63926 *   // d is the length of the line
63927 *   // the distance from point 1 to point 2.
63928 *   var d = int(dist(x1, y1, x2, y2));
63929 *
63930 *   // Let's write d along the line we are drawing!
63931 *   push();
63932 *   translate((x1 + x2) / 2, (y1 + y2) / 2);
63933 *   rotate(atan2(y2 - y1, x2 - x1));
63934 *   text(nfc(d, 1), 0, -5);
63935 *   pop();
63936 *   // Fancy!
63937 * }
63938 * </code></div>
63939 *
63940 * @alt
63941 * 2 ellipses joined by line. 1 ellipse moves with mouse X&Y. Distance displayed.
63942 */
63943/**
63944 * @method dist
63945 * @param  {Number} x1
63946 * @param  {Number} y1
63947 * @param  {Number} z1 z-coordinate of the first point
63948 * @param  {Number} x2
63949 * @param  {Number} y2
63950 * @param  {Number} z2 z-coordinate of the second point
63951 * @return {Number}    distance between the two points
63952 */
63953p5.prototype.dist = function() {
63954  p5._validateParameters('dist', arguments);
63955  if (arguments.length === 4) {
63956    //2D
63957    return hypot(arguments[2] - arguments[0], arguments[3] - arguments[1]);
63958  } else if (arguments.length === 6) {
63959    //3D
63960    return hypot(
63961      arguments[3] - arguments[0],
63962      arguments[4] - arguments[1],
63963      arguments[5] - arguments[2]
63964    );
63965  }
63966};
63967
63968/**
63969 * Returns Euler's number e (2.71828...) raised to the power of the n
63970 * parameter. Maps to Math.exp().
63971 *
63972 * @method exp
63973 * @param  {Number} n exponent to raise
63974 * @return {Number}   e^n
63975 * @example
63976 * <div><code>
63977 * function draw() {
63978 *   background(200);
63979 *
63980 *   // Compute the exp() function with a value between 0 and 2
63981 *   var xValue = map(mouseX, 0, width, 0, 2);
63982 *   var yValue = exp(xValue);
63983 *
63984 *   var y = map(yValue, 0, 8, height, 0);
63985 *
63986 *   var legend = 'exp (' + nfc(xValue, 3) + ')\n= ' + nf(yValue, 1, 4);
63987 *   stroke(150);
63988 *   line(mouseX, y, mouseX, height);
63989 *   fill(0);
63990 *   text(legend, 5, 15);
63991 *   noStroke();
63992 *   ellipse(mouseX, y, 7, 7);
63993 *
63994 *   // Draw the exp(x) curve,
63995 *   // over the domain of x from 0 to 2
63996 *   noFill();
63997 *   stroke(0);
63998 *   beginShape();
63999 *   for (var x = 0; x < width; x++) {
64000 *     xValue = map(x, 0, width, 0, 2);
64001 *     yValue = exp(xValue);
64002 *     y = map(yValue, 0, 8, height, 0);
64003 *     vertex(x, y);
64004 *   }
64005 *
64006 *   endShape();
64007 *   line(0, 0, 0, height);
64008 *   line(0, height - 1, width, height - 1);
64009 * }
64010 * </code></div>
64011 *
64012 * @alt
64013 * ellipse moves along a curve with mouse x. e^n displayed.
64014 *
64015 */
64016p5.prototype.exp = Math.exp;
64017
64018/**
64019 * Calculates the closest int value that is less than or equal to the
64020 * value of the parameter. Maps to Math.floor().
64021 *
64022 * @method floor
64023 * @param  {Number} n number to round down
64024 * @return {Integer}  rounded down number
64025 * @example
64026 * <div><code>
64027 * function draw() {
64028 *   background(200);
64029 *   //map, mouseX between 0 and 5.
64030 *   var ax = map(mouseX, 0, 100, 0, 5);
64031 *   var ay = 66;
64032 *
64033 *   //Get the floor of the mapped number.
64034 *   var bx = floor(map(mouseX, 0, 100, 0, 5));
64035 *   var by = 33;
64036 *
64037 *   // Multiply the mapped numbers by 20 to more easily
64038 *   // see the changes.
64039 *   stroke(0);
64040 *   fill(0);
64041 *   line(0, ay, ax * 20, ay);
64042 *   line(0, by, bx * 20, by);
64043 *
64044 *   // Reformat the float returned by map and draw it.
64045 *   noStroke();
64046 *   text(nfc(ax, 2), ax, ay - 5);
64047 *   text(nfc(bx, 1), bx, by - 5);
64048 * }
64049 * </code></div>
64050 *
64051 * @alt
64052 * 2 horizontal lines & number sets. increase with mouse x. bottom to 2 decimals
64053 *
64054 */
64055p5.prototype.floor = Math.floor;
64056
64057/**
64058 * Calculates a number between two numbers at a specific increment. The amt
64059 * parameter is the amount to interpolate between the two values where 0.0
64060 * equal to the first point, 0.1 is very near the first point, 0.5 is
64061 * half-way in between, etc. The lerp function is convenient for creating
64062 * motion along a straight path and for drawing dotted lines.
64063 *
64064 * @method lerp
64065 * @param  {Number} start first value
64066 * @param  {Number} stop  second value
64067 * @param  {Number} amt   number between 0.0 and 1.0
64068 * @return {Number}       lerped value
64069 * @example
64070 * <div><code>
64071 * function setup() {
64072 *   background(200);
64073 *   var a = 20;
64074 *   var b = 80;
64075 *   var c = lerp(a, b, 0.2);
64076 *   var d = lerp(a, b, 0.5);
64077 *   var e = lerp(a, b, 0.8);
64078 *
64079 *   var y = 50;
64080 *
64081 *   strokeWeight(5);
64082 *   stroke(0); // Draw the original points in black
64083 *   point(a, y);
64084 *   point(b, y);
64085 *
64086 *   stroke(100); // Draw the lerp points in gray
64087 *   point(c, y);
64088 *   point(d, y);
64089 *   point(e, y);
64090 * }
64091 * </code></div>
64092 *
64093 * @alt
64094 * 5 points horizontally staggered mid-canvas. mid 3 are grey, outer black
64095 *
64096 */
64097p5.prototype.lerp = function(start, stop, amt) {
64098  p5._validateParameters('lerp', arguments);
64099  return amt * (stop - start) + start;
64100};
64101
64102/**
64103 * Calculates the natural logarithm (the base-e logarithm) of a number. This
64104 * function expects the n parameter to be a value greater than 0.0. Maps to
64105 * Math.log().
64106 *
64107 * @method log
64108 * @param  {Number} n number greater than 0
64109 * @return {Number}   natural logarithm of n
64110 * @example
64111 * <div><code>
64112 * function draw() {
64113 *   background(200);
64114 *   var maxX = 2.8;
64115 *   var maxY = 1.5;
64116 *
64117 *   // Compute the natural log of a value between 0 and maxX
64118 *   var xValue = map(mouseX, 0, width, 0, maxX);
64119 *   if (xValue > 0) {
64120    // Cannot take the log of a negative number.
64121 *     var yValue = log(xValue);
64122 *     var y = map(yValue, -maxY, maxY, height, 0);
64123 *
64124 *     // Display the calculation occurring.
64125 *     var legend = 'log(' + nf(xValue, 1, 2) + ')\n= ' + nf(yValue, 1, 3);
64126 *     stroke(150);
64127 *     line(mouseX, y, mouseX, height);
64128 *     fill(0);
64129 *     text(legend, 5, 15);
64130 *     noStroke();
64131 *     ellipse(mouseX, y, 7, 7);
64132 *   }
64133 *
64134 *   // Draw the log(x) curve,
64135 *   // over the domain of x from 0 to maxX
64136 *   noFill();
64137 *   stroke(0);
64138 *   beginShape();
64139 *   for (var x = 0; x < width; x++) {
64140 *     xValue = map(x, 0, width, 0, maxX);
64141 *     yValue = log(xValue);
64142 *     y = map(yValue, -maxY, maxY, height, 0);
64143 *     vertex(x, y);
64144 *   }
64145 *   endShape();
64146 *   line(0, 0, 0, height);
64147 *   line(0, height / 2, width, height / 2);
64148 * }
64149 * </code></div>
64150 *
64151 * @alt
64152 * ellipse moves along a curve with mouse x. natural logarithm of n displayed.
64153 *
64154 */
64155p5.prototype.log = Math.log;
64156
64157/**
64158 * Calculates the magnitude (or length) of a vector. A vector is a direction
64159 * in space commonly used in computer graphics and linear algebra. Because it
64160 * has no "start" position, the magnitude of a vector can be thought of as
64161 * the distance from the coordinate 0,0 to its x,y value. Therefore, mag() is
64162 * a shortcut for writing dist(0, 0, x, y).
64163 *
64164 * @method mag
64165 * @param  {Number} a first value
64166 * @param  {Number} b second value
64167 * @return {Number}   magnitude of vector from (0,0) to (a,b)
64168 * @example
64169 * <div><code>
64170 * function setup() {
64171 *   var x1 = 20;
64172 *   var x2 = 80;
64173 *   var y1 = 30;
64174 *   var y2 = 70;
64175 *
64176 *   line(0, 0, x1, y1);
64177 *   print(mag(x1, y1)); // Prints "36.05551275463989"
64178 *   line(0, 0, x2, y1);
64179 *   print(mag(x2, y1)); // Prints "85.44003745317531"
64180 *   line(0, 0, x1, y2);
64181 *   print(mag(x1, y2)); // Prints "72.80109889280519"
64182 *   line(0, 0, x2, y2);
64183 *   print(mag(x2, y2)); // Prints "106.3014581273465"
64184 * }
64185 * </code></div>
64186 *
64187 * @alt
64188 * 4 lines of different length radiate from top left of canvas.
64189 *
64190 */
64191p5.prototype.mag = function(x, y) {
64192  p5._validateParameters('mag', arguments);
64193  return hypot(x, y);
64194};
64195
64196/**
64197 * Re-maps a number from one range to another.
64198 * <br><br>
64199 * In the first example above, the number 25 is converted from a value in the
64200 * range of 0 to 100 into a value that ranges from the left edge of the
64201 * window (0) to the right edge (width).
64202 *
64203 * @method map
64204 * @param  {Number} value  the incoming value to be converted
64205 * @param  {Number} start1 lower bound of the value's current range
64206 * @param  {Number} stop1  upper bound of the value's current range
64207 * @param  {Number} start2 lower bound of the value's target range
64208 * @param  {Number} stop2  upper bound of the value's target range
64209 * @param  {Boolean} [withinBounds] constrain the value to the newly mapped range
64210 * @return {Number}        remapped number
64211 * @example
64212 *   <div><code>
64213 * var value = 25;
64214 * var m = map(value, 0, 100, 0, width);
64215 * ellipse(m, 50, 10, 10);
64216</code></div>
64217 *
64218 *   <div><code>
64219 * function setup() {
64220 *   noStroke();
64221 * }
64222 *
64223 * function draw() {
64224 *   background(204);
64225 *   var x1 = map(mouseX, 0, width, 25, 75);
64226 *   ellipse(x1, 25, 25, 25);
64227 *   //This ellipse is constrained to the 0-100 range
64228 *   //after setting withinBounds to true
64229 *   var x2 = map(mouseX, 0, width, 0, 100, true);
64230 *   ellipse(x2, 75, 25, 25);
64231 * }
64232</code></div>
64233 *
64234 * @alt
64235 * 10 by 10 white ellipse with in mid left canvas
64236 * 2 25 by 25 white ellipses move with mouse x. Bottom has more range from X
64237 *
64238 */
64239p5.prototype.map = function(n, start1, stop1, start2, stop2, withinBounds) {
64240  p5._validateParameters('map', arguments);
64241  var newval = (n - start1) / (stop1 - start1) * (stop2 - start2) + start2;
64242  if (!withinBounds) {
64243    return newval;
64244  }
64245  if (start2 < stop2) {
64246    return this.constrain(newval, start2, stop2);
64247  } else {
64248    return this.constrain(newval, stop2, start2);
64249  }
64250};
64251
64252/**
64253 * Determines the largest value in a sequence of numbers, and then returns
64254 * that value. max() accepts any number of Number parameters, or an Array
64255 * of any length.
64256 *
64257 * @method max
64258 * @param  {Number} n0 Number to compare
64259 * @param  {Number} n1 Number to compare
64260 * @return {Number}             maximum Number
64261 * @example
64262 * <div><code>
64263 * function setup() {
64264 *   // Change the elements in the array and run the sketch
64265 *   // to show how max() works!
64266 *   var numArray = [2, 1, 5, 4, 8, 9];
64267 *   fill(0);
64268 *   noStroke();
64269 *   text('Array Elements', 0, 10);
64270 *   // Draw all numbers in the array
64271 *   var spacing = 15;
64272 *   var elemsY = 25;
64273 *   for (var i = 0; i < numArray.length; i++) {
64274 *     text(numArray[i], i * spacing, elemsY);
64275 *   }
64276 *   var maxX = 33;
64277 *   var maxY = 80;
64278 *   // Draw the Maximum value in the array.
64279 *   textSize(32);
64280 *   text(max(numArray), maxX, maxY);
64281 * }
64282 * </code></div>
64283 *
64284 * @alt
64285 * Small text at top reads: Array Elements 2 1 5 4 8 9. Large text at center: 9
64286 *
64287 */
64288/**
64289 * @method max
64290 * @param  {Number[]} nums Numbers to compare
64291 * @return {Number}
64292 */
64293p5.prototype.max = function() {
64294  p5._validateParameters('max', arguments);
64295  if (arguments[0] instanceof Array) {
64296    return Math.max.apply(null, arguments[0]);
64297  } else {
64298    return Math.max.apply(null, arguments);
64299  }
64300};
64301
64302/**
64303 * Determines the smallest value in a sequence of numbers, and then returns
64304 * that value. min() accepts any number of Number parameters, or an Array
64305 * of any length.
64306 *
64307 * @method min
64308 * @param  {Number} n0 Number to compare
64309 * @param  {Number} n1 Number to compare
64310 * @return {Number}             minimum Number
64311 * @example
64312 * <div><code>
64313 * function setup() {
64314 *   // Change the elements in the array and run the sketch
64315 *   // to show how min() works!
64316 *   var numArray = [2, 1, 5, 4, 8, 9];
64317 *   fill(0);
64318 *   noStroke();
64319 *   text('Array Elements', 0, 10);
64320 *   // Draw all numbers in the array
64321 *   var spacing = 15;
64322 *   var elemsY = 25;
64323 *   for (var i = 0; i < numArray.length; i++) {
64324 *     text(numArray[i], i * spacing, elemsY);
64325 *   }
64326 *   var maxX = 33;
64327 *   var maxY = 80;
64328 *   // Draw the Minimum value in the array.
64329 *   textSize(32);
64330 *   text(min(numArray), maxX, maxY);
64331 * }
64332 * </code></div>
64333 *
64334 * @alt
64335 * Small text at top reads: Array Elements 2 1 5 4 8 9. Large text at center: 1
64336 *
64337 */
64338/**
64339 * @method min
64340 * @param  {Number[]} nums Numbers to compare
64341 * @return {Number}
64342 */
64343p5.prototype.min = function() {
64344  p5._validateParameters('min', arguments);
64345  if (arguments[0] instanceof Array) {
64346    return Math.min.apply(null, arguments[0]);
64347  } else {
64348    return Math.min.apply(null, arguments);
64349  }
64350};
64351
64352/**
64353 * Normalizes a number from another range into a value between 0 and 1.
64354 * Identical to map(value, low, high, 0, 1).
64355 * Numbers outside of the range are not clamped to 0 and 1, because
64356 * out-of-range values are often intentional and useful. (See the second
64357 * example above.)
64358 *
64359 * @method norm
64360 * @param  {Number} value incoming value to be normalized
64361 * @param  {Number} start lower bound of the value's current range
64362 * @param  {Number} stop  upper bound of the value's current range
64363 * @return {Number}       normalized number
64364 * @example
64365 * <div><code>
64366 * function draw() {
64367 *   background(200);
64368 *   var currentNum = mouseX;
64369 *   var lowerBound = 0;
64370 *   var upperBound = width; //100;
64371 *   var normalized = norm(currentNum, lowerBound, upperBound);
64372 *   var lineY = 70;
64373 *   line(0, lineY, width, lineY);
64374 *   //Draw an ellipse mapped to the non-normalized value.
64375 *   noStroke();
64376 *   fill(50);
64377 *   var s = 7; // ellipse size
64378 *   ellipse(currentNum, lineY, s, s);
64379 *
64380 *   // Draw the guide
64381 *   var guideY = lineY + 15;
64382 *   text('0', 0, guideY);
64383 *   textAlign(RIGHT);
64384 *   text('100', width, guideY);
64385 *
64386 *   // Draw the normalized value
64387 *   textAlign(LEFT);
64388 *   fill(0);
64389 *   textSize(32);
64390 *   var normalY = 40;
64391 *   var normalX = 20;
64392 *   text(normalized, normalX, normalY);
64393 * }
64394 * </code></div>
64395 *
64396 * @alt
64397 * ellipse moves with mouse. 0 shown left & 100 right and updating values center
64398 *
64399 */
64400p5.prototype.norm = function(n, start, stop) {
64401  p5._validateParameters('norm', arguments);
64402  return this.map(n, start, stop, 0, 1);
64403};
64404
64405/**
64406 * Facilitates exponential expressions. The pow() function is an efficie
64406nt
64407 * way of multiplying numbers by themselves (or their reciprocals) in large
64408 * quantities. For example, pow(3, 5) is equivalent to the expression
64409 * 3*3*3*3*3 and pow(3, -5) is equivalent to 1 / 3*3*3*3*3. Maps to
64410 * Math.pow().
64411 *
64412 * @method pow
64413 * @param  {Number} n base of the exponential expression
64414 * @param  {Number} e power by which to raise the base
64415 * @return {Number}   n^e
64416 * @example
64417 * <div><code>
64418 * function setup() {
64419 *   //Exponentially increase the size of an ellipse.
64420 *   var eSize = 3; // Original Size
64421 *   var eLoc = 10; // Original Location
64422 *
64423 *   ellipse(eLoc, eLoc, eSize, eSize);
64424 *
64425 *   ellipse(eLoc * 2, eLoc * 2, pow(eSize, 2), pow(eSize, 2));
64426 *
64427 *   ellipse(eLoc * 4, eLoc * 4, pow(eSize, 3), pow(eSize, 3));
64428 *
64429 *   ellipse(eLoc * 8, eLoc * 8, pow(eSize, 4), pow(eSize, 4));
64430 * }
64431 * </code></div>
64432 *
64433 * @alt
64434 * small to large ellipses radiating from top left of canvas
64435 *
64436 */
64437p5.prototype.pow = Math.pow;
64438
64439/**
64440 * Calculates the integer closest to the n parameter. For example,
64441 * round(133.8) returns the value 134. Maps to Math.round().
64442 *
64443 * @method round
64444 * @param  {Number} n number to round
64445 * @return {Integer}  rounded number
64446 * @example
64447 * <div><code>
64448 * function draw() {
64449 *   background(200);
64450 *   //map, mouseX between 0 and 5.
64451 *   var ax = map(mouseX, 0, 100, 0, 5);
64452 *   var ay = 66;
64453 *
64454 *   // Round the mapped number.
64455 *   var bx = round(map(mouseX, 0, 100, 0, 5));
64456 *   var by = 33;
64457 *
64458 *   // Multiply the mapped numbers by 20 to more easily
64459 *   // see the changes.
64460 *   stroke(0);
64461 *   fill(0);
64462 *   line(0, ay, ax * 20, ay);
64463 *   line(0, by, bx * 20, by);
64464 *
64465 *   // Reformat the float returned by map and draw it.
64466 *   noStroke();
64467 *   text(nfc(ax, 2), ax, ay - 5);
64468 *   text(nfc(bx, 1), bx, by - 5);
64469 * }
64470 * </code></div>
64471 *
64472 * @alt
64473 * horizontal center line squared values displayed on top and regular on bottom.
64474 *
64475 */
64476p5.prototype.round = Math.round;
64477
64478/**
64479 * Squares a number (multiplies a number by itself). The result is always a
64480 * positive number, as multiplying two negative numbers always yields a
64481 * positive result. For example, -1 * -1 = 1.
64482 *
64483 * @method sq
64484 * @param  {Number} n number to square
64485 * @return {Number}   squared number
64486 * @example
64487 * <div><code>
64488 * function draw() {
64489 *   background(200);
64490 *   var eSize = 7;
64491 *   var x1 = map(mouseX, 0, width, 0, 10);
64492 *   var y1 = 80;
64493 *   var x2 = sq(x1);
64494 *   var y2 = 20;
64495 *
64496 *   // Draw the non-squared.
64497 *   line(0, y1, width, y1);
64498 *   ellipse(x1, y1, eSize, eSize);
64499 *
64500 *   // Draw the squared.
64501 *   line(0, y2, width, y2);
64502 *   ellipse(x2, y2, eSize, eSize);
64503 *
64504 *   // Draw dividing line.
64505 *   stroke(100);
64506 *   line(0, height / 2, width, height / 2);
64507 *
64508 *   // Draw text.
64509 *   var spacing = 15;
64510 *   noStroke();
64511 *   fill(0);
64512 *   text('x = ' + x1, 0, y1 + spacing);
64513 *   text('sq(x) = ' + x2, 0, y2 + spacing);
64514 * }
64515 * </code></div>
64516 *
64517 * @alt
64518 * horizontal center line squared values displayed on top and regular on bottom.
64519 *
64520 */
64521p5.prototype.sq = function(n) {
64522  return n * n;
64523};
64524
64525/**
64526 * Calculates the square root of a number. The square root of a number is
64527 * always positive, even though there may be a valid negative root. The
64528 * square root s of number a is such that s*s = a. It is the opposite of
64529 * squaring. Maps to Math.sqrt().
64530 *
64531 * @method sqrt
64532 * @param  {Number} n non-negative number to square root
64533 * @return {Number}   square root of number
64534 * @example
64535 * <div><code>
64536 * function draw() {
64537 *   background(200);
64538 *   var eSize = 7;
64539 *   var x1 = mouseX;
64540 *   var y1 = 80;
64541 *   var x2 = sqrt(x1);
64542 *   var y2 = 20;
64543 *
64544 *   // Draw the non-squared.
64545 *   line(0, y1, width, y1);
64546 *   ellipse(x1, y1, eSize, eSize);
64547 *
64548 *   // Draw the squared.
64549 *   line(0, y2, width, y2);
64550 *   ellipse(x2, y2, eSize, eSize);
64551 *
64552 *   // Draw dividing line.
64553 *   stroke(100);
64554 *   line(0, height / 2, width, height / 2);
64555 *
64556 *   // Draw text.
64557 *   noStroke();
64558 *   fill(0);
64559 *   var spacing = 15;
64560 *   text('x = ' + x1, 0, y1 + spacing);
64561 *   text('sqrt(x) = ' + x2, 0, y2 + spacing);
64562 * }
64563 * </code></div>
64564 *
64565 * @alt
64566 * horizontal center line squareroot values displayed on top and regular on bottom.
64567 *
64568 */
64569p5.prototype.sqrt = Math.sqrt;
64570
64571// Calculate the length of the hypotenuse of a right triangle
64572// This won't under- or overflow in intermediate steps
64573// https://en.wikipedia.org/wiki/Hypot
64574function hypot(x, y, z) {
64575  // Use the native implementation if it's available
64576  if (typeof Math.hypot === 'function') {
64577    return Math.hypot.apply(null, arguments);
64578  }
64579
64580  // Otherwise use the V8 implementation
64581  // https://github.com/v8/v8/blob/8cd3cf297287e581a49e487067f5cbd991b27123/src/js/math.js#L217
64582  var length = arguments.length;
64583  var args = [];
64584  var max = 0;
64585  for (var i = 0; i < length; i++) {
64586    var n = arguments[i];
64587    n = +n;
64588    if (n === Infinity || n === -Infinity) {
64589      return Infinity;
64590    }
64591    n = Math.abs(n);
64592    if (n > max) {
64593      max = n;
64594    }
64595    args[i] = n;
64596  }
64597
64598  if (max === 0) {
64599    max = 1;
64600  }
64601  var sum = 0;
64602  var compensation = 0;
64603  for (var j = 0; j < length; j++) {
64604    var m = args[j] / max;
64605    var summand = m * m - compensation;
64606    var preliminary = sum + summand;
64607    compensation = preliminary - sum - summand;
64608    sum = preliminary;
64609  }
64610  return Math.sqrt(sum) * max;
64611}
64612
64613module.exports = p5;
64614
64615},{"../core/core":22}],51:[function(_dereq_,module,exports){
64616/**
64617 * @module Math
64618 * @submodule Math
64619 * @for p5
64620 * @requires core
64621 */
64622
64623'use strict';
64624
64625var p5 = _dereq_('../core/core');
64626
64627/**
64628 * Creates a new p5.Vector (the datatype for storing vectors). This provides a
64629 * two or three dimensional vector, specifically a Euclidean (also known as
64630 * geometric) vector. A vector is an entity that has both magnitude and
64631 * direction.
64632 *
64633 * @method createVector
64634 * @param {Number} [x] x component of the vector
64635 * @param {Number} [y] y component of the vector
64636 * @param {Number} [z] z component of the vector
64637 * @return {p5.Vector}
64638 * @example
64639 * <div modernizr='webgl'><code>
64640 * function setup() {
64641 *   createCanvas(100, 100, WEBGL);
64642 *   noStroke();
64643 *   fill(255, 102, 204);
64644 * }
64645 *
64646 * function draw() {
64647 *   background(255);
64648 *   pointLight(color(255), createVector(sin(millis() / 1000) * 20, -40, -10));
64649 *   scale(0.75);
64650 *   sphere();
64651 * }
64652 * </code></div>
64653 *
64654 * @alt
64655 * a purple sphere lit by a point light oscillating horizontally
64656 */
64657p5.prototype.createVector = function(x, y, z) {
64658  if (this instanceof p5) {
64659    return new p5.Vector(this, arguments);
64660  } else {
64661    return new p5.Vector(x, y, z);
64662  }
64663};
64664
64665module.exports = p5;
64666
64667},{"../core/core":22}],52:[function(_dereq_,module,exports){
64668//////////////////////////////////////////////////////////////
64669
64670// http://mrl.nyu.edu/~perlin/noise/
64671// Adapting from PApplet.java
64672// which was adapted from toxi
64673// which was adapted from the german demo group farbrausch
64674// as used in their demo "art": http://www.farb-rausch.de/fr010src.zip
64675
64676// someday we might consider using "improved noise"
64677// http://mrl.nyu.edu/~perlin/paper445.pdf
64678// See: https://github.com/shiffman/The-Nature-of-Code-Examples-p5.js/
64679//      blob/master/introduction/Noise1D/noise.js
64680
64681/**
64682 * @module Math
64683 * @submodule Noise
64684 * @for p5
64685 * @requires core
64686 */
64687
64688'use strict';
64689
64690var p5 = _dereq_('../core/core');
64691
64692var PERLIN_YWRAPB = 4;
64693var PERLIN_YWRAP = 1 << PERLIN_YWRAPB;
64694var PERLIN_ZWRAPB = 8;
64695var PERLIN_ZWRAP = 1 << PERLIN_ZWRAPB;
64696var PERLIN_SIZE = 4095;
64697
64698var perlin_octaves = 4; // default to medium smooth
64699var perlin_amp_falloff = 0.5; // 50% reduction/octave
64700
64701var scaled_cosine = function(i) {
64702  return 0.5 * (1.0 - Math.cos(i * Math.PI));
64703};
64704
64705var perlin; // will be initialized lazily by noise() or noiseSeed()
64706
64707/**
64708 * Returns the Perlin noise value at specified coordinates. Perlin noise is
64709 * a random sequence generator producing a more natural ordered, harmonic
64710 * succession of numbers compared to the standard <b>random()</b> function.
64711 * It was invented by Ken Perlin in the 1980s and been used since in
64712 * graphical applications to produce procedural textures, natural motion,
64713 * shapes, terrains etc.<br /><br /> The main difference to the
64714 * <b>random()</b> function is that Perlin noise is defined in an infinite
64715 * n-dimensional space where each pair of coordinates corresponds to a
64716 * fixed semi-random value (fixed only for the lifespan of the program; see
64717 * the noiseSeed() function). p5.js can compute 1D, 2D and 3D noise,
64718 * depending on the number of coordinates given. The resulting value will
64719 * always be between 0.0 and 1.0. The noise value can be animated by moving
64720 * through the noise space as demonstrated in the example above. The 2nd
64721 * and 3rd dimension can also be interpreted as time.<br /><br />The actual
64722 * noise is structured similar to an audio signal, in respect to the
64723 * function's use of frequencies. Similar to the concept of harmonics in
64724 * physics, perlin noise is computed over several octaves which are added
64725 * together for the final result. <br /><br />Another way to adjust the
64726 * character of the resulting sequence is the scale of the input
64727 * coordinates. As the function works within an infinite space the value of
64728 * the coordinates doesn't matter as such, only the distance between
64729 * successive coordinates does (eg. when using <b>noise()</b> within a
64730 * loop). As a general rule the smaller the difference between coordinates,
64731 * the smoother the resulting noise sequence will be. Steps of 0.005-0.03
64732 * work best for most applications, but this will differ depending on use.
64733 *
64734 *
64735 * @method noise
64736 * @param  {Number} x   x-coordinate in noise space
64737 * @param  {Number} [y] y-coordinate in noise space
64738 * @param  {Number} [z] z-coordinate in noise space
64739 * @return {Number}     Perlin noise value (between 0 and 1) at specified
64740 *                      coordinates
64741 * @example
64742 * <div>
64743 * <code>
64744 * var xoff = 0.0;
64745 *
64746 * function draw() {
64747 *   background(204);
64748 *   xoff = xoff + 0.01;
64749 *   var n = noise(xoff) * width;
64750 *   line(n, 0, n, height);
64751 * }
64752 * </code>
64753 * </div>
64754 * <div>
64755 * <code>var noiseScale=0.02;
64756 *
64757 * function draw() {
64758 *   background(0);
64759 *   for (var x=0; x < width; x++) {
64760 *     var noiseVal = noise((mouseX+x)*noiseScale, mouseY*noiseScale);
64761 *     stroke(noiseVal*255);
64762 *     line(x, mouseY+noiseVal*80, x, height);
64763 *   }
64764 * }
64765 * </code>
64766 * </div>
64767 *
64768 * @alt
64769 * vertical line moves left to right with updating noise values.
64770 * horizontal wave pattern effected by mouse x-position & updating noise values.
64771 *
64772 */
64773
64774p5.prototype.noise = function(x, y, z) {
64775  y = y || 0;
64776  z = z || 0;
64777
64778  if (perlin == null) {
64779    perlin = new Array(PERLIN_SIZE + 1);
64780    for (var i = 0; i < PERLIN_SIZE + 1; i++) {
64781      perlin[i] = Math.random();
64782    }
64783  }
64784
64785  if (x < 0) {
64786    x = -x;
64787  }
64788  if (y < 0) {
64789    y = -y;
64790  }
64791  if (z < 0) {
64792    z = -z;
64793  }
64794
64795  var xi = Math.floor(x),
64796    yi = Math.floor(y),
64797    zi = Math.floor(z);
64798  var xf = x - xi;
64799  var yf = y - yi;
64800  var zf = z - zi;
64801  var rxf, ryf;
64802
64803  var r = 0;
64804  var ampl = 0.5;
64805
64806  var n1, n2, n3;
64807
64808  for (var o = 0; o < perlin_octaves; o++) {
64809    var of = xi + (yi << PERLIN_YWRAPB) + (zi << PERLIN_ZWRAPB);
64810
64811    rxf = scaled_cosine(xf);
64812    ryf = scaled_cosine(yf);
64813
64814    n1 = perlin[of & PERLIN_SIZE];
64815    n1 += rxf * (perlin[(of + 1) & PERLIN_SIZE] - n1);
64816    n2 = perlin[(of + PERLIN_YWRAP) & PERLIN_SIZE];
64817    n2 += rxf * (perlin[(of + PERLIN_YWRAP + 1) & PERLIN_SIZE] - n2);
64818    n1 += ryf * (n2 - n1);
64819
64820    of += PERLIN_ZWRAP;
64821    n2 = perlin[of & PERLIN_SIZE];
64822    n2 += rxf * (perlin[(of + 1) & PERLIN_SIZE] - n2);
64823    n3 = perlin[(of + PERLIN_YWRAP) & PERLIN_SIZE];
64824    n3 += rxf * (perlin[(of + PERLIN_YWRAP + 1) & PERLIN_SIZE] - n3);
64825    n2 += ryf * (n3 - n2);
64826
64827    n1 += scaled_cosine(zf) * (n2 - n1);
64828
64829    r += n1 * ampl;
64830    ampl *= perlin_amp_falloff;
64831    xi <<= 1;
64832    xf *= 2;
64833    yi <<= 1;
64834    yf *= 2;
64835    zi <<= 1;
64836    zf *= 2;
64837
64838    if (xf >= 1.0) {
64839      xi++;
64840      xf--;
64841    }
64842    if (yf >= 1.0) {
64843      yi++;
64844      yf--;
64845    }
64846    if (zf >= 1.0) {
64847      zi++;
64848      zf--;
64849    }
64850  }
64851  return r;
64852};
64853
64854/**
64855 *
64856 * Adjusts the character and level of detail produced by the Perlin noise
64857 * function. Similar to harmonics in physics, noise is computed over
64858 * several octaves. Lower octaves contribute more to the output signal and
64859 * as such define the overall intensity of the noise, whereas higher octaves
64860 * create finer grained details in the noise sequence.
64861 * <br><br>
64862 * By default, noise is computed over 4 octaves with each octave contributing
64863 * exactly half than its predecessor, starting at 50% strength for the 1st
64864 * octave. This falloff amount can be changed by adding an additional function
64865 * parameter. Eg. a falloff factor of 0.75 means each octave will now have
64866 * 75% impact (25% less) of the previous lower octave. Any value between
64867 * 0.0 and 1.0 is valid, however note that values greater than 0.5 might
64868 * result in greater than 1.0 values returned by <b>noise()</b>.
64869 * <br><br>
64870 * By changing these parameters, the signal created by the <b>noise()</b>
64871 * function can be adapted to fit very specific needs and characteristics.
64872 *
64873 * @method noiseDetail
64874 * @param {Number} lod number of octaves to be used by the noise
64875 * @param {Number} falloff falloff factor for each octave
64876 * @example
64877 * <div>
64878 * <code>
64879 * var noiseVal;
64880 * var noiseScale = 0.02;
64881 *
64882 * function setup() {
64883 *   createCanvas(100, 100);
64884 * }
64885 *
64886 * function draw() {
64887 *   background(0);
64888 *   for (var y = 0; y < height; y++) {
64889 *     for (var x = 0; x < width / 2; x++) {
64890 *       noiseDetail(2, 0.2);
64891 *       noiseVal = noise((mouseX + x) * noiseScale, (mouseY + y) * noiseScale);
64892 *       stroke(noiseVal * 255);
64893 *       point(x, y);
64894 *       noiseDetail(8, 0.65);
64895 *       noiseVal = noise(
64896 *         (mouseX + x + width / 2) * noiseScale,
64897 *         (mouseY + y) * noiseScale
64898 *       );
64899 *       stroke(noiseVal * 255);
64900 *       point(x + width / 2, y);
64901 *     }
64902 *   }
64903 * }
64904 * </code>
64905 * </div>
64906 *
64907 * @alt
64908 * 2 vertical grey smokey patterns affected my mouse x-position and noise.
64909 *
64910 */
64911p5.prototype.noiseDetail = function(lod, falloff) {
64912  if (lod > 0) {
64913    perlin_octaves = lod;
64914  }
64915  if (falloff > 0) {
64916    perlin_amp_falloff = falloff;
64917  }
64918};
64919
64920/**
64921 * Sets the seed value for <b>noise()</b>. By default, <b>noise()</b>
64922 * produces different results each time the program is run. Set the
64923 * <b>value</b> parameter to a constant to return the same pseudo-random
64924 * numbers each time the software is run.
64925 *
64926 * @method noiseSeed
64927 * @param {Number} seed   the seed value
64928 * @example
64929 * <div>
64930 * <code>var xoff = 0.0;
64931 *
64932 * function setup() {
64933 *   noiseSeed(99);
64934 *   stroke(0, 10);
64935 * }
64936 *
64937 * function draw() {
64938 *   xoff = xoff + .01;
64939 *   var n = noise(xoff) * width;
64940 *   line(n, 0, n, height);
64941 * }
64942 * </code>
64943 * </div>
64944 *
64945 * @alt
64946 * vertical grey lines drawing in pattern affected by noise.
64947 *
64948 */
64949p5.prototype.noiseSeed = function(seed) {
64950  // Linear Congruential Generator
64951  // Variant of a Lehman Generator
64952  var lcg = (function() {
64953    // Set to values from http://en.wikipedia.org/wiki/Numerical_Recipes
64954    // m is basically chosen to be large (as it is the max period)
64955    // and for its relationships to a and c
64956    var m = 4294967296;
64957    // a - 1 should be divisible by m's prime factors
64958    var a = 1664525;
64959    // c and m should be co-prime
64960    var c = 1013904223;
64961    var seed, z;
64962    return {
64963      setSeed: function(val) {
64964        // pick a random seed if val is undefined or null
64965        // the >>> 0 casts the seed to an unsigned 32-bit integer
64966        z = seed = (val == null ? Math.random() * m : val) >>> 0;
64967      },
64968      getSeed: function() {
64969        return seed;
64970      },
64971      rand: function() {
64972        // define the recurrence relationship
64973        z = (a * z + c) % m;
64974        // return a float in [0, 1)
64975        // if z = m then z / m = 0 therefore (z % m) / m < 1 always
64976        return z / m;
64977      }
64978    };
64979  })();
64980
64981  lcg.setSeed(seed);
64982  perlin = new Array(PERLIN_SIZE + 1);
64983  for (var i = 0; i < PERLIN_SIZE + 1; i++) {
64984    perlin[i] = lcg.rand();
64985  }
64986};
64987
64988module.exports = p5;
64989
64990},{"../core/core":22}],53:[function(_dereq_,module,exports){
64991/**
64992 * @module Math
64993 * @submodule Math
64994 * @requires constants
64995 */
64996
64997'use strict';
64998
64999var p5 = _dereq_('../core/core');
65000var constants = _dereq_('../core/constants');
65001
65002/**
65003 * A class to describe a two or three dimensional vector, specifically
65004 * a Euclidean (also known as geometric) vector. A vector is an entity
65005 * that has both magnitude and direction. The datatype, however, stores
65006 * the components of the vector (x, y for 2D, and x, y, z for 3D). The magnitude
65007 * and direction can be accessed via the methods mag() and heading().
65008 * <br><br>
65009 * In many of the p5.js examples, you will see p5.Vector used to describe a
65010 * position, velocity, or acceleration. For example, if you consider a rectangle
65011 * moving across the screen, at any given instant it has a position (a vector
65012 * that points from the origin to its location), a velocity (the rate at which
65013 * the object's position changes per time unit, expressed as a vector), and
65014 * acceleration (the rate at which the object's velocity changes per time
65015 * unit, expressed as a vector).
65016 * <br><br>
65017 * Since vectors represent groupings of values, we cannot simply use
65018 * traditional addition/multiplication/etc. Instead, we'll need to do some
65019 * "vector" math, which is made easy by the methods inside the p5.Vector class.
65020 *
65021 * @class p5.Vector
65022 * @param {Number} [x] x component of the vector
65023 * @param {Number} [y] y component of the vector
65024 * @param {Number} [z] z component of the vector
65025 * @example
65026 * <div>
65027 * <code>
65028 * var v1 = createVector(40, 50);
65029 * var v2 = createVector(40, 50);
65030 *
65031 * ellipse(v1.x, v1.y, 50, 50);
65032 * ellipse(v2.x, v2.y, 50, 50);
65033 * v1.add(v2);
65034 * ellipse(v1.x, v1.y, 50, 50);
65035 * </code>
65036 * </div>
65037 *
65038 * @alt
65039 * 2 white ellipses. One center-left the other bottom right and off canvas
65040 *
65041 */
65042p5.Vector = function Vector() {
65043  var x, y, z;
65044  // This is how it comes in with createVector()
65045  if (arguments[0] instanceof p5) {
65046    // save reference to p5 if passed in
65047    this.p5 = arguments[0];
65048    x = arguments[1][0] || 0;
65049    y = arguments[1][1] || 0;
65050    z = arguments[1][2] || 0;
65051    // This is what we'll get with new p5.Vector()
65052  } else {
65053    x = arguments[0] || 0;
65054    y = arguments[1] || 0;
65055    z = arguments[2] || 0;
65056  }
65057  /**
65058   * The x component of the vector
65059   * @property x {Number}
65060   */
65061  this.x = x;
65062  /**
65063   * The y component of the vector
65064   * @property y {Number}
65065   */
65066  this.y = y;
65067  /**
65068   * The z component of the vector
65069   * @property z {Number}
65070   */
65071  this.z = z;
65072};
65073
65074/**
65075 * Returns a string representation of a vector v by calling String(v)
65076 * or v.toString(). This method is useful for logging vectors in the
65077 * console.
65078 * @method  toString
65079 * @return {String}
65080 * @example
65081 * <div class = "norender">
65082 * <code>
65083 * function setup() {
65084 *   var v = createVector(20, 30);
65085 *   print(String(v)); // prints "p5.Vector Object : [20, 30, 0]"
65086 * }
65087 * </code>
65088 * </div>
65089 *
65090 * <div>
65091 * <code>
65092 * function draw() {
65093 *   background(240);
65094 *
65095 *   var v0 = createVector(0, 0);
65096 *   var v1 = createVector(mouseX, mouseY);
65097 *   drawArrow(v0, v1, 'black');
65098 *
65099 *   noStroke();
65100 *   text(v1.toString(), 10, 25, 90, 75);
65101 * }
65102 *
65103 * // draw an arrow for a vector at a given base position
65104 * function drawArrow(base, vec, myColor) {
65105 *   push();
65106 *   stroke(myColor);
65107 *   strokeWeight(3);
65108 *   fill(myColor);
65109 *   translate(base.x, base.y);
65110 *   line(0, 0, vec.x, vec.y);
65111 *   rotate(vec.heading());
65112 *   var arrowSize = 7;
65113 *   translate(vec.mag() - arrowSize, 0);
65114 *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
65115 *   pop();
65116 * }
65117 * </code>
65118 * </div>
65119 */
65120p5.Vector.prototype.toString = function p5VectorToString() {
65121  return 'p5.Vector Object : [' + this.x + ', ' + this.y + ', ' + this.z + ']';
65122};
65123
65124/**
65125 * Sets the x, y, and z component of the vector using two or three separate
65126 * variables, the data from a p5.Vector, or the values from a float array.
65127 * @method set
65128 * @param {Number} [x] the x component of the vector
65129 * @param {Number} [y] the y component of the vector
65130 * @param {Number} [z] the z component of the vector
65131 * @chainable
65132 * @example
65133 * <div class="norender">
65134 * <code>
65135 * function setup() {
65136 *   var v = createVector(1, 2, 3);
65137 *   v.set(4, 5, 6); // Sets vector to [4, 5, 6]
65138 *
65139 *   var v1 = createVector(0, 0, 0);
65140 *   var arr = [1, 2, 3];
65141 *   v1.set(arr); // Sets vector to [1, 2, 3]
65142 * }
65143 * </code>
65144 * </div>
65145 *
65146 * <div>
65147 * <code>
65148 * var v0, v1;
65149 * function setup() {
65150 *   createCanvas(100, 100);
65151 *
65152 *   v0 = createVector(0, 0);
65153 *   v1 = createVector(50, 50);
65154 * }
65155 *
65156 * function draw() {
65157 *   background(240);
65158 *
65159 *   drawArrow(v0, v1, 'black');
65160 *   v1.set(v1.x + random(-1, 1), v1.y + random(-1, 1));
65161 *
65162 *   noStroke();
65163 *   text('x: ' + round(v1.x) + ' y: ' + round(v1.y), 20, 90);
65164 * }
65165 *
65166 * // draw an arrow for a vector at a given base position
65167 * function drawArrow(base, vec, myColor) {
65168 *   push();
65169 *   stroke(myColor);
65170 *   strokeWeight(3);
65171 *   fill(myColor);
65172 *   translate(base.x, base.y);
65173 *   line(0, 0, vec.x, vec.y);
65174 *   rotate(vec.heading());
65175 *   var arrowSize = 7;
65176 *   translate(vec.mag() - arrowSize, 0);
65177 *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
65178 *   pop();
65179 * }
65180 * </code>
65181 * </div>
65182 */
65183/**
65184 * @method set
65185 * @param {p5.Vector|Number[]} value the vector to set
65186 * @chainable
65187 */
65188p5.Vector.prototype.set = function set(x, y, z) {
65189  if (x instanceof p5.Vector) {
65190    this.x = x.x || 0;
65191    this.y = x.y || 0;
65192    this.z = x.z || 0;
65193    return this;
65194  }
65195  if (x instanceof Array) {
65196    this.x = x[0] || 0;
65197    this.y = x[1] || 0;
65198    this.z = x[2] || 0;
65199    return this;
65200  }
65201  this.x = x || 0;
65202  this.y = y || 0;
65203  this.z = z || 0;
65204  return this;
65205};
65206
65207/**
65208 * Gets a copy of the vector, returns a p5.Vector object.
65209 *
65210 * @method copy
65211 * @return {p5.Vector} the copy of the p5.Vector object
65212 * @example
65213 * <div class="norender">
65214 * <code>
65215 * var v1 = createVector(1, 2, 3);
65216 * var v2 = v1.copy();
65217 * print(v1.x === v2.x && v1.y === v2.y && v1.z === v2.z);
65218 * // Prints "true"
65219 * </code>
65220 * </div>
65221 */
65222p5.Vector.prototype.copy = function copy() {
65223  if (this.p5) {
65224    return new p5.Vector(this.p5, [this.x, this.y, this.z]);
65225  } else {
65226    return new p5.Vector(this.x, this.y, this.z);
65227  }
65228};
65229
65230/**
65231 * Adds x, y, and z components to a vector, adds one vector to another, or
65232 * adds two independent vectors together. The version of the method that adds
65233 * two vectors together is a static method and returns a p5.Vector, the others
65234 * acts directly on the vector. See the examples for more context.
65235 *
65236 * @method add
65237 * @param  {Number} x   the x component of the vector to be added
65238 * @param  {Number} [y] the y component of the vector to be added
65239 * @param  {Number} [z] the z component of the vector to be added
65240 * @chainable
65241 * @example
65242 * <div class="norender">
65243 * <code>
65244 * var v = createVector(1, 2, 3);
65245 * v.add(4, 5, 6);
65246 * // v's components are set to [5, 7, 9]
65247 * </code>
65248 * </div>
65249 *
65250 * <div class="norender">
65251 * <code>
65252 * // Static method
65253 * var v1 = createVector(1, 2, 3);
65254 * var v2 = createVector(2, 3, 4);
65255 *
65256 * var v3 = p5.Vector.add(v1, v2);
65257 * // v3 has components [3, 5, 7]
65258 * print(v3);
65259 * </code>
65260 * </div>
65261 *
65262 * <div>
65263 * <code>
65264 * // red vector + blue vector = purple vector
65265 * function draw() {
65266 *   background(240);
65267 *
65268 *   var v0 = createVector(0, 0);
65269 *   var v1 = createVector(mouseX, mouseY);
65270 *   drawArrow(v0, v1, 'red');
65271 *
65272 *   var v2 = createVector(-30, 20);
65273 *   drawArrow(v1, v2, 'blue');
65274 *
65275 *   var v3 = p5.Vector.add(v1, v2);
65276 *   drawArrow(v0, v3, 'purple');
65277 * }
65278 *
65279 * // draw an arrow for a vector at a given base position
65280 * function drawArrow(base, vec, myColor) {
65281 *   push();
65282 *   stroke(myColor);
65283 *   strokeWeight(3);
65284 *   fill(myColor);
65285 *   translate(base.x, base.y);
65286 *   line(0, 0, vec.x, vec.y);
65287 *   rotate(vec.heading());
65288 *   var arrowSize = 7;
65289 *   translate(vec.mag() - arrowSize, 0);
65290 *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
65291 *   pop();
65292 * }
65293 * </code>
65294 * </div>
65295 */
65296/**
65297 * @method add
65298 * @param  {p5.Vector|Number[]} value the vector to add
65299 * @chainable
65300 */
65301p5.Vector.prototype.add = function add(x, y, z) {
65302  if (x instanceof p5.Vector) {
65303    this.x += x.x || 0;
65304    this.y += x.y || 0;
65305    this.z += x.z || 0;
65306    return this;
65307  }
65308  if (x instanceof Array) {
65309    this.x += x[0] || 0;
65310    this.y += x[1] || 0;
65311    this.z += x[2] || 0;
65312    return this;
65313  }
65314  this.x += x || 0;
65315  this.y += y || 0;
65316  this.z += z || 0;
65317  return this;
65318};
65319
65320/**
65321 * Subtracts x, y, and z components from a vector, subtracts one vector from
65322 * another, or subtracts two independent vectors. The version of the method
65323 * that subtracts two vectors is a static method and returns a p5.Vector, the
65324 * other acts directly on the vector. See the examples for more context.
65325 *
65326 * @method sub
65327 * @param  {Number} x   the x component of the vector to subtract
65328 * @param  {Number} [y] the y component of the vector to subtract
65329 * @param  {Number} [z] the z component of the vector to subtract
65330 * @chainable
65331 * @example
65332 * <div class="norender">
65333 * <code>
65334 * var v = createVector(4, 5, 6);
65335 * v.sub(1, 1, 1);
65336 * // v's components are set to [3, 4, 5]
65337 * </code>
65338 * </div>
65339 *
65340 * <div class="norender">
65341 * <code>
65342 * // Static method
65343 * var v1 = createVector(2, 3, 4);
65344 * var v2 = createVector(1, 2, 3);
65345 *
65346 * var v3 = p5.Vector.sub(v1, v2);
65347 * // v3 has components [1, 1, 1]
65348 * print(v3);
65349 * </code>
65350 * </div>
65351 *
65352 * <div>
65353 * <code>
65354 * // red vector - blue vector = purple vector
65355 * function draw() {
65356 *   background(240);
65357 *
65358 *   var v0 = createVector(0, 0);
65359 *   var v1 = createVector(70, 50);
65360 *   drawArrow(v0, v1, 'red');
65361 *
65362 *   var v2 = createVector(mouseX, mouseY);
65363 *   drawArrow(v0, v2, 'blue');
65364 *
65365 *   var v3 = p5.Vector.sub(v1, v2);
65366 *   drawArrow(v2, v3, 'purple');
65367 * }
65368 *
65369 * // draw an arrow for a vector at a given base position
65370 * function drawArrow(base, vec, myColor) {
65371 *   push();
65372 *   stroke(myColor);
65373 *   strokeWeight(3);
65374 *   fill(myColor);
65375 *   translate(base.x, base.y);
65376 *   line(0, 0, vec.x, vec.y);
65377 *   rotate(vec.heading());
65378 *   var arrowSize = 7;
65379 *   translate(vec.mag() - arrowSize, 0);
65380 *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
65381 *   pop();
65382 * }
65383 * </code>
65384 * </div>
65385 */
65386/**
65387 * @method sub
65388 * @param  {p5.Vector|Number[]} value the vector to subtract
65389 * @chainable
65390 */
65391p5.Vector.prototype.sub = function sub(x, y, z) {
65392  if (x instanceof p5.Vector) {
65393    this.x -= x.x || 0;
65394    this.y -= x.y || 0;
65395    this.z -= x.z || 0;
65396    return this;
65397  }
65398  if (x instanceof Array) {
65399    this.x -= x[0] || 0;
65400    this.y -= x[1] || 0;
65401    this.z -= x[2] || 0;
65402    return this;
65403  }
65404  this.x -= x || 0;
65405  this.y -= y || 0;
65406  this.z -= z || 0;
65407  return this;
65408};
65409
65410/**
65411 * Multiply the vector by a scalar. The static version of this method
65412 * creates a new p5.Vector while the non static version acts on the vector
65413 * directly. See the examples for more context.
65414 *
65415 * @method mult
65416 * @param  {Number}    n the number to multiply with the vector
65417 * @chainable
65418 * @example
65419 * <div class="norender">
65420 * <code>
65421 * var v = createVector(1, 2, 3);
65422 * v.mult(2);
65423 * // v's components are set to [2, 4, 6]
65424 * </code>
65425 * </div>
65426 *
65427 * <div class="norender">
65428 * <code>
65429 * // Static method
65430 * var v1 = createVector(1, 2, 3);
65431 * var v2 = p5.Vector.mult(v1, 2);
65432 * // v2 has components [2, 4, 6]
65433 * print(v2);
65434 * </code>
65435 * </div>
65436 *
65437 * <div>
65438 * <code>
65439 * function draw() {
65440 *   background(240);
65441 *
65442 *   var v0 = createVector(50, 50);
65443 *   var v1 = createVector(25, -25);
65444 *   drawArrow(v0, v1, 'red');
65445 *
65446 *   var num = map(mouseX, 0, width, -2, 2, true);
65447 *   var v2 = p5.Vector.mult(v1, num);
65448 *   drawArrow(v0, v2, 'blue');
65449 *
65450 *   noStroke();
65451 *   text('multiplied by ' + num.toFixed(2), 5, 90);
65452 * }
65453 *
65454 * // draw an arrow for a vector at a given base position
65455 * function drawArrow(base, vec, myColor) {
65456 *   push();
65457 *   stroke(myColor);
65458 *   strokeWeight(3);
65459 *   fill(myColor);
65460 *   translate(base.x, base.y);
65461 *   line(0, 0, vec.x, vec.y);
65462 *   rotate(vec.heading());
65463 *   var arrowSize = 7;
65464 *   translate(vec.mag() - arrowSize, 0);
65465 *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
65466 *   pop();
65467 * }
65468 * </code>
65469 * </div>
65470 */
65471p5.Vector.prototype.mult = function mult(n) {
65472  if (!(typeof n === 'number' && isFinite(n))) {
65473    console.warn(
65474      'p5.Vector.prototype.mult:',
65475      'n is undefined or not a finite number'
65476    );
65477    return this;
65478  }
65479  this.x *= n;
65480  this.y *= n;
65481  this.z *= n;
65482  return this;
65483};
65484
65485/**
65486 * Divide the vector by a scalar. The static version of this method creates a
65487 * new p5.Vector while the non static version acts on the vector directly.
65488 * See the examples for more context.
65489 *
65490 * @method div
65491 * @param  {number}    n the number to divide the vector by
65492 * @chainable
65493 * @example
65494 * <div class="norender">
65495 * <code>
65496 * var v = createVector(6, 4, 2);
65497 * v.div(2); //v's components are set to [3, 2, 1]
65498 * </code>
65499 * </div>
65500 *
65501 * <div class="norender">
65502 * <code>
65503 * // Static method
65504 * var v1 = createVector(6, 4, 2);
65505 * var v2 = p5.Vector.div(v1, 2);
65506 * // v2 has components [3, 2, 1]
65507 * print(v2);
65508 * </code>
65509 * </div>
65510 *
65511 * <div>
65512 * <code>
65513 * function draw() {
65514 *   background(240);
65515 *
65516 *   var v0 = createVector(0, 100);
65517 *   var v1 = createVector(50, -50);
65518 *   drawArrow(v0, v1, 'red');
65519 *
65520 *   var num = map(mouseX, 0, width, 10, 0.5, true);
65521 *   var v2 = p5.Vector.div(v1, num);
65522 *   drawArrow(v0, v2, 'blue');
65523 *
65524 *   noStroke();
65525 *   text('divided by ' + num.toFixed(2), 10, 90);
65526 * }
65527 *
65528 * // draw an arrow for a vector at a given base position
65529 * function drawArrow(base, vec, myColor) {
65530 *   push();
65531 *   stroke(myColor);
65532 *   strokeWeight(3);
65533 *   fill(myColor);
65534 *   translate(base.x, base.y);
65535 *   line(0, 0, vec.x, vec.y);
65536 *   rotate(vec.heading());
65537 *   var arrowSize = 7;
65538 *   translate(vec.mag() - arrowSize, 0);
65539 *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
65540 *   pop();
65541 * }
65542 * </code>
65543 * </div>
65544 */
65545p5.Vector.prototype.div = function div(n) {
65546  if (!(typeof n === 'number' && isFinite(n))) {
65547    console.warn(
65548      'p5.Vector.prototype.div:',
65549      'n is undefined or not a finite number'
65550    );
65551    return this;
65552  }
65553  if (n === 0) {
65554    console.warn('p5.Vector.prototype.div:', 'divide by 0');
65555    return this;
65556  }
65557  this.x /= n;
65558  this.y /= n;
65559  this.z /= n;
65560  return this;
65561};
65562
65563/**
65564 * Calculates the magnitude (length) of the vector and returns the result as
65565 * a float (this is simply the equation sqrt(x*x + y*y + z*z).)
65566 *
65567 * @method mag
65568 * @return {Number} magnitude of the vector
65569 * @example
65570 * <div>
65571 * <code>
65572 * function draw() {
65573 *   background(240);
65574 *
65575 *   var v0 = createVector(0, 0);
65576 *   var v1 = createVector(mouseX, mouseY);
65577 *   drawArrow(v0, v1, 'black');
65578 *
65579 *   noStroke();
65580 *   text('vector length: ' + v1.mag().toFixed(2), 10, 70, 90, 30);
65581 * }
65582 *
65583 * // draw an arrow for a vector at a given base position
65584 * function drawArrow(base, vec, myColor) {
65585 *   push();
65586 *   stroke(myColor);
65587 *   strokeWeight(3);
65588 *   fill(myColor);
65589 *   translate(base.x, base.y);
65590 *   line(0, 0, vec.x, vec.y);
65591 *   rotate(vec.heading());
65592 *   var arrowSize = 7;
65593 *   translate(vec.mag() - arrowSize, 0);
65594 *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
65595 *   pop();
65596 * }
65597 * </code>
65598 * </div>
65599 * <div class="norender">
65600 * <code>
65601 * var v = createVector(20.0, 30.0, 40.0);
65602 * var m = v.mag();
65603 * print(m); // Prints "53.85164807134504"
65604 * </code>
65605 * </div>
65606 */
65607p5.Vector.prototype.mag = function mag() {
65608  return Math.sqrt(this.magSq());
65609};
65610
65611/**
65612 * Calculates the squared magnitude of the vector and returns the result
65613 * as a float (this is simply the equation <em>(x*x + y*y + z*z)</em>.)
65614 * Faster if the real length is not required in the
65615 * case of comparing vectors, etc.
65616 *
65617 * @method magSq
65618 * @return {number} squared magnitude of the vector
65619 * @example
65620 * <div class="norender">
65621 * <code>
65622 * // Static method
65623 * var v1 = createVector(6, 4, 2);
65624 * print(v1.magSq()); // Prints "56"
65625 * </code>
65626 * </div>
65627 *
65628 * <div>
65629 * <code>
65630 * function draw() {
65631 *   background(240);
65632 *
65633 *   var v0 = createVector(0, 0);
65634 *   var v1 = createVector(mouseX, mouseY);
65635 *   drawArrow(v0, v1, 'black');
65636 *
65637 *   noStroke();
65638 *   text('vector length squared: ' + v1.magSq().toFixed(2), 10, 45, 90, 55);
65639 * }
65640 *
65641 * // draw an arrow for a vector at a given base position
65642 * function drawArrow(base, vec, myColor) {
65643 *   push();
65644 *   stroke(myColor);
65645 *   strokeWeight(3);
65646 *   fill(myColor);
65647 *   translate(base.x, base.y);
65648 *   line(0, 0, vec.x, vec.y);
65649 *   rotate(vec.heading());
65650 *   var arrowSize = 7;
65651 *   translate(vec.mag() - arrowSize, 0);
65652 *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
65653 *   pop();
65654 * }
65655 * </code>
65656 * </div>
65657 */
65658p5.Vector.prototype.magSq = function magSq() {
65659  var x = this.x;
65660  var y = this.y;
65661  var z = this.z;
65662  return x * x + y * y + z * z;
65663};
65664
65665/**
65666 * Calculates the dot product of two vectors. The version of the method
65667 * that computes the dot product of two independent vectors is a static
65668 * method. See the examples for more context.
65669 *
65670 *
65671 * @method dot
65672 * @param  {Number} x   x component of the vector
65673 * @param  {Number} [y] y component of the vector
65674 * @param  {Number} [z] z component of the vector
65675 * @return {Number}       the dot product
65676 *
65677 * @example
65678 * <div class="norender">
65679 * <code>
65680 * var v1 = createVector(1, 2, 3);
65681 * var v2 = createVector(2, 3, 4);
65682 *
65683 * print(v1.dot(v2)); // Prints "20"
65684 * </code>
65685 * </div>
65686 *
65687 * <div class="norender">
65688 * <code>
65689 * //Static method
65690 * var v1 = createVector(1, 2, 3);
65691 * var v2 = createVector(3, 2, 1);
65692 * print(p5.Vector.dot(v1, v2)); // Prints "10"
65693 * </code>
65694 * </div>
65695 */
65696/**
65697 * @method dot
65698 * @param  {p5.Vector} value value component of the vector or a p5.Vector
65699 * @return {Number}
65700 */
65701p5.Vector.prototype.dot = function dot(x, y, z) {
65702  if (x instanceof p5.Vector) {
65703    return this.dot(x.x, x.y, x.z);
65704  }
65705  return this.x * (x || 0) + this.y * (y || 0) + this.z * (z || 0);
65706};
65707
65708/**
65709 * Calculates and returns a vector composed of the cross product between
65710 * two vectors. Both the static and non static methods return a new p5.Vector.
65711 * See the examples for more context.
65712 *
65713 * @method cross
65714 * @param  {p5.Vector} v p5.Vector to be crossed
65715 * @return {p5.Vector}   p5.Vector composed of cross product
65716 * @example
65717 * <div class="norender">
65718 * <code>
65719 * var v1 = createVector(1, 2, 3);
65720 * var v2 = createVector(1, 2, 3);
65721 *
65722 * v1.cross(v2); // v's components are [0, 0, 0]
65723 * </code>
65724 * </div>
65725 *
65726 * <div class="norender">
65727 * <code>
65728 * // Static method
65729 * var v1 = createVector(1, 0, 0);
65730 * var v2 = createVector(0, 1, 0);
65731 *
65732 * var crossProduct = p5.Vector.cross(v1, v2);
65733 * // crossProduct has components [0, 0, 1]
65734 * print(crossProduct);
65735 * </code>
65736 * </div>
65737 */
65738p5.Vector.prototype.cross = function cross(v) {
65739  var x = this.y * v.z - this.z * v.y;
65740  var y = this.z * v.x - this.x * v.z;
65741  var z = this.x * v.y - this.y * v.x;
65742  if (this.p5) {
65743    return new p5.Vector(this.p5, [x, y, z]);
65744  } else {
65745    return new p5.Vector(x, y, z);
65746  }
65747};
65748
65749/**
65750 * Calculates the Euclidean distance between two points (considering a
65751 * point as a vector object).
65752 *
65753 * @method dist
65754 * @param  {p5.Vector} v the x, y, and z coordinates of a p5.Vector
65755 * @return {Number}      the distance
65756 * @example
65757 * <div class="norender">
65758 * <code>
65759 * var v1 = createVector(1, 0, 0);
65760 * var v2 = createVector(0, 1, 0);
65761 *
65762 * var distance = v1.dist(v2); // distance is 1.4142...
65763 * print(distance);
65764 * </code>
65765 * </div>
65766 *
65767 * <div class="norender">
65768 * <code>
65769 * // Static method
65770 * var v1 = createVector(1, 0, 0);
65771 * var v2 = createVector(0, 1, 0);
65772 *
65773 * var distance = p5.Vector.dist(v1, v2);
65774 * // distance is 1.4142...
65775 * print(distance);
65776 * </code>
65777 * </div>
65778 *
65779 * <div>
65780 * <code>
65781 * function draw() {
65782 *   background(240);
65783 *
65784 *   var v0 = createVector(0, 0);
65785 *
65786 *   var v1 = createVector(70, 50);
65787 *   drawArrow(v0, v1, 'red');
65788 *
65789 *   var v2 = createVector(mouseX, mouseY);
65790 *   drawArrow(v0, v2, 'blue');
65791 *
65792 *   noStroke();
65793 *   text('distance between vectors: ' + v2.dist(v1).toFixed(2), 5, 50, 95, 50);
65794 * }
65795 *
65796 * // draw an arrow for a vector at a given base position
65797 * function drawArrow(base, vec, myColor) {
65798 *   push();
65799 *   stroke(myColor);
65800 *   strokeWeight(3);
65801 *   fill(myColor);
65802 *   translate(base.x, base.y);
65803 *   line(0, 0, vec.x, vec.y);
65804 *   rotate(vec.heading());
65805 *   var arrowSize = 7;
65806 *   translate(vec.mag() - arrowSize, 0);
65807 *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
65808 *   pop();
65809 * }
65810 * </code>
65811 * </div>
65812 */
65813p5.Vector.prototype.dist = function dist(v) {
65814  return v
65815    .copy()
65816    .sub(this)
65817    .mag();
65818};
65819
65820/**
65821 * Normalize the vector to length 1 (make it a unit vector).
65822 *
65823 * @method normalize
65824 * @return {p5.Vector} normalized p5.Vector
65825 * @example
65826 * <div class="norender">
65827 * <code>
65828 * var v = createVector(10, 20, 2);
65829 * // v has components [10.0, 20.0, 2.0]
65830 * v.normalize();
65831 * // v's components are set to
65832 * // [0.4454354, 0.8908708, 0.089087084]
65833 * </code>
65834 * </div>
65835 * <div>
65836 * <code>
65837 * function draw() {
65838 *   background(240);
65839 *
65840 *   var v0 = createVector(50, 50);
65841 *   var v1 = createVector(mouseX - 50, mouseY - 50);
65842 *
65843 *   drawArrow(v0, v1, 'red');
65844 *   v1.normalize();
65845 *   drawArrow(v0, v1.mult(35), 'blue');
65846 *
65847 *   noFill();
65848 *   ellipse(50, 50, 35 * 2);
65849 * }
65850 *
65851 * // draw an arrow for a vector at a given base position
65852 * function drawArrow(base, vec, myColor) {
65853 *   push();
65854 *   stroke(myColor);
65855 *   strokeWeight(3);
65856 *   fill(myColor);
65857 *   translate(base.x, base.y);
65858 *   line(0, 0, vec.x, vec.y);
65859 *   rotate(vec.heading());
65860 *   var arrowSize = 7;
65861 *   translate(vec.mag() - arrowSize, 0);
65862 *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
65863 *   pop();
65864 * }
65865 * </code>
65866 * </div>
65867 */
65868p5.Vector.prototype.normalize = function normalize() {
65869  var len = this.mag();
65870  // here we multiply by the reciprocal instead of calling 'div()'
65871  // since div duplicates this zero check.
65872  if (len !== 0) this.mult(1 / len);
65873  return this;
65874};
65875
65876/**
65877 * Limit the magnitude of this vector to the value used for the <b>max</b>
65878 * parameter.
65879 *
65880 * @method limit
65881 * @param  {Number}    max the maximum magnitude for the vector
65882 * @chainable
65883 * @example
65884 * <div class="norender">
65885 * <code>
65886 * var v = createVector(10, 20, 2);
65887 * // v has components [10.0, 20.0, 2.0]
65888 * v.limit(5);
65889 * // v's components are set to
65890 * // [2.2271771, 4.4543543, 0.4454354]
65891 * </code>
65892 * </div>
65893 * <div>
65894 * <code>
65895 * function draw() {
65896 *   background(240);
65897 *
65898 *   var v0 = createVector(50, 50);
65899 *   var v1 = createVector(mouseX - 50, mouseY - 50);
65900 *
65901 *   drawArrow(v0, v1, 'red');
65902 *   drawArrow(v0, v1.limit(35), 'blue');
65903 *
65904 *   noFill();
65905 *   ellipse(50, 50, 35 * 2);
65906 * }
65907 *
65908 * // draw an arrow for a vector at a given base position
65909 * function drawArrow(base, vec, myColor) {
65910 *   push();
65911 *   stroke(myColor);
65912 *   strokeWeight(3);
65913 *   fill(myColor);
65914 *   translate(base.x, base.y);
65915 *   line(0, 0, vec.x, vec.y);
65916 *   rotate(vec.heading());
65917 *   var arrowSize = 7;
65918 *   translate(vec.mag() - arrowSize, 0);
65919 *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
65920 *   pop();
65921 * }
65922 * </code>
65923 * </div>
65924 */
65925p5.Vector.prototype.limit = function limit(max) {
65926  var mSq = this.magSq();
65927  if (mSq > max * max) {
65928    this.div(Math.sqrt(mSq)) //normalize it
65929      .mult(max);
65930  }
65931  return this;
65932};
65933
65934/**
65935 * Set the magnitude of this vector to the value used for the <b>len</b>
65936 * parameter.
65937 *
65938 * @method setMag
65939 * @param  {number}    len the new length for this vector
65940 * @chainable
65941 * @example
65942 * <div class="norender">
65943 * <code>
65944 * var v = createVector(10, 20, 2);
65945 * // v has components [10.0, 20.0, 2.0]
65946 * v.setMag(10);
65947 * // v's components are set to [6.0, 8.0, 0.0]
65948 * </code>
65949 * </div>
65950 *
65951 * <div>
65952 * <code>
65953 * function draw() {
65954 *   background(240);
65955 *
65956 *   var v0 = createVector(0, 0);
65957 *   var v1 = createVector(50, 50);
65958 *
65959 *   drawArrow(v0, v1, 'red');
65960 *
65961 *   var length = map(mouseX, 0, width, 0, 141, true);
65962 *   v1.setMag(length);
65963 *   drawArrow(v0, v1, 'blue');
65964 *
65965 *   noStroke();
65966 *   text('magnitude set to: ' + length.toFixed(2), 10, 70, 90, 30);
65967 * }
65968 *
65969 * // draw an arrow for a vector at a given base position
65970 * function drawArrow(base, vec, myColor) {
65971 *   push();
65972 *   stroke(myColor);
65973 *   strokeWeight(3);
65974 *   fill(myColor);
65975 *   translate(base.x, base.y);
65976 *   line(0, 0, vec.x, vec.y);
65977 *   rotate(vec.heading());
65978 *   var arrowSize = 7;
65979 *   translate(vec.mag() - arrowSize, 0);
65980 *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
65981 *   pop();
65982 * }
65983 * </code>
65984 * </div>
65985 */
65986p5.Vector.prototype.setMag = function setMag(n) {
65987  return this.normalize().mult(n);
65988};
65989
65990/**
65991 * Calculate the angle of rotation for this vector (only 2D vectors)
65992 *
65993 * @method heading
65994 * @return {Number} the angle of rotation
65995 * @example
65996 * <div class = "norender">
65997 * <code>
65998 * function setup() {
65999 *   var v1 = createVector(30, 50);
66000 *   print(v1.heading()); // 1.0303768265243125
66001 *
66002 *   v1 = createVector(40, 50);
66003 *   print(v1.heading());
66003 // 0.8960553845713439
66004 *
66005 *   v1 = createVector(30, 70);
66006 *   print(v1.heading()); // 1.1659045405098132
66007 * }
66008 * </code>
66009 * </div>
66010 *
66011 * <div>
66012 * <code>
66013 * function draw() {
66014 *   background(240);
66015 *
66016 *   var v0 = createVector(50, 50);
66017 *   var v1 = createVector(mouseX - 50, mouseY - 50);
66018 *
66019 *   drawArrow(v0, v1, 'black');
66020 *
66021 *   var myHeading = v1.heading();
66022 *   noStroke();
66023 *   text(
66024 *     'vector heading: ' +
66025 *       myHeading.toFixed(2) +
66026 *       ' radians or ' +
66027 *       degrees(myHeading).toFixed(2) +
66028 *       ' degrees',
66029 *     10,
66030 *     50,
66031 *     90,
66032 *     50
66033 *   );
66034 * }
66035 *
66036 * // draw an arrow for a vector at a given base position
66037 * function drawArrow(base, vec, myColor) {
66038 *   push();
66039 *   stroke(myColor);
66040 *   strokeWeight(3);
66041 *   fill(myColor);
66042 *   translate(base.x, base.y);
66043 *   line(0, 0, vec.x, vec.y);
66044 *   rotate(vec.heading());
66045 *   var arrowSize = 7;
66046 *   translate(vec.mag() - arrowSize, 0);
66047 *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
66048 *   pop();
66049 * }
66050 * </code>
66051 * </div>
66052 */
66053p5.Vector.prototype.heading = function heading() {
66054  var h = Math.atan2(this.y, this.x);
66055  if (this.p5) return this.p5._fromRadians(h);
66056  return h;
66057};
66058
66059/**
66060 * Rotate the vector by an angle (only 2D vectors), magnitude remains the
66061 * same
66062 *
66063 * @method rotate
66064 * @param  {number}    angle the angle of rotation
66065 * @chainable
66066 * @example
66067 * <div class="norender">
66068 * <code>
66069 * var v = createVector(10.0, 20.0);
66070 * // v has components [10.0, 20.0, 0.0]
66071 * v.rotate(HALF_PI);
66072 * // v's components are set to [-20.0, 9.999999, 0.0]
66073 * </code>
66074 * </div>
66075 *
66076 * <div>
66077 * <code>
66078 * var angle = 0;
66079 * function draw() {
66080 *   background(240);
66081 *
66082 *   var v0 = createVector(50, 50);
66083 *   var v1 = createVector(50, 0);
66084 *
66085 *   drawArrow(v0, v1.rotate(angle), 'black');
66086 *   angle += 0.01;
66087 * }
66088 *
66089 * // draw an arrow for a vector at a given base position
66090 * function drawArrow(base, vec, myColor) {
66091 *   push();
66092 *   stroke(myColor);
66093 *   strokeWeight(3);
66094 *   fill(myColor);
66095 *   translate(base.x, base.y);
66096 *   line(0, 0, vec.x, vec.y);
66097 *   rotate(vec.heading());
66098 *   var arrowSize = 7;
66099 *   translate(vec.mag() - arrowSize, 0);
66100 *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
66101 *   pop();
66102 * }
66103 * </code>
66104 * </div>
66105 */
66106p5.Vector.prototype.rotate = function rotate(a) {
66107  var newHeading = this.heading() + a;
66108  if (this.p5) newHeading = this.p5._toRadians(newHeading);
66109  var mag = this.mag();
66110  this.x = Math.cos(newHeading) * mag;
66111  this.y = Math.sin(newHeading) * mag;
66112  return this;
66113};
66114
66115/**
66116 * Calculates and returns the angle (in radians) between two vectors.
66117 * @method angleBetween
66118 * @param  {p5.Vector}    the x, y, and z components of a p5.Vector
66119 * @return {Number}       the angle between (in radians)
66120 * @example
66121 * <div class="norender">
66122 * <code>
66123 * var v1 = createVector(1, 0, 0);
66124 * var v2 = createVector(0, 1, 0);
66125 *
66126 * var angle = v1.angleBetween(v2);
66127 * // angle is PI/2
66128 * print(angle);
66129 * </code>
66130 * </div>
66131 *
66132 * <div>
66133 * <code>
66134 * function draw() {
66135 *   background(240);
66136 *   var v0 = createVector(50, 50);
66137 *
66138 *   var v1 = createVector(50, 0);
66139 *   drawArrow(v0, v1, 'red');
66140 *
66141 *   var v2 = createVector(mouseX - 50, mouseY - 50);
66142 *   drawArrow(v0, v2, 'blue');
66143 *
66144 *   var angleBetween = v1.angleBetween(v2);
66145 *   noStroke();
66146 *   text(
66147 *     'angle between: ' +
66148 *       angleBetween.toFixed(2) +
66149 *       ' radians or ' +
66150 *       degrees(angleBetween).toFixed(2) +
66151 *       ' degrees',
66152 *     10,
66153 *     50,
66154 *     90,
66155 *     50
66156 *   );
66157 * }
66158 *
66159 * // draw an arrow for a vector at a given base position
66160 * function drawArrow(base, vec, myColor) {
66161 *   push();
66162 *   stroke(myColor);
66163 *   strokeWeight(3);
66164 *   fill(myColor);
66165 *   translate(base.x, base.y);
66166 *   line(0, 0, vec.x, vec.y);
66167 *   rotate(vec.heading());
66168 *   var arrowSize = 7;
66169 *   translate(vec.mag() - arrowSize, 0);
66170 *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
66171 *   pop();
66172 * }
66173 * </code>
66174 * </div>
66175 */
66176p5.Vector.prototype.angleBetween = function angleBetween(v) {
66177  var dotmagmag = this.dot(v) / (this.mag() * v.mag());
66178  // Mathematically speaking: the dotmagmag variable will be between -1 and 1
66179  // inclusive. Practically though it could be slightly outside this range due
66180  // to floating-point rounding issues. This can make Math.acos return NaN.
66181  //
66182  // Solution: we'll clamp the value to the -1,1 range
66183  var angle = Math.acos(Math.min(1, Math.max(-1, dotmagmag)));
66184  if (this.p5) return this.p5._fromRadians(angle);
66185  return angle;
66186};
66187
66188/**
66189 * Linear interpolate the vector to another vector
66190 *
66191 * @method lerp
66192 * @param  {Number}    x   the x component
66193 * @param  {Number}    y   the y component
66194 * @param  {Number}    z   the z component
66195 * @param  {Number}    amt the amount of interpolation; some value between 0.0
66196 *                         (old vector) and 1.0 (new vector). 0.9 is very near
66197 *                         the new vector. 0.5 is halfway in between.
66198 * @chainable
66199 *
66200 * @example
66201 * <div class="norender">
66202 * <code>
66203 * var v = createVector(1, 1, 0);
66204 *
66205 * v.lerp(3, 3, 0, 0.5); // v now has components [2,2,0]
66206 * </code>
66207 * </div>
66208 *
66209 * <div class="norender">
66210 * <code>
66211 * var v1 = createVector(0, 0, 0);
66212 * var v2 = createVector(100, 100, 0);
66213 *
66214 * var v3 = p5.Vector.lerp(v1, v2, 0.5);
66215 * // v3 has components [50,50,0]
66216 * print(v3);
66217 * </code>
66218 * </div>
66219 *
66220 * <div>
66221 * <code>
66222 * var step = 0.01;
66223 * var amount = 0;
66224 *
66225 * function draw() {
66226 *   background(240);
66227 *   var v0 = createVector(0, 0);
66228 *
66229 *   var v1 = createVector(mouseX, mouseY);
66230 *   drawArrow(v0, v1, 'red');
66231 *
66232 *   var v2 = createVector(90, 90);
66233 *   drawArrow(v0, v2, 'blue');
66234 *
66235 *   if (amount > 1 || amount < 0) {
66236 *     step *= -1;
66237 *   }
66238 *   amount += step;
66239 *   var v3 = p5.Vector.lerp(v1, v2, amount);
66240 *
66241 *   drawArrow(v0, v3, 'purple');
66242 * }
66243 *
66244 * // draw an arrow for a vector at a given base position
66245 * function drawArrow(base, vec, myColor) {
66246 *   push();
66247 *   stroke(myColor);
66248 *   strokeWeight(3);
66249 *   fill(myColor);
66250 *   translate(base.x, base.y);
66251 *   line(0, 0, vec.x, vec.y);
66252 *   rotate(vec.heading());
66253 *   var arrowSize = 7;
66254 *   translate(vec.mag() - arrowSize, 0);
66255 *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
66256 *   pop();
66257 * }
66258 * </code>
66259 * </div>
66260 */
66261/**
66262 * @method lerp
66263 * @param  {p5.Vector} v   the p5.Vector to lerp to
66264 * @param  {Number}    amt
66265 * @chainable
66266 */
66267p5.Vector.prototype.lerp = function lerp(x, y, z, amt) {
66268  if (x instanceof p5.Vector) {
66269    return this.lerp(x.x, x.y, x.z, y);
66270  }
66271  this.x += (x - this.x) * amt || 0;
66272  this.y += (y - this.y) * amt || 0;
66273  this.z += (z - this.z) * amt || 0;
66274  return this;
66275};
66276
66277/**
66278 * Return a representation of this vector as a float array. This is only
66279 * for temporary use. If used in any other fashion, the contents should be
66280 * copied by using the <b>p5.Vector.copy()</b> method to copy into your own
66281 * array.
66282 *
66283 * @method array
66284 * @return {Number[]} an Array with the 3 values
66285 * @example
66286 * <div class = "norender">
66287 * <code>
66288 * function setup() {
66289 *   var v = createVector(20, 30);
66290 *   print(v.array()); // Prints : Array [20, 30, 0]
66291 * }
66292 * </code>
66293 * </div>
66294 *
66295 * <div class="norender">
66296 * <code>
66297 * var v = createVector(10.0, 20.0, 30.0);
66298 * var f = v.array();
66299 * print(f[0]); // Prints "10.0"
66300 * print(f[1]); // Prints "20.0"
66301 * print(f[2]); // Prints "30.0"
66302 * </code>
66303 * </div>
66304 */
66305p5.Vector.prototype.array = function array() {
66306  return [this.x || 0, this.y || 0, this.z || 0];
66307};
66308
66309/**
66310 * Equality check against a p5.Vector
66311 *
66312 * @method equals
66313 * @param {Number} [x] the x component of the vector
66314 * @param {Number} [y] the y component of the vector
66315 * @param {Number} [z] the z component of the vector
66316 * @return {Boolean} whether the vectors are equals
66317 * @example
66318 * <div class = "norender">
66319 * <code>
66320 * var v1 = createVector(5, 10, 20);
66321 * var v2 = createVector(5, 10, 20);
66322 * var v3 = createVector(13, 10, 19);
66323 *
66324 * print(v1.equals(v2.x, v2.y, v2.z)); // true
66325 * print(v1.equals(v3.x, v3.y, v3.z)); // false
66326 * </code>
66327 * </div>
66328 *
66329 * <div class="norender">
66330 * <code>
66331 * var v1 = createVector(10.0, 20.0, 30.0);
66332 * var v2 = createVector(10.0, 20.0, 30.0);
66333 * var v3 = createVector(0.0, 0.0, 0.0);
66334 * print(v1.equals(v2)); // true
66335 * print(v1.equals(v3)); // false
66336 * </code>
66337 * </div>
66338 */
66339/**
66340 * @method equals
66341 * @param {p5.Vector|Array} value the vector to compare
66342 * @return {Boolean}
66343 */
66344p5.Vector.prototype.equals = function equals(x, y, z) {
66345  var a, b, c;
66346  if (x instanceof p5.Vector) {
66347    a = x.x || 0;
66348    b = x.y || 0;
66349    c = x.z || 0;
66350  } else if (x instanceof Array) {
66351    a = x[0] || 0;
66352    b = x[1] || 0;
66353    c = x[2] || 0;
66354  } else {
66355    a = x || 0;
66356    b = y || 0;
66357    c = z || 0;
66358  }
66359  return this.x === a && this.y === b && this.z === c;
66360};
66361
66362// Static Methods
66363
66364/**
66365 * Make a new 2D vector from an angle
66366 *
66367 * @method fromAngle
66368 * @static
66369 * @param {Number}     angle the desired angle, in radians
66370 * @param {Number}     [length] the length of the new vector (defaults to 1)
66371 * @return {p5.Vector}       the new p5.Vector object
66372 * @example
66373 * <div>
66374 * <code>
66375 * function draw() {
66376 *   background(200);
66377 *
66378 *   // Create a variable, proportional to the mouseX,
66379 *   // varying from 0-360, to represent an angle in degrees.
66380 *   angleMode(DEGREES);
66381 *   var myDegrees = map(mouseX, 0, width, 0, 360);
66382 *
66383 *   // Display that variable in an onscreen text.
66384 *   // (Note the nfc() function to truncate additional decimal places,
66385 *   // and the "\xB0" character for the degree symbol.)
66386 *   var readout = 'angle = ' + nfc(myDegrees, 1) + '\xB0';
66387 *   noStroke();
66388 *   fill(0);
66389 *   text(readout, 5, 15);
66390 *
66391 *   // Create a p5.Vector using the fromAngle function,
66392 *   // and extract its x and y components.
66393 *   var v = p5.Vector.fromAngle(radians(myDegrees), 30);
66394 *   var vx = v.x;
66395 *   var vy = v.y;
66396 *
66397 *   push();
66398 *   translate(width / 2, height / 2);
66399 *   noFill();
66400 *   stroke(150);
66401 *   line(0, 0, 30, 0);
66402 *   stroke(0);
66403 *   line(0, 0, vx, vy);
66404 *   pop();
66405 * }
66406 * </code>
66407 * </div>
66408 */
66409p5.Vector.fromAngle = function fromAngle(angle, length) {
66410  if (typeof length === 'undefined') {
66411    length = 1;
66412  }
66413  return new p5.Vector(length * Math.cos(angle), length * Math.sin(angle), 0);
66414};
66415
66416/**
66417 * Make a new 3D vector from a pair of ISO spherical angles
66418 *
66419 * @method fromAngles
66420 * @static
66421 * @param {Number}     theta    the polar angle, in radians (zero is up)
66422 * @param {Number}     phi      the azimuthal angle, in radians
66423 *                               (zero is out of the screen)
66424 * @param {Number}     [length] the length of the new vector (defaults to 1)
66425 * @return {p5.Vector}          the new p5.Vector object
66426 * @example
66427 * <div modernizr='webgl'>
66428 * <code>
66429 * function setup() {
66430 *   createCanvas(100, 100, WEBGL);
66431 *   fill(255);
66432 *   noStroke();
66433 * }
66434 * function draw() {
66435 *   background(255);
66436 *
66437 *   var t = millis() / 1000;
66438 *
66439 *   // add three point lights
66440 *   pointLight(color('#f00'), p5.Vector.fromAngles(t * 1.0, t * 1.3, 100));
66441 *   pointLight(color('#0f0'), p5.Vector.fromAngles(t * 1.1, t * 1.2, 100));
66442 *   pointLight(color('#00f'), p5.Vector.fromAngles(t * 1.2, t * 1.1, 100));
66443 *
66444 *   sphere(35);
66445 * }
66446 * </code>
66447 * </div>
66448 */
66449p5.Vector.fromAngles = function(theta, phi, length) {
66450  if (typeof length === 'undefined') {
66451    length = 1;
66452  }
66453  var cosPhi = Math.cos(phi);
66454  var sinPhi = Math.sin(phi);
66455  var cosTheta = Math.cos(theta);
66456  var sinTheta = Math.sin(theta);
66457
66458  return new p5.Vector(
66459    length * sinTheta * sinPhi,
66460    -length * cosTheta,
66461    length * sinTheta * cosPhi
66462  );
66463};
66464
66465/**
66466 * Make a new 2D unit vector from a random angle
66467 *
66468 * @method random2D
66469 * @static
66470 * @return {p5.Vector} the new p5.Vector object
66471 * @example
66472 * <div class="norender">
66473 * <code>
66474 * var v = p5.Vector.random2D();
66475 * // May make v's attributes something like:
66476 * // [0.61554617, -0.51195765, 0.0] or
66477 * // [-0.4695841, -0.14366731, 0.0] or
66478 * // [0.6091097, -0.22805278, 0.0]
66479 * print(v);
66480 * </code>
66481 * </div>
66482 *
66483 * <div>
66484 * <code>
66485 * function setup() {
66486 *   frameRate(1);
66487 * }
66488 *
66489 * function draw() {
66490 *   background(240);
66491 *
66492 *   var v0 = createVector(50, 50);
66493 *   var v1 = p5.Vector.random2D();
66494 *   drawArrow(v0, v1.mult(50), 'black');
66495 * }
66496 *
66497 * // draw an arrow for a vector at a given base position
66498 * function drawArrow(base, vec, myColor) {
66499 *   push();
66500 *   stroke(myColor);
66501 *   strokeWeight(3);
66502 *   fill(myColor);
66503 *   translate(base.x, base.y);
66504 *   line(0, 0, vec.x, vec.y);
66505 *   rotate(vec.heading());
66506 *   var arrowSize = 7;
66507 *   translate(vec.mag() - arrowSize, 0);
66508 *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
66509 *   pop();
66510 * }
66511 * </code>
66512 * </div>
66513 */
66514p5.Vector.random2D = function random2D() {
66515  return this.fromAngle(Math.random() * constants.TWO_PI);
66516};
66517
66518/**
66519 * Make a new random 3D unit vector.
66520 *
66521 * @method random3D
66522 * @static
66523 * @return {p5.Vector} the new p5.Vector object
66524 * @example
66525 * <div class="norender">
66526 * <code>
66527 * var v = p5.Vector.random3D();
66528 * // May make v's attributes something like:
66529 * // [0.61554617, -0.51195765, 0.599168] or
66530 * // [-0.4695841, -0.14366731, -0.8711202] or
66531 * // [0.6091097, -0.22805278, -0.7595902]
66532 * print(v);
66533 * </code>
66534 * </div>
66535 */
66536p5.Vector.random3D = function random3D() {
66537  var angle = Math.random() * constants.TWO_PI;
66538  var vz = Math.random() * 2 - 1;
66539  var vzBase = Math.sqrt(1 - vz * vz);
66540  var vx = vzBase * Math.cos(angle);
66541  var vy = vzBase * Math.sin(angle);
66542  return new p5.Vector(vx, vy, vz);
66543};
66544
66545// Adds two vectors together and returns a new one.
66546/**
66547 * @method add
66548 * @static
66549 * @param  {p5.Vector} v1 a p5.Vector to add
66550 * @param  {p5.Vector} v2 a p5.Vector to add
66551 * @param  {p5.Vector} target the vector to receive the result
66552 */
66553/**
66554 * @method add
66555 * @static
66556 * @param  {p5.Vector} v1
66557 * @param  {p5.Vector} v2
66558 * @return {p5.Vector} the resulting p5.Vector
66559 *
66560 */
66561
66562p5.Vector.add = function add(v1, v2, target) {
66563  if (!target) {
66564    target = v1.copy();
66565  } else {
66566    target.set(v1);
66567  }
66568  target.add(v2);
66569  return target;
66570};
66571
66572/*
66573 * Subtracts one p5.Vector from another and returns a new one.  The second
66574 * vector (v2) is subtracted from the first (v1), resulting in v1-v2.
66575 */
66576/**
66577 * @method sub
66578 * @static
66579 * @param  {p5.Vector} v1 a p5.Vector to subtract from
66580 * @param  {p5.Vector} v2 a p5.Vector to subtract
66581 * @param  {p5.Vector} target if undefined a new vector will be created
66582 */
66583/**
66584 * @method sub
66585 * @static
66586 * @param  {p5.Vector} v1
66587 * @param  {p5.Vector} v2
66588 * @return {p5.Vector} the resulting p5.Vector
66589 */
66590
66591p5.Vector.sub = function sub(v1, v2, target) {
66592  if (!target) {
66593    target = v1.copy();
66594  } else {
66595    target.set(v1);
66596  }
66597  target.sub(v2);
66598  return target;
66599};
66600
66601/**
66602 * Multiplies a vector by a scalar and returns a new vector.
66603 */
66604/**
66605 * @method mult
66606 * @static
66607 * @param  {p5.Vector} v the vector to multiply
66608 * @param  {Number}  n
66609 * @param  {p5.Vector} target if undefined a new vector will be created
66610 */
66611/**
66612 * @method mult
66613 * @static
66614 * @param  {p5.Vector} v
66615 * @param  {Number}  n
66616 * @return {p5.Vector}  the resulting new p5.Vector
66617 */
66618p5.Vector.mult = function mult(v, n, target) {
66619  if (!target) {
66620    target = v.copy();
66621  } else {
66622    target.set(v);
66623  }
66624  target.mult(n);
66625  return target;
66626};
66627
66628/**
66629 * Divides a vector by a scalar and returns a new vector.
66630 */
66631/**
66632 * @method div
66633 * @static
66634 * @param  {p5.Vector} v the vector to divide
66635 * @param  {Number}  n
66636 * @param  {p5.Vector} target if undefined a new vector will be created
66637 */
66638/**
66639 * @method div
66640 * @static
66641 * @param  {p5.Vector} v
66642 * @param  {Number}  n
66643 * @return {p5.Vector} the resulting new p5.Vector
66644 */
66645p5.Vector.div = function div(v, n, target) {
66646  if (!target) {
66647    target = v.copy();
66648  } else {
66649    target.set(v);
66650  }
66651  target.div(n);
66652  return target;
66653};
66654
66655/**
66656 * Calculates the dot product of two vectors.
66657 */
66658/**
66659 * @method dot
66660 * @static
66661 * @param  {p5.Vector} v1 the first p5.Vector
66662 * @param  {p5.Vector} v2 the second p5.Vector
66663 * @return {Number}     the dot product
66664 */
66665p5.Vector.dot = function dot(v1, v2) {
66666  return v1.dot(v2);
66667};
66668
66669/**
66670 * Calculates the cross product of two vectors.
66671 */
66672/**
66673 * @method cross
66674 * @static
66675 * @param  {p5.Vector} v1 the first p5.Vector
66676 * @param  {p5.Vector} v2 the second p5.Vector
66677 * @return {Number}     the cross product
66678 */
66679p5.Vector.cross = function cross(v1, v2) {
66680  return v1.cross(v2);
66681};
66682
66683/**
66684 * Calculates the Euclidean distance between two points (considering a
66685 * point as a vector object).
66686 */
66687/**
66688 * @method dist
66689 * @static
66690 * @param  {p5.Vector} v1 the first p5.Vector
66691 * @param  {p5.Vector} v2 the second p5.Vector
66692 * @return {Number}     the distance
66693 */
66694p5.Vector.dist = function dist(v1, v2) {
66695  return v1.dist(v2);
66696};
66697
66698/**
66699 * Linear interpolate a vector to another vector and return the result as a
66700 * new vector.
66701 */
66702/**
66703 * @method lerp
66704 * @static
66705 * @param {p5.Vector} v1
66706 * @param {p5.Vector} v2
66707 * @param {Number} amt
66708 * @param {p5.Vector} target if undefined a new vector will be created
66709 */
66710/**
66711 * @method lerp
66712 * @static
66713 * @param {p5.Vector} v1
66714 * @param {p5.Vector} v2
66715 * @param {Number} amt
66716 * @return {Number}      the lerped value
66717 */
66718p5.Vector.lerp = function lerp(v1, v2, amt, target) {
66719  if (!target) {
66720    target = v1.copy();
66721  } else {
66722    target.set(v1);
66723  }
66724  target.lerp(v2, amt);
66725  return target;
66726};
66727
66728/**
66729 * @method mag
66730 * @param {p5.Vector} vecT the vector to return the magnitude of
66731 * @return {Number}        the magnitude of vecT
66732 * @static
66733 */
66734p5.Vector.mag = function mag(vecT) {
66735  var x = vecT.x,
66736    y = vecT.y,
66737    z = vecT.z;
66738  var magSq = x * x + y * y + z * z;
66739  return Math.sqrt(magSq);
66740};
66741
66742module.exports = p5.Vector;
66743
66744},{"../core/constants":21,"../core/core":22}],54:[function(_dereq_,module,exports){
66745/**
66746 * @module Math
66747 * @submodule Random
66748 * @for p5
66749 * @requires core
66750 */
66751
66752'use strict';
66753
66754var p5 = _dereq_('../core/core');
66755
66756var seeded = false;
66757var previous = false;
66758var y2 = 0;
66759
66760// Linear Congruential Generator
66761// Variant of a Lehman Generator
66762var lcg = (function() {
66763  // Set to values from http://en.wikipedia.org/wiki/Numerical_Recipes
66764  // m is basically chosen to be large (as it is the max period)
66765  // and for its relationships to a and c
66766  var m = 4294967296,
66767    // a - 1 should be divisible by m's prime factors
66768    a = 1664525,
66769    // c and m should be co-prime
66770    c = 1013904223,
66771    seed,
66772    z;
66773  return {
66774    setSeed: function(val) {
66775      // pick a random seed if val is undefined or null
66776      // the >>> 0 casts the seed to an unsigned 32-bit integer
66777      z = seed = (val == null ? Math.random() * m : val) >>> 0;
66778    },
66779    getSeed: function() {
66780      return seed;
66781    },
66782    rand: function() {
66783      // define the recurrence relationship
66784      z = (a * z + c) % m;
66785      // return a float in [0, 1)
66786      // if z = m then z / m = 0 therefore (z % m) / m < 1 always
66787      return z / m;
66788    }
66789  };
66790})();
66791
66792/**
66793 * Sets the seed value for random().
66794 *
66795 * By default, random() produces different results each time the program
66796 * is run. Set the seed parameter to a constant to return the same
66797 * pseudo-random numbers each time the software is run.
66798 *
66799 * @method randomSeed
66800 * @param {Number} seed   the seed value
66801 * @example
66802 * <div>
66803 * <code>
66804 * randomSeed(99);
66805 * for (var i = 0; i < 100; i++) {
66806 *   var r = random(0, 255);
66807 *   stroke(r);
66808 *   line(i, 0, i, 100);
66809 * }
66810 * </code>
66811 * </div>
66812 *
66813 * @alt
66814 * many vertical lines drawn in white, black or grey.
66815 *
66816 */
66817p5.prototype.randomSeed = function(seed) {
66818  lcg.setSeed(seed);
66819  seeded = true;
66820  previous = false;
66821};
66822
66823/**
66824 * Return a random floating-point number.
66825 *
66826 * Takes either 0, 1 or 2 arguments.
66827 *
66828 * If no argument is given, returns a random number from 0
66829 * up to (but not including) 1.
66830 *
66831 * If one argument is given and it is a number, returns a random number from 0
66832 * up to (but not including) the number.
66833 *
66834 * If one argument is given and it is an array, returns a random element from
66835 * that array.
66836 *
66837 * If two arguments are given, returns a random number from the
66838 * first argument up to (but not including) the second argument.
66839 *
66840 * @method random
66841 * @param  {Number} [min]   the lower bound (inclusive)
66842 * @param  {Number} [max]   the upper bound (exclusive)
66843 * @return {Number} the random number
66844 * @example
66845 * <div>
66846 * <code>
66847 * for (var i = 0; i < 100; i++) {
66848 *   var r = random(50);
66849 *   stroke(r * 5);
66850 *   line(50, i, 50 + r, i);
66851 * }
66852 * </code>
66853 * </div>
66854 * <div>
66855 * <code>
66856 * for (var i = 0; i < 100; i++) {
66857 *   var r = random(-50, 50);
66858 *   line(50, i, 50 + r, i);
66859 * }
66860 * </code>
66861 * </div>
66862 * <div>
66863 * <code>
66864 * // Get a random element from an array using the random(Array) syntax
66865 * var words = ['apple', 'bear', 'cat', 'dog'];
66866 * var word = random(words); // select random word
66867 * text(word, 10, 50); // draw the word
66868 * </code>
66869 * </div>
66870 *
66871 * @alt
66872 * 100 horizontal lines from center canvas to right. size+fill change each time
66873 * 100 horizontal lines from center of canvas. height & side change each render
66874 * word displayed at random. Either apple, bear, cat, or dog
66875 *
66876 */
66877/**
66878 * @method random
66879 * @param  {Array} choices   the array to choose from
66880 * @return {*} the random element from the array
66881 * @example
66882 */
66883p5.prototype.random = function(min, max) {
66884  var rand;
66885
66886  if (seeded) {
66887    rand = lcg.rand();
66888  } else {
66889    rand = Math.random();
66890  }
66891  if (typeof min === 'undefined') {
66892    return rand;
66893  } else if (typeof max === 'undefined') {
66894    if (min instanceof Array) {
66895      return min[Math.floor(rand * min.length)];
66896    } else {
66897      return rand * min;
66898    }
66899  } else {
66900    if (min > max) {
66901      var tmp = min;
66902      min = max;
66903      max = tmp;
66904    }
66905
66906    return rand * (max - min) + min;
66907  }
66908};
66909
66910/**
66911 *
66912 * Returns a random number fitting a Gaussian, or
66913 * normal, distribution. There is theoretically no minimum or maximum
66914 * value that randomGaussian() might return. Rather, there is
66915 * just a very low probability that values far from the mean will be
66916 * returned; and a higher probability that numbers near the mean will
66917 * be returned.
66918 * <br><br>
66919 * Takes either 0, 1 or 2 arguments.<br>
66920 * If no args, returns a mean of 0 and standard deviation of 1.<br>
66921 * If one arg, that arg is the mean (standard deviation is 1).<br>
66922 * If two args, first is mean, second is standard deviation.
66923 *
66924 * @method randomGaussian
66925 * @param  {Number} mean  the mean
66926 * @param  {Number} sd    the standard deviation
66927 * @return {Number} the random number
66928 * @example
66929 * <div>
66930 * <code>
66931 * for (var y = 0; y < 100; y++) {
66932 *   var x = randomGaussian(50, 15);
66933 *   line(50, y, x, y);
66934 * }
66935 * </code>
66936 * </div>
66937 * <div>
66938 * <code>
66939 * var distribution = new Array(360);
66940 *
66941 * function setup() {
66942 *   createCanvas(100, 100);
66943 *   for (var i = 0; i < distribution.length; i++) {
66944 *     distribution[i] = floor(randomGaussian(0, 15));
66945 *   }
66946 * }
66947 *
66948 * function draw() {
66949 *   background(204);
66950 *
66951 *   translate(width / 2, width / 2);
66952 *
66953 *   for (var i = 0; i < distribution.length; i++) {
66954 *     rotate(TWO_PI / distribution.length);
66955 *     stroke(0);
66956 *     var dist = abs(distribution[i]);
66957 *     line(0, 0, dist, 0);
66958 *   }
66959 * }
66960 * </code>
66961 * </div>
66962 * @alt
66963 * 100 horizontal lines from center of canvas. height & side change each render
66964 * black lines radiate from center of canvas. size determined each render
66965 */
66966p5.prototype.randomGaussian = function(mean, sd) {
66967  var y1, x1, x2, w;
66968  if (previous) {
66969    y1 = y2;
66970    previous = false;
66971  } else {
66972    do {
66973      x1 = this.random(2) - 1;
66974      x2 = this.random(2) - 1;
66975      w = x1 * x1 + x2 * x2;
66976    } while (w >= 1);
66977    w = Math.sqrt(-2 * Math.log(w) / w);
66978    y1 = x1 * w;
66979    y2 = x2 * w;
66980    previous = true;
66981  }
66982
66983  var m = mean || 0;
66984  var s = sd || 1;
66985  return y1 * s + m;
66986};
66987
66988module.exports = p5;
66989
66990},{"../core/core":22}],55:[function(_dereq_,module,exports){
66991/**
66992 * @module Math
66993 * @submodule Trigonometry
66994 * @for p5
66995 * @requires core
66996 * @requires constants
66997 */
66998
66999'use strict';
67000
67001var p5 = _dereq_('../core/core');
67002var constants = _dereq_('../core/constants');
67003
67004/*
67005 * all DEGREES/RADIANS conversion should be done in the p5 instance
67006 * if possible, using the p5._toRadians(), p5._fromRadians() methods.
67007 */
67008p5.prototype._angleMode = constants.RADIANS;
67009
67010/**
67011 * The inverse of cos(), returns the arc cosine of a value. This function
67012 * expects the values in the range of -1 to 1 and values are returned in
67013 * the range 0 to PI (3.1415927).
67014 *
67015 * @method acos
67016 * @param  {Number} value the value whose arc cosine is to be returned
67017 * @return {Number}       the arc cosine of the given value
67018 *
67019 * @example
67020 * <div class= “norender">
67021 * <code>
67022 * var a = PI;
67023 * var c = cos(a);
67024 * var ac = acos(c);
67025 * // Prints: "3.1415927 : -1.0 : 3.1415927"
67026 * print(a + ' : ' + c + ' : ' + ac);
67027 * </code>
67028 * </div>
67029 *
67030 * <div class= “norender">
67031 * <code>
67032 * var a = PI + PI / 4.0;
67033 * var c = cos(a);
67034 * var ac = acos(c);
67035 * // Prints: "3.926991 : -0.70710665 : 2.3561943"
67036 * print(a + ' : ' + c + ' : ' + ac);
67037 * </code>
67038 * </div>
67039 */
67040p5.prototype.acos = function(ratio) {
67041  return this._fromRadians(Math.acos(ratio));
67042};
67043
67044/**
67045 * The inverse of sin(), returns the arc sine of a value. This function
67046 * expects the values in the range of -1 to 1 and values are returned
67047 * in the range -PI/2 to PI/2.
67048 *
67049 * @method asin
67050 * @param  {Number} value the value whose arc sine is to be returned
67051 * @return {Number}       the arc sine of the given value
67052 *
67053 * @example
67054 * <div class= “norender">
67055 * <code>
67056 * var a = PI + PI / 3;
67057 * var s = sin(a);
67058 * var as = asin(s);
67059 * // Prints: "1.0471976 : 0.86602545 : 1.0471976"
67060 * print(a + ' : ' + s + ' : ' + as);
67061 * </code>
67062 * </div>
67063 *
67064 * <div class= “norender">
67065 * <code>
67066 * var a = PI + PI / 3.0;
67067 * var s = sin(a);
67068 * var as = asin(s);
67069 * // Prints: "4.1887903 : -0.86602545 : -1.0471976"
67070 * print(a + ' : ' + s + ' : ' + as);
67071 * </code>
67072 * </div>
67073 *
67074 */
67075p5.prototype.asin = function(ratio) {
67076  return this._fromRadians(Math.asin(ratio));
67077};
67078
67079/**
67080 * The inverse of tan(), returns the arc tangent of a value. This function
67081 * expects the values in the range of -Infinity to Infinity (exclusive) and
67082 * values are returned in the range -PI/2 to PI/2.
67083 *
67084 * @method atan
67085 * @param  {Number} value the value whose arc tangent is to be returned
67086 * @return {Number}       the arc tangent of the given value
67087 *
67088 * @example
67089 * <div class= “norender">
67090 * <code>
67091 * var a = PI + PI / 3;
67092 * var t = tan(a);
67093 * var at = atan(t);
67094 * // Prints: "1.0471976 : 1.7320509 : 1.0471976"
67095 * print(a + ' : ' + t + ' : ' + at);
67096 * </code>
67097 * </div>
67098 *
67099 * <div class= “norender">
67100 * <code>
67101 * var a = PI + PI / 3.0;
67102 * var t = tan(a);
67103 * var at = atan(t);
67104 * // Prints: "4.1887903 : 1.7320513 : 1.0471977"
67105 * print(a + ' : ' + t + ' : ' + at);
67106 * </code>
67107 * </div>
67108 *
67109 */
67110p5.prototype.atan = function(ratio) {
67111  return this._fromRadians(Math.atan(ratio));
67112};
67113
67114/**
67115 * Calculates the angle (in radians) from a specified point to the coordinate
67116 * origin as measured from the positive x-axis. Values are returned as a
67117 * float in the range from PI to -PI. The atan2() function is most often used
67118 * for orienting geometry to the position of the cursor.
67119 * <br><br>
67120 * Note: The y-coordinate of the point is the first parameter, and the
67121 * x-coordinate is the second parameter, due the the structure of calculating
67122 * the tangent.
67123 *
67124 * @method atan2
67125 * @param  {Number} y y-coordinate of the point
67126 * @param  {Number} x x-coordinate of the point
67127 * @return {Number}   the arc tangent of the given point
67128 *
67129 * @example
67130 * <div>
67131 * <code>
67132 * function draw() {
67133 *   background(204);
67134 *   translate(width / 2, height / 2);
67135 *   var a = atan2(mouseY - height / 2, mouseX - width / 2);
67136 *   rotate(a);
67137 *   rect(-30, -5, 60, 10);
67138 * }
67139 * </code>
67140 * </div>
67141 *
67142 * @alt
67143 * 60 by 10 rect at center of canvas rotates with mouse movements
67144 *
67145 */
67146p5.prototype.atan2 = function(y, x) {
67147  return this._fromRadians(Math.atan2(y, x));
67148};
67149
67150/**
67151 * Calculates the cosine of an angle. This function takes into account the
67152 * current angleMode. Values are returned in the range -1 to 1.
67153 *
67154 * @method cos
67155 * @param  {Number} angle the angle
67156 * @return {Number}       the cosine of the angle
67157 *
67158 * @example
67159 * <div>
67160 * <code>
67161 * var a = 0.0;
67162 * var inc = TWO_PI / 25.0;
67163 * for (var i = 0; i < 25; i++) {
67164 *   line(i * 4, 50, i * 4, 50 + cos(a) * 40.0);
67165 *   a = a + inc;
67166 * }
67167 * </code>
67168 * </div>
67169 *
67170 * @alt
67171 * vertical black lines form wave patterns, extend-down on left and right side
67172 *
67173 */
67174p5.prototype.cos = function(angle) {
67175  return Math.cos(this._toRadians(angle));
67176};
67177
67178/**
67179 * Calculates the sine of an angle. This function takes into account the
67180 * current angleMode. Values are returned in the range -1 to 1.
67181 *
67182 * @method sin
67183 * @param  {Number} angle the angle
67184 * @return {Number}       the sine of the angle
67185 *
67186 * @example
67187 * <div>
67188 * <code>
67189 * var a = 0.0;
67190 * var inc = TWO_PI / 25.0;
67191 * for (var i = 0; i < 25; i++) {
67192 *   line(i * 4, 50, i * 4, 50 + sin(a) * 40.0);
67193 *   a = a + inc;
67194 * }
67195 * </code>
67196 * </div>
67197 *
67198 * @alt
67199 * vertical black lines extend down and up from center to form wave pattern
67200 *
67201 */
67202p5.prototype.sin = function(angle) {
67203  return Math.sin(this._toRadians(angle));
67204};
67205
67206/**
67207 * Calculates the tangent of an angle. This function takes into account
67208 * the current angleMode. Values are returned in the range -1 to 1.
67209 *
67210 * @method tan
67211 * @param  {Number} angle the angle
67212 * @return {Number}       the tangent of the angle
67213 *
67214 * @example
67215 * <div>
67216 * <code>
67217 * var a = 0.0;
67218 * var inc = TWO_PI / 50.0;
67219 * for (var i = 0; i < 100; i = i + 2) {
67220 *   line(i, 50, i, 50 + tan(a) * 2.0);
67221 *   a = a + inc;
67222 * }
67223 * </code>
67224 *
67225 *
67226 * @alt
67227 * vertical black lines end down and up from center to form spike pattern
67228 *
67229 */
67230p5.prototype.tan = function(angle) {
67231  return Math.tan(this._toRadians(angle));
67232};
67233
67234/**
67235 * Converts a radian measurement to its corresponding value in degrees.
67236 * Radians and degrees are two ways of measuring the same thing. There are
67237 * 360 degrees in a circle and 2*PI radians in a circle. For example,
67238 * 90° = PI/2 = 1.5707964. This function does not take into account the
67239 * current angleMode.
67240 *
67241 * @method degrees
67242 * @param  {Number} radians the radians value to convert to degrees
67243 * @return {Number}         the converted angle
67244 *
67245 *
67246 * @example
67247 * <div class= “norender">
67248 * <code>
67249 * var rad = PI / 4;
67250 * var deg = degrees(rad);
67251 * print(rad + ' radians is ' + deg + ' degrees');
67252 * // Prints: 0.7853981633974483 radians is 45 degrees
67253 * </code>
67254 * </div>
67255 *
67256 */
67257p5.prototype.degrees = function(angle) {
67258  return angle * constants.RAD_TO_DEG;
67259};
67260
67261/**
67262 * Converts a degree measurement to its corresponding value in radians.
67263 * Radians and degrees are two ways of measuring the same thing. There are
67264 * 360 degrees in a circle and 2*PI radians in a circle. For example,
67265 * 90° = PI/2 = 1.5707964. This function does not take into account the
67266 * current angleMode.
67267 *
67268 * @method radians
67269 * @param  {Number} degrees the degree value to convert to radians
67270 * @return {Number}         the converted angle
67271 *
67272 * @example
67273 * <div class= “norender">
67274 * <code>
67275 * var deg = 45.0;
67276 * var rad = radians(deg);
67277 * print(deg + ' degrees is ' + rad + ' radians');
67278 * // Prints: 45 degrees is 0.7853981633974483 radians
67279 * </code>
67280 * </div>
67281 */
67282p5.prototype.radians = function(angle) {
67283  return angle * constants.DEG_TO_RAD;
67284};
67285
67286/**
67287 * Sets the current mode of p5 to given mode. Default mode is RADIANS.
67288 *
67289 * @method angleMode
67290 * @param {Constant} mode either RADIANS or DEGREES
67291 *
67292 * @example
67293 * <div>
67294 * <code>
67295 * function draw() {
67296 *   background(204);
67297 *   angleMode(DEGREES); // Change the mode to DEGREES
67298 *   var a = atan2(mouseY - height / 2, mouseX - width / 2);
67299 *   translate(width / 2, height / 2);
67300 *   push();
67301 *   rotate(a);
67302 *   rect(-20, -5, 40, 10); // Larger rectangle is rotating in degrees
67303 *   pop();
67304 *   angleMode(RADIANS); // Change the mode to RADIANS
67305 *   rotate(a); // var a stays the same
67306 *   rect(-40, -5, 20, 10); // Smaller rectangle is rotating in radians
67307 * }
67308 * </code>
67309 * </div>
67310 *
67311 * @alt
67312 * 40 by 10 rect in center rotates with mouse moves. 20 by 10 rect moves faster.
67313 *
67314 *
67315 */
67316p5.prototype.angleMode = function(mode) {
67317  if (mode === constants.DEGREES || mode === constants.RADIANS) {
67318    this._angleMode = mode;
67319  }
67320};
67321
67322/**
67323 * converts angles from the current angleMode to RADIANS
67324 *
67325 * @method _toRadians
67326 * @private
67327 * @param {Number} angle
67328 * @returns {Number}
67329 */
67330p5.prototype._toRadians = function(angle) {
67331  if (this._angleMode === constants.DEGREES) {
67332    return angle * constants.DEG_TO_RAD;
67333  }
67334  return angle;
67335};
67336
67337/**
67338 * converts angles from the current angleMode to DEGREES
67339 *
67340 * @method _toDegrees
67341 * @private
67342 * @param {Number} angle
67343 * @returns {Number}
67344 */
67345p5.prototype._toDegrees = function(angle) {
67346  if (this._angleMode === constants.RADIANS) {
67347    return angle * constants.RAD_TO_DEG;
67348  }
67349  return angle;
67350};
67351
67352/**
67353 * converts angles from RADIANS into the current angleMode
67354 *
67355 * @method _fromRadians
67356 * @private
67357 * @param {Number} angle
67358 * @returns {Number}
67359 */
67360p5.prototype._fromRadians = function(angle) {
67361  if (this._angleMode === constants.DEGREES) {
67362    return angle * constants.RAD_TO_DEG;
67363  }
67364  return angle;
67365};
67366
67367module.exports = p5;
67368
67369},{"../core/constants":21,"../core/core":22}],56:[function(_dereq_,module,exports){
67370/**
67371 * @module Typography
67372 * @submodule Attributes
67373 * @for p5
67374 * @requires core
67375 * @requires constants
67376 */
67377
67378'use strict';
67379
67380var p5 = _dereq_('../core/core');
67381
67382/**
67383 * Sets the current alignment for drawing text. Accepts two
67384 * arguments: horizAlign (LEFT, CENTER, or RIGHT) and
67385 * vertAlign (TOP, BOTTOM, CENTER, or BASELINE).
67386 *
67387 * The horizAlign parameter is in reference to the x value
67388 * of the text() function, while the vertAlign parameter is
67389 * in reference to the y value.
67390 *
67391 * So if you write textAlign(LEFT), you are aligning the left
67392 * edge of your text to the x value you give in text(). If you
67393 * write textAlign(RIGHT, TOP), you are aligning the right edge
67394 * of your text to the x value and the top of edge of the text
67395 * to the y value.
67396 *
67397 * @method textAlign
67398 * @param {Constant} horizAlign horizontal alignment, either LEFT,
67399 *                            CENTER, or RIGHT
67400 * @param {Constant} [vertAlign] vertical alignment, either TOP,
67401 *                            BOTTOM, CENTER, or BASELINE
67402 * @chainable
67403 * @example
67404 * <div>
67405 * <code>
67406 * textSize(16);
67407 * textAlign(RIGHT);
67408 * text('ABCD', 50, 30);
67409 * textAlign(CENTER);
67410 * text('EFGH', 50, 50);
67411 * textAlign(LEFT);
67412 * text('IJKL', 50, 70);
67413 * </code>
67414 * </div>
67415 *
67416 * @alt
67417 *Letters ABCD displayed at top right, EFGH at center and IJKL at bottom left.
67418 *
67419 */
67420/**
67421 * @method textAlign
67422 * @return {Object}
67423 */
67424p5.prototype.textAlign = function(horizAlign, vertAlign) {
67425  p5._validateParameters('textAlign', arguments);
67426  return this._renderer.textAlign.apply(this._renderer, arguments);
67427};
67428
67429/**
67430 * Sets/gets the spacing, in pixels, between lines of text. This
67431 * setting will be used in all subsequent calls to the text() function.
67432 *
67433 * @method textLeading
67434 * @param {Number} leading the size in pixels for spacing between lines
67435 * @chainable
67436 *
67437 * @example
67438 * <div>
67439 * <code>
67440 * // Text to display. The "\n" is a "new line" character
67441 * var lines = 'L1\nL2\nL3';
67442 * textSize(12);
67443 *
67444 * textLeading(10); // Set leading to 10
67445 * text(lines, 10, 25);
67446 *
67447 * textLeading(20); // Set leading to 20
67448 * text(lines, 40, 25);
67449 *
67450 * textLeading(30); // Set leading to 30
67451 * text(lines, 70, 25);
67452 * </code>
67453 * </div>
67454 *
67455 * @alt
67456 *set L1 L2 & L3 displayed vertically 3 times. spacing increases for each set
67457 */
67458/**
67459 * @method textLeading
67460 * @return {Number}
67461 */
67462p5.prototype.textLeading = function(theLeading) {
67463  p5._validateParameters('textLeading', arguments);
67464  return this._renderer.textLeading.apply(this._renderer, arguments);
67465};
67466
67467/**
67468 * Sets/gets the current font size. This size will be used in all subsequent
67469 * calls to the text() function. Font size is measured in pixels.
67470 *
67471 * @method textSize
67472 * @param {Number} theSize the size of the letters in units of pixels
67473 * @chainable
67474 *
67475 * @example
67476 * <div>
67477 * <code>
67478 * textSize(12);
67479 * text('Font Size 12', 10, 30);
67480 * textSize(14);
67481 * text('Font Size 14', 10, 60);
67482 * textSize(16);
67483 * text('Font Size 16', 10, 90);
67484 * </code>
67485 * </div>
67486 *
67487 * @alt
67488 *Font Size 12 displayed small, Font Size 14 medium & Font Size 16 large
67489 */
67490/**
67491 * @method textSize
67492 * @return {Number}
67493 */
67494p5.prototype.textSize = function(theSize) {
67495  p5._validateParameters('textSize', arguments);
67496  return this._renderer.textSize.apply(this._renderer, arguments);
67497};
67498
67499/**
67500 * Sets/gets the style of the text for system fonts to NORMAL, ITALIC, or BOLD.
67501 * Note: this may be is overridden by CSS styling. For non-system fonts
67502 * (opentype, truetype, etc.) please load styled fonts instead.
67503 *
67504 * @method textStyle
67505 * @param {Constant} theStyle styling for text, either NORMAL,
67506 *                            ITALIC, or BOLD
67507 * @chainable
67508 * @example
67509 * <div>
67510 * <code>
67511 * strokeWeight(0);
67512 * textSize(12);
67513 * textStyle(NORMAL);
67514 * text('Font Style Normal', 10, 30);
67515 * textStyle(ITALIC);
67516 * text('Font Style Italic', 10, 60);
67517 * textStyle(BOLD);
67518 * text('Font Style Bold', 10, 90);
67519 * </code>
67520 * </div>
67521 *
67522 * @alt
67523 *words Font Style Normal displayed normally, Italic in italic and bold in bold
67524 */
67525/**
67526 * @method textStyle
67527 * @return {String}
67528 */
67529p5.prototype.textStyle = function(theStyle) {
67530  p5._validateParameters('textStyle', arguments);
67531  return this._renderer.textStyle.apply(this._renderer, arguments);
67532};
67533
67534/**
67535 * Calculates and returns the width of any character or text string.
67536 *
67537 * @method textWidth
67538 * @param {String} theText the String of characters to measure
67539 * @return {Number}
67540 * @example
67541 * <div>
67542 * <code>
67543 * textSize(28);
67544 *
67545 * var aChar = 'P';
67546 * var cWidth = textWidth(aChar);
67547 * text(aChar, 0, 40);
67548 * line(cWidth, 0, cWidth, 50);
67549 *
67550 * var aString = 'p5.js';
67551 * var sWidth = textWidth(aString);
67552 * text(aString, 0, 85);
67553 * line(sWidth, 50, sWidth, 100);
67554 * </code>
67555 * </div>
67556 *
67557 * @alt
67558 *Letter P and p5.js are displayed with vertical lines at end. P is wide
67559 *
67560 */
67561p5.prototype.textWidth = function(theText) {
67562  p5._validateParameters('textWidth', arguments);
67563  if (theText.length === 0) {
67564    return 0;
67565  }
67566  return this._renderer.textWidth.apply(this._renderer, arguments);
67567};
67568
67569/**
67570 * Returns the ascent of the current font at its current size. The ascent
67571 * represents the distance, in pixels, of the tallest character above
67572 * the baseline.
67573 * @method textAscent
67574 * @return {Number}
67575 * @example
67576 * <div>
67577 * <code>
67578 * var base = height * 0.75;
67579 * var scalar = 0.8; // Different for each font
67580 *
67581 * textSize(32); // Set initial text size
67582 * var asc = textAscent() * scalar; // Calc ascent
67583 * line(0, base - asc, width, base - asc);
67584 * text('dp', 0, base); // Draw text on baseline
67585 *
67586 * textSize(64); // Increase text size
67587 * asc = textAscent() * scalar; // Recalc ascent
67588 * line(40, base - asc, width, base - asc);
67589 * text('dp', 40, base); // Draw text on baseline
67590 * </code>
67591 * </div>
67592 */
67593p5.prototype.textAscent = function() {
67594  p5._validateParameters('textAscent', arguments);
67595  return this._renderer.textAscent();
67596};
67597
67598/**
67599 * Returns the descent of the current font at its current size. The descent
67600 * represents the distance, in pixels, of the character with the longest
67601 * descender below the baseline.
67602 * @method textDescent
67603 * @return {Number}
67604 * @example
67605 * <div>
67606 * <code>
67607 * var base = height * 0.75;
67608 * var scalar = 0.8; // Different for each font
67609 *
67610 * textSize(32); // Set initial text size
67611 * var desc = textDescent() * scalar; // Calc ascent
67612 * line(0, base + desc, width, base + desc);
67613 * text('dp', 0, base); // Draw text on baseline
67614 *
67615 * textSize(64); // Increase text size
67616 * desc = textDescent() * scalar; // Recalc ascent
67617 * line(40, base + desc, width, base + desc);
67618 * text('dp', 40, base); // Draw text on baseline
67619 * </code>
67620 * </div>
67621 */
67622p5.prototype.textDescent = function() {
67623  p5._validateParameters('textDescent', arguments);
67624  return this._renderer.textDescent();
67625};
67626
67627/**
67628 * Helper function to measure ascent and descent.
67629 */
67630p5.prototype._updateTextMetrics = function() {
67631  return this._renderer._updateTextMetrics();
67632};
67633
67634module.exports = p5;
67635
67636},{"../core/core":22}],57:[function(_dereq_,module,exports){
67637/**
67638 * @module Typography
67639 * @submodule Loading & Displaying
67640 * @for p5
67641 * @requires core
67642 */
67643
67644'use strict';
67645
67646var p5 = _dereq_('../core/core');
67647var constants = _dereq_('../core/constants');
67648var opentype = _dereq_('opentype.js');
67649
67650_dereq_('../core/error_helpers');
67651
67652/**
67653 * Loads an opentype font file (.otf, .ttf) from a file or a URL,
67654 * and returns a PFont Object. This method is asynchronous,
67655 * meaning it may not finish before the next line in your sketch
67656 * is executed.
67657 * <br><br>
67658 * The path to the font should be relative to the HTML file
67659 * that links in your sketch. Loading an from a URL or other
67660 * remote location may be blocked due to your browser's built-in
67661 * security.
67662 *
67663 * @method loadFont
67664 * @param  {String}        path       name of the file or url to load
67665 * @param  {Function}      [callback] function to be executed after
67666 *                                    loadFont() completes
67667 * @param  {Function}      [onError]  function to be executed if
67668 *                                    an error occurs
67669 * @return {p5.Font}                  p5.Font object
67670 * @example
67671 *
67672 * <p>Calling loadFont() inside preload() guarantees that the load
67673 * operation will have completed before setup() and draw() are called.</p>
67674 *
67675 * <div><code>
67676 * var myFont;
67677 * function preload() {
67678 *   myFont = loadFont('assets/AvenirNextLTPro-Demi.otf');
67679 * }
67680 *
67681 * function setup() {
67682 *   fill('#ED225D');
67683 *   textFont(myFont);
67684 *   textSize(36);
67685 *   text('p5*js', 10, 50);
67686 * }
67687 * </code></div>
67688 *
67689 * Outside of preload(), you may supply a callback function to handle the
67690 * object:
67691 *
67692 * <div><code>
67693 * function setup() {
67694 *   loadFont('assets/AvenirNextLTPro-Demi.otf', drawText);
67695 * }
67696 *
67697 * function drawText(font) {
67698 *   fill('#ED225D');
67699 *   textFont(font, 36);
67700 *   text('p5*js', 10, 50);
67701 * }
67702 * </code></div>
67703 *
67704 * <p>You can also use the string name of the font to style other HTML
67705 * elements.</p>
67706 *
67707 * <div><code>
67708 * function preload() {
67709 *   loadFont('assets/Avenir.otf');
67710 * }
67711 *
67712 * function setup() {
67713 *   var myDiv = createDiv('hello there');
67714 *   myDiv.style('font-family', 'Avenir');
67715 * }
67716 * </code></div>
67717 *
67718 * @alt
67719 * p5*js in p5's theme dark pink
67720 * p5*js in p5's theme dark pink
67721 *
67722 */
67723p5.prototype.loadFont = function(path, onSuccess, onError) {
67724  p5._validateParameters('loadFont', arguments);
67725  var p5Font = new p5.Font(this);
67726
67727  var self = this;
67728  opentype.load(path, function(err, font) {
67729    if (err) {
67730      if (typeof onError !== 'undefined') {
67731        return onError(err);
67732      }
67733      p5._friendlyFileLoadError(4, path);
67734      console.error(err, path);
67735      return;
67736    }
67737
67738    p5Font.font = font;
67739
67740    if (typeof onSuccess !== 'undefined') {
67741      onSuccess(p5Font);
67742    }
67743
67744    self._decrementPreload();
67745
67746    // check that we have an acceptable font type
67747    var validFontTypes = ['ttf', 'otf', 'woff', 'woff2'],
67748      fileNoPath = path
67749        .split('\\')
67750        .pop()
67751        .split('/')
67752        .pop(),
67753      lastDotIdx = fileNoPath.lastIndexOf('.'),
67754      fontFamily,
67755      newStyle,
67756      fileExt = lastDotIdx < 1 ? null : fileNoPath.substr(lastDotIdx + 1);
67757
67758    // if so, add it to the DOM (name-only) for use with p5.dom
67759    if (validFontTypes.indexOf(fileExt) > -1) {
67760      fontFamily = fileNoPath.substr(0, lastDotIdx);
67761      newStyle = document.createElement('style');
67762      newStyle.appendChild(
67763        document.createTextNode(
67764          '\n@font-face {' +
67765            '\nfont-family: ' +
67766            fontFamily +
67767            ';\nsrc: url(' +
67768            path +
67769            ');\n}\n'
67770        )
67771      );
67772      document.head.appendChild(newStyle);
67773    }
67774  });
67775
67776  return p5Font;
67777};
67778
67779/**
67780 * Draws text to the screen. Displays the information specified in the first
67781 * parameter on the screen in the position specified by the additional
67782 * parameters. A default font will be used unless a font is set with the
67783 * textFont() function and a default size will be used unless a font is set
67784 * with textSize(). Change the color of the text with the fill() function.
67785 * Change the outline of the text with the stroke() and strokeWeight(
67785)
67786 * functions.
67787 * <br><br>
67788 * The text displays in relation to the textAlign() function, which gives the
67789 * option to draw to the left, right, and center of the coordinates.
67790 * <br><br>
67791 * The x2 and y2 parameters define a rectangular area to display within and
67792 * may only be used with string data. When these parameters are specified,
67793 * they are interpreted based on the current rectMode() setting. Text that
67794 * does not fit completely within the rectangle specified will not be drawn
67795 * to the screen.
67796 *
67797 * @method text
67798 * @param {String|Object|Array|Number|Boolean} str the alphanumeric
67799 *                                             symbols to be displayed
67800 * @param {Number} x   x-coordinate of text
67801 * @param {Number} y   y-coordinate of text
67802 * @param {Number} [x2]  by default, the width of the text box,
67803 *                     see rectMode() for more info
67804 * @param {Number} [y2]  by default, the height of the text box,
67805 *                     see rectMode() for more info
67806 * @chainable
67807 * @example
67808 * <div>
67809 * <code>
67810 * textSize(32);
67811 * text('word', 10, 30);
67812 * fill(0, 102, 153);
67813 * text('word', 10, 60);
67814 * fill(0, 102, 153, 51);
67815 * text('word', 10, 90);
67816 * </code>
67817 * </div>
67818 * <div>
67819 * <code>
67820 * var s = 'The quick brown fox jumped over the lazy dog.';
67821 * fill(50);
67822 * text(s, 10, 10, 70, 80); // Text wraps within text box
67823 * </code>
67824 * </div>
67825 *
67826 * @alt
67827 *'word' displayed 3 times going from black, blue to translucent blue
67828 * The quick brown fox jumped over the lazy dog.
67829 *
67830 */
67831p5.prototype.text = function(str, x, y, maxWidth, maxHeight) {
67832  p5._validateParameters('text', arguments);
67833  return !(this._renderer._doFill || this._renderer._doStroke)
67834    ? this
67835    : this._renderer.text.apply(this._renderer, arguments);
67836};
67837
67838/**
67839 * Sets the current font that will be drawn with the text() function.
67840 *
67841 * @method textFont
67842 * @return {Object} the current font
67843 *
67844 * @example
67845 * <div>
67846 * <code>
67847 * fill(0);
67848 * textSize(12);
67849 * textFont('Georgia');
67850 * text('Georgia', 12, 30);
67851 * textFont('Helvetica');
67852 * text('Helvetica', 12, 60);
67853 * </code>
67854 * </div>
67855 * <div>
67856 * <code>
67857 * var fontRegular, fontItalic, fontBold;
67858 * function preload() {
67859 *   fontRegular = loadFont('assets/Regular.otf');
67860 *   fontItalic = loadFont('assets/Italic.ttf');
67861 *   fontBold = loadFont('assets/Bold.ttf');
67862 * }
67863 * function setup() {
67864 *   background(210);
67865 *   fill(0)
67866    .strokeWeight(0)
67867    .textSize(10);
67868 *   textFont(fontRegular);
67869 *   text('Font Style Normal', 10, 30);
67870 *   textFont(fontItalic);
67871 *   text('Font Style Italic', 10, 50);
67872 *   textFont(fontBold);
67873 *   text('Font Style Bold', 10, 70);
67874 * }
67875 * </code>
67876 * </div>
67877 *
67878 * @alt
67879 *words Font Style Normal displayed normally, Italic in italic and bold in bold
67880 */
67881/**
67882 * @method textFont
67883 * @param {Object|String} font a font loaded via loadFont(), or a String
67884 * representing a <a href="https://mzl.la/2dOw8WD">web safe font</a> (a font
67885 * that is generally available across all systems)
67886 * @param {Number} [size] the font size to use
67887 * @chainable
67888 */
67889p5.prototype.textFont = function(theFont, theSize) {
67890  p5._validateParameters('textFont', arguments);
67891  if (arguments.length) {
67892    if (!theFont) {
67893      throw Error('null font passed to textFont');
67894    }
67895
67896    this._renderer._setProperty('_textFont', theFont);
67897
67898    if (theSize) {
67899      this._renderer._setProperty('_textSize', theSize);
67900      this._renderer._setProperty(
67901        '_textLeading',
67902        theSize * constants._DEFAULT_LEADMULT
67903      );
67904    }
67905
67906    return this._renderer._applyTextProperties();
67907  }
67908
67909  return this._renderer._textFont;
67910};
67911
67912module.exports = p5;
67913
67914},{"../core/constants":21,"../core/core":22,"../core/error_helpers":25,"opentype.js":10}],58:[function(_dereq_,module,exports){
67915/**
67916 * This module defines the p5.Font class and functions for
67917 * drawing text to the display canvas.
67918 * @module Typography
67919 * @submodule Font
67920 * @requires core
67921 * @requires constants
67922 */
67923
67924'use strict';
67925
67926var p5 = _dereq_('../core/core');
67927var constants = _dereq_('../core/constants');
67928
67929/*
67930 * TODO:
67931 * -- kerning
67932 * -- alignment: justified?
67933 */
67934
67935/**
67936 * Base class for font handling
67937 * @class p5.Font
67938 * @param {p5} [pInst] pointer to p5 instance
67939 */
67940p5.Font = function(p) {
67941  this.parent = p;
67942
67943  this.cache = {};
67944
67945  /**
67946   * Underlying opentype font implementation
67947   * @property font
67948   */
67949  this.font = undefined;
67950};
67951
67952p5.Font.prototype.list = function() {
67953  // TODO
67954  throw 'not yet implemented';
67955};
67956
67957/**
67958 * Returns a tight bounding box for the given text string using this
67959 * font (currently only supports single lines)
67960 *
67961 * @method textBounds
67962 * @param  {String} line     a line of text
67963 * @param  {Number} x        x-position
67964 * @param  {Number} y        y-position
67965 * @param  {Number} [fontSize] font size to use (optional)
67966 * @param  {Object} [options] opentype options (optional)
67967 *
67968 * @return {Object}          a rectangle object with properties: x, y, w, h
67969 *
67970 * @example
67971 * <div>
67972 * <code>
67973 * var font;
67974 * var textString = 'Lorem ipsum dolor sit amet.';
67975 * function preload() {
67976 *   font = loadFont('./assets/Regular.otf');
67977 * }
67978 * function setup() {
67979 *   background(210);
67980 *
67981 *   var bbox = font.textBounds(textString, 10, 30, 12);
67982 *   fill(255);
67983 *   stroke(0);
67984 *   rect(bbox.x, bbox.y, bbox.w, bbox.h);
67985 *   fill(0);
67986 *   noStroke();
67987 *
67988 *   textFont(font);
67989 *   textSize(12);
67990 *   text(textString, 10, 30);
67991 * }
67992 * </code>
67993 * </div>
67994 *
67995 * @alt
67996 *words Lorem ipsum dol go off canvas and contained by white bounding box
67997 *
67998 */
67999p5.Font.prototype.textBounds = function(str, x, y, fontSize, options) {
68000  x = x !== undefined ? x : 0;
68001  y = y !== undefined ? y : 0;
68002  fontSize = fontSize || this.parent._renderer._textSize;
68003
68004  // Check cache for existing bounds. Take into consideration the text alignment
68005  // settings. Default alignment should match opentype's origin: left-aligned &
68006  // alphabetic baseline.
68007  var p =
68008      (options && options.renderer && options.renderer._pInst) || this.parent,
68009    ctx = p._renderer.drawingContext,
68010    alignment = ctx.textAlign || constants.LEFT,
68011    baseline = ctx.textBaseline || constants.BASELINE,
68012    key = cacheKey('textBounds', str, x, y, fontSize, alignment, baseline),
68013    result = this.cache[key];
68014
68015  if (!result) {
68016    var minX,
68017      minY,
68018      maxX,
68019      maxY,
68020      pos,
68021      xCoords = [],
68022      yCoords = [],
68023      scale = this._scale(fontSize);
68024
68025    this.font.forEachGlyph(str, x, y, fontSize, options, function(
68026      glyph,
68027      gX,
68028      gY,
68029      gFontSize
68030    ) {
68031      var gm = glyph.getMetrics();
68032      xCoords.push(gX + gm.xMin * scale);
68033      xCoords.push(gX + gm.xMax * scale);
68034      yCoords.push(gY + -gm.yMin * scale);
68035      yCoords.push(gY + -gm.yMax * scale);
68036    });
68037
68038    minX = Math.min.apply(null, xCoords);
68039    minY = Math.min.apply(null, yCoords);
68040    maxX = Math.max.apply(null, xCoords);
68041    maxY = Math.max.apply(null, yCoords);
68042
68043    result = {
68044      x: minX,
68045      y: minY,
68046      h: maxY - minY,
68047      w: maxX - minX,
68048      advance: minX - x
68049    };
68050
68051    // Bounds are now calculated, so shift the x & y to match alignment settings
68052    pos = this._handleAlignment(
68053      p,
68054      ctx,
68055      str,
68056      result.x,
68057      result.y,
68058      result.w + result.advance
68059    );
68060
68061    result.x = pos.x;
68062    result.y = pos.y;
68063
68064    this.cache[
68065      cacheKey('textBounds', str, x, y, fontSize, alignment, baseline)
68066    ] = result;
68067  }
68068
68069  return result;
68070};
68071
68072/**
68073 * Computes an array of points following the path for specified text
68074 *
68075 * @method textToPoints
68076 * @param  {String} txt     a line of text
68077 * @param  {Number} x        x-position
68078 * @param  {Number} y        y-position
68079 * @param  {Number} fontSize font size to use (optional)
68080 * @param  {Object} [options] an (optional) object that can contain:
68081 *
68082 * <br>sampleFactor - the ratio of path-length to number of samples
68083 * (default=.25); higher values yield more points and are therefore
68084 * more precise
68085 *
68086 * <br>simplifyThreshold - if set to a non-zero value, collinear points will be
68087 * be removed from the polygon; the value represents the threshold angle to use
68088 * when determining whether two edges are collinear
68089 *
68090 * @return {Array}  an array of points, each with x, y, alpha (the path angle)
68091 * @example
68092 * <div>
68093 * <code>
68094 * var font;
68095 * function preload() {
68096 *   font = loadFont('./assets/Avenir.otf');
68097 * }
68098 *
68099 * var points;
68100 * var bounds;
68101 * function setup() {
68102 *   createCanvas(100, 100);
68103 *   stroke(0);
68104 *   fill(255, 104, 204);
68105 *
68106 *   points = font.textToPoints('p5', 0, 0, 10, {
68107 *     sampleFactor: 5,
68108 *     simplifyThreshold: 0
68109 *   });
68110 *   bounds = font.textBounds(' p5 ', 0, 0, 10);
68111 * }
68112 *
68113 * function draw() {
68114 *   background(255);
68115 *   beginShape();
68116 *   translate(-bounds.x * width / bounds.w, -bounds.y * height / bounds.h);
68117 *   for (var i = 0; i < points.length; i++) {
68118 *     var p = points[i];
68119 *     vertex(
68120 *       p.x * width / bounds.w +
68121 *         sin(20 * p.y / bounds.h + millis() / 1000) * width / 30,
68122 *       p.y * height / bounds.h
68123 *     );
68124 *   }
68125 *   endShape(CLOSE);
68126 * }
68127 * </code>
68128 * </div>
68129 *
68130 */
68131p5.Font.prototype.textToPoints = function(txt, x, y, fontSize, options) {
68132  var xoff = 0,
68133    result = [],
68134    glyphs = this._getGlyphs(txt);
68135
68136  function isSpace(i) {
68137    return (
68138      (glyphs[i].name && glyphs[i].name === 'space') ||
68139      (txt.length === glyphs.length && txt[i] === ' ') ||
68140      (glyphs[i].index && glyphs[i].index === 3)
68141    );
68142  }
68143
68144  fontSize = fontSize || this.parent._renderer._textSize;
68145
68146  for (var i = 0; i < glyphs.length; i++) {
68147    if (!isSpace(i)) {
68148      // fix to #1817, #2069
68149
68150      var gpath = glyphs[i].getPath(x, y, fontSize),
68151        paths = splitPaths(gpath.commands);
68152
68153      for (var j = 0; j < paths.length; j++) {
68154        var pts = pathToPoints(paths[j], options);
68155
68156        for (var k = 0; k < pts.length; k++) {
68157          pts[k].x += xoff;
68158          result.push(pts[k]);
68159        }
68160      }
68161    }
68162
68163    xoff += glyphs[i].advanceWidth * this._scale(fontSize);
68164  }
68165
68166  return result;
68167};
68168
68169// ----------------------------- End API ------------------------------
68170
68171/**
68172 * Returns the set of opentype glyphs for the supplied string.
68173 *
68174 * Note that there is not a strict one-to-one mapping between characters
68175 * and glyphs, so the list of returned glyphs can be larger or smaller
68176 *  than the length of the given string.
68177 *
68178 * @private
68179 * @param  {String} str the string to be converted
68180 * @return {Array}     the opentype glyphs
68181 */
68182p5.Font.prototype._getGlyphs = function(str) {
68183  return this.font.stringToGlyphs(str);
68184};
68185
68186/**
68187 * Returns an opentype path for the supplied string and position.
68188 *
68189 * @private
68190 * @param  {String} line     a line of text
68191 * @param  {Number} x        x-position
68192 * @param  {Number} y        y-position
68193 * @param  {Object} options opentype options (optional)
68194 * @return {Object}     the opentype path
68195 */
68196p5.Font.prototype._getPath = function(line, x, y, options) {
68197  var p =
68198      (options && options.renderer && options.renderer._pInst) || this.parent,
68199    ctx = p._renderer.drawingContext,
68200    pos = this._handleAlignment(p, ctx, line, x, y);
68201
68202  return this.font.getPath(line, pos.x, pos.y, p._renderer._textSize, options);
68203};
68204
68205/*
68206 * Creates an SVG-formatted path-data string
68207 * (See http://www.w3.org/TR/SVG/paths.html#PathData)
68208 * from the given opentype path or string/position
68209 *
68210 * @param  {Object} path    an opentype path, OR the following:
68211 *
68212 * @param  {String} line     a line of text
68213 * @param  {Number} x        x-position
68214 * @param  {Number} y        y-position
68215 * @param  {Object} options opentype options (optional), set options.decimals
68216 * to set the decimal precision of the path-data
68217 *
68218 * @return {Object}     this p5.Font object
68219 */
68220p5.Font.prototype._getPathData = function(line, x, y, options) {
68221  var decimals = 3;
68222
68223  // create path from string/position
68224  if (typeof line === 'string' && arguments.length > 2) {
68225    line = this._getPath(line, x, y, options);
68226  } else if (typeof x === 'object') {
68227    // handle options specified in 2nd arg
68228    options = x;
68229  }
68230
68231  // handle svg arguments
68232  if (options && typeof options.decimals === 'number') {
68233    decimals = options.decimals;
68234  }
68235
68236  return line.toPathData(decimals);
68237};
68238
68239/*
68240 * Creates an SVG <path> element, as a string,
68241 * from the given opentype path or string/position
68242 *
68243 * @param  {Object} path    an opentype path, OR the following:
68244 *
68245 * @param  {String} line     a line of text
68246 * @param  {Number} x        x-position
68247 * @param  {Number} y        y-position
68248 * @param  {Object} options opentype options (optional), set options.decimals
68249 * to set the decimal precision of the path-data in the <path> element,
68250 *  options.fill to set the fill color for the <path> element,
68251 *  options.stroke to set the stroke color for the <path> element,
68252 *  options.strokeWidth to set the strokeWidth for the <path> element.
68253 *
68254 * @return {Object}     this p5.Font object
68255 */
68256p5.Font.prototype._getSVG = function(line, x, y, options) {
68257  var decimals = 3;
68258
68259  // create path from string/position
68260  if (typeof line === 'string' && arguments.length > 2) {
68261    line = this._getPath(line, x, y, options);
68262  } else if (typeof x === 'object') {
68263    // handle options specified in 2nd arg
68264    options = x;
68265  }
68266
68267  // handle svg arguments
68268  if (options) {
68269    if (typeof options.decimals === 'number') {
68270      decimals = options.decimals;
68271    }
68272    if (typeof options.strokeWidth === 'number') {
68273      line.strokeWidth = options.strokeWidth;
68274    }
68275    if (typeof options.fill !== 'undefined') {
68276      line.fill = options.fill;
68277    }
68278    if (typeof options.stroke !== 'undefined') {
68279      line.stroke = options.stroke;
68280    }
68281  }
68282
68283  return line.toSVG(decimals);
68284};
68285
68286/*
68287 * Renders an opentype path or string/position
68288 * to the current graphics context
68289 *
68290 * @param  {Object} path    an opentype path, OR the following:
68291 *
68292 * @param  {String} line     a line of text
68293 * @param  {Number} x        x-position
68294 * @param  {Number} y        y-position
68295 * @param  {Object} options opentype options (optional)
68296 *
68297 * @return {p5.Font}     this p5.Font object
68298 */
68299p5.Font.prototype._renderPath = function(line, x, y, options) {
68300  var pdata,
68301    pg = (options && options.renderer) || this.parent._renderer,
68302    ctx = pg.drawingContext;
68303
68304  if (typeof line === 'object' && line.commands) {
68305    pdata = line.commands;
68306  } else {
68307    //pos = handleAlignment(p, ctx, line, x, y);
68308    pdata = this._getPath(line, x, y, options).commands;
68309  }
68310
68311  ctx.beginPath();
68312  for (var i = 0; i < pdata.length; i += 1) {
68313    var cmd = pdata[i];
68314    if (cmd.type === 'M') {
68315      ctx.moveTo(cmd.x, cmd.y);
68316    } else if (cmd.type === 'L') {
68317      ctx.lineTo(cmd.x, cmd.y);
68318    } else if (cmd.type === 'C') {
68319      ctx.bezierCurveTo(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y);
68320    } else if (cmd.type === 'Q') {
68321      ctx.quadraticCurveTo(cmd.x1, cmd.y1, cmd.x, cmd.y);
68322    } else if (cmd.type === 'Z') {
68323      ctx.closePath();
68324    }
68325  }
68326
68327  // only draw stroke if manually set by user
68328  if (pg._doStroke && pg._strokeSet) {
68329    ctx.stroke();
68330  }
68331
68332  if (pg._doFill) {
68333    // if fill hasn't been set by user, use default-text-fill
68334    if (!pg._fillSet) {
68335      pg._setFill(constants._DEFAULT_TEXT_FILL);
68336    }
68337    ctx.fill();
68338  }
68339
68340  return this;
68341};
68342
68343p5.Font.prototype._textWidth = function(str, fontSize) {
68344  return this.font.getAdvanceWidth(str, fontSize);
68345};
68346
68347p5.Font.prototype._textAscent = function(fontSize) {
68348  return this.font.ascender * this._scale(fontSize);
68349};
68350
68351p5.Font.prototype._textDescent = function(fontSize) {
68352  return -this.font.descender * this._scale(fontSize);
68353};
68354
68355p5.Font.prototype._scale = function(fontSize) {
68356  return (
68357    1 / this.font.unitsPerEm * (fontSize || this.parent._renderer._textSize)
68358  );
68359};
68360
68361p5.Font.prototype._handleAlignment = function(p, ctx, line, x, y, textWidth) {
68362  var fontSize = p._renderer._textSize,
68363    textAscent = this._textAscent(fontSize),
68364    textDescent = this._textDescent(fontSize);
68365
68366  textWidth =
68367    textWidth !== undefined ? textWidth : this._textWidth(line, fontSize);
68368
68369  if (ctx.textAlign === constants.CENTER) {
68370    x -= textWidth / 2;
68371  } else if (ctx.textAlign === constants.RIGHT) {
68372    x -= textWidth;
68373  }
68374
68375  if (ctx.textBaseline === constants.TOP) {
68376    y += textAscent;
68377  } else if (ctx.textBaseline === constants._CTX_MIDDLE) {
68378    y += textAscent / 2;
68379  } else if (ctx.textBaseline === constants.BOTTOM) {
68380    y -= textDescent;
68381  }
68382
68383  return { x: x, y: y };
68384};
68385
68386// path-utils
68387
68388function pathToPoints(cmds, options) {
68389  var opts = parseOpts(options, {
68390    sampleFactor: 0.1,
68391    simplifyThreshold: 0
68392  });
68393
68394  var len = pointAtLength(cmds, 0, 1), // total-length
68395    t = len / (len * opts.sampleFactor),
68396    pts = [];
68397
68398  for (var i = 0; i < len; i += t) {
68399    pts.push(pointAtLength(cmds, i));
68400  }
68401
68402  if (opts.simplifyThreshold) {
68403    /*var count = */ simplify(pts, opts.simplifyThreshold);
68404    //console.log('Simplify: removed ' + count + ' pts');
68405  }
68406
68407  return pts;
68408}
68409
68410function simplify(pts, angle) {
68411  angle = typeof angle === 'undefined' ? 0 : angle;
68412
68413  var num = 0;
68414  for (var i = pts.length - 1; pts.length > 3 && i >= 0; --i) {
68415    if (collinear(at(pts, i - 1), at(pts, i), at(pts, i + 1), angle)) {
68416      // Remove the middle point
68417      pts.splice(i % pts.length, 1);
68418      num++;
68419    }
68420  }
68421  return num;
68422}
68423
68424function splitPaths(cmds) {
68425  var paths = [],
68426    current;
68427  for (var i = 0; i < cmds.length; i++) {
68428    if (cmds[i].type === 'M') {
68429      if (current) {
68430        paths.push(current);
68431      }
68432      current = [];
68433    }
68434    current.push(cmdToArr(cmds[i]));
68435  }
68436  paths.push(current);
68437
68438  return paths;
68439}
68440
68441function cmdToArr(cmd) {
68442  var arr = [cmd.type];
68443  if (cmd.type === 'M' || cmd.type === 'L') {
68444    // moveto or lineto
68445    arr.push(cmd.x, cmd.y);
68446  } else if (cmd.type === 'C') {
68447    arr.push(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y);
68448  } else if (cmd.type === 'Q') {
68449    arr.push(cmd.x1, cmd.y1, cmd.x, cmd.y);
68450  }
68451  // else if (cmd.type === 'Z') { /* no-op */ }
68452  return arr;
68453}
68454
68455function parseOpts(options, defaults) {
68456  if (typeof options !== 'object') {
68457    options = defaults;
68458  } else {
68459    for (var key in defaults) {
68460      if (typeof options[key] === 'undefined') {
68461        options[key] = defaults[key];
68462      }
68463    }
68464  }
68465  return options;
68466}
68467
68468//////////////////////// Helpers ////////////////////////////
68469
68470function at(v, i) {
68471  var s = v.length;
68472  return v[i < 0 ? i % s + s : i % s];
68473}
68474
68475function collinear(a, b, c, thresholdAngle) {
68476  if (!thresholdAngle) {
68477    return areaTriangle(a, b, c) === 0;
68478  }
68479
68480  if (typeof collinear.tmpPoint1 === 'undefined') {
68481    collinear.tmpPoint1 = [];
68482    collinear.tmpPoint2 = [];
68483  }
68484
68485  var ab = collinear.tmpPoint1,
68486    bc = collinear.tmpPoint2;
68487  ab.x = b.x - a.x;
68488  ab.y = b.y - a.y;
68489  bc.x = c.x - b.x;
68490  bc.y = c.y - b.y;
68491
68492  var dot = ab.x * bc.x + ab.y * bc.y,
68493    magA = Math.sqrt(ab.x * ab.x + ab.y * ab.y),
68494    magB = Math.sqrt(bc.x * bc.x + bc.y * bc.y),
68495    angle = Math.acos(dot / (magA * magB));
68496
68497  return angle < thresholdAngle;
68498}
68499
68500function areaTriangle(a, b, c) {
68501  return (b[0] - a[0]) * (c[1] - a[1]) - (c[0] - a[0]) * (b[1] - a[1]);
68502}
68503
68504// Portions of below code copyright 2008 Dmitry Baranovskiy (via MIT license)
68505
68506function findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {
68507  var t1 = 1 - t,
68508    t13 = Math.pow(t1, 3),
68509    t12 = Math.pow(t1, 2),
68510    t2 = t * t,
68511    t3 = t2 * t,
68512    x = t13 * p1x + t12 * 3 * t * c1x + t1 * 3 * t * t * c2x + t3 * p2x,
68513    y = t13 * p1y + t12 * 3 * t * c1y + t1 * 3 * t * t * c2y + t3 * p2y,
68514    mx = p1x + 2 * t * (c1x - p1x) + t2 * (c2x - 2 * c1x + p1x),
68515    my = p1y + 2 * t * (c1y - p1y) + t2 * (c2y - 2 * c1y + p1y),
68516    nx = c1x + 2 * t * (c2x - c1x) + t2 * (p2x - 2 * c2x + c1x),
68517    ny = c1y + 2 * t * (c2y - c1y) + t2 * (p2y - 2 * c2y + c1y),
68518    ax = t1 * p1x + t * c1x,
68519    ay = t1 * p1y + t * c1y,
68520    cx = t1 * c2x + t * p2x,
68521    cy = t1 * c2y + t * p2y,
68522    alpha = 90 - Math.atan2(mx - nx, my - ny) * 180 / Math.PI;
68523
68524  if (mx > nx || my < ny) {
68525    alpha += 180;
68526  }
68527
68528  return {
68529    x: x,
68530    y: y,
68531    m: { x: mx, y: my },
68532    n: { x: nx, y: ny },
68533    start: { x: ax, y: ay },
68534    end: { x: cx, y: cy },
68535    alpha: alpha
68536  };
68537}
68538
68539function getPointAtSegmentLength(
68540  p1x,
68541  p1y,
68542  c1x,
68543  c1y,
68544  c2x,
68545  c2y,
68546  p2x,
68547  p2y,
68548  length
68549) {
68550  return length == null
68551    ? bezlen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y)
68552    : findDotsAtSegment(
68553        p1x,
68554        p1y,
68555        c1x,
68556        c1y,
68557        c2x,
68558        c2y,
68559        p2x,
68560        p2y,
68561        getTatLen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length)
68562      );
68563}
68564
68565function pointAtLength(path, length, istotal) {
68566  path = path2curve(path);
68567  var x,
68568    y,
68569    p,
68570    l,
68571    sp = '',
68572    subpaths = {},
68573    point,
68574    len = 0;
68575  for (var i = 0, ii = path.length; i < ii; i++) {
68576    p = path[i];
68577    if (p[0] === 'M') {
68578      x = +p[1];
68579      y = +p[2];
68580    } else {
68581      l = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);
68582      if (len + l > length) {
68583        if (!istotal) {
68584          point = getPointAtSegmentLength(
68585            x,
68586            y,
68587            p[1],
68588            p[2],
68589            p[3],
68590            p[4],
68591            p[5],
68592            p[6],
68593            length - len
68594          );
68595          return { x: point.x, y: point.y, alpha: point.alpha };
68596        }
68597      }
68598      len += l;
68599      x = +p[5];
68600      y = +p[6];
68601    }
68602    sp += p.shift() + p;
68603  }
68604  subpaths.end = sp;
68605
68606  point = istotal
68607    ? len
68608    : findDotsAtSegment(x, y, p[0], p[1], p[2], p[3], p[4], p[5], 1);
68609
68610  if (point.alpha) {
68611    point = { x: point.x, y: point.y, alpha: point.alpha };
68612  }
68613
68614  return point;
68615}
68616
68617function pathToAbsolute(pathArray) {
68618  var res = [],
68619    x = 0,
68620    y = 0,
68621    mx = 0,
68622    my = 0,
68623    start = 0;
68624  if (!pathArray) {
68625    // console.warn("Unexpected state: undefined pathArray"); // shouldn't happen
68626    return res;
68627  }
68628  if (pathArray[0][0] === 'M') {
68629    x = +pathArray[0][1];
68630    y = +pathArray[0][2];
68631    mx = x;
68632    my = y;
68633    start++;
68634    res[0] = ['M', x, y];
68635  }
68636
68637  var dots,
68638    crz =
68639      pathArray.length === 3 &&
68640      pathArray[0][0] === 'M' &&
68641      pathArray[1][0].toUpperCase() === 'R' &&
68642      pathArray[2][0].toUpperCase() === 'Z';
68643
68644  for (var r, pa, i = start, ii = pathArray.length; i < ii; i++) {
68645    res.push((r = []));
68646    pa = pathArray[i];
68647    if (pa[0] !== String.prototype.toUpperCase.call(pa[0])) {
68648      r[0] = String.prototype.toUpperCase.call(pa[0]);
68649      switch (r[0]) {
68650        case 'A':
68651          r[1] = pa[1];
68652          r[2] = pa[2];
68653          r[3] = pa[3];
68654          r[4] = pa[4];
68655          r[5] = pa[5];
68656          r[6] = +(pa[6] + x);
68657          r[7] = +(pa[7] + y);
68658          break;
68659        case 'V':
68660          r[1] = +pa[1] + y;
68661          break;
68662        case 'H':
68663          r[1] = +pa[1] + x;
68664          break;
68665        case 'R':
68666          dots = [x, y].concat(pa.slice(1));
68667          for (var j = 2, jj = dots.length; j < jj; j++) {
68668            dots[j] = +dots[j] + x;
68669            dots[++j] = +dots[j] + y;
68670          }
68671          res.pop();
68672          res = res.concat(catmullRom2bezier(dots, crz));
68673          break;
68674        case 'M':
68675          mx = +pa[1] + x;
68676          my = +pa[2] + y;
68677          break;
68678        default:
68679          for (j = 1, jj = pa.length; j < jj; j++) {
68680            r[j] = +pa[j] + (j % 2 ? x : y);
68681          }
68682      }
68683    } else if (pa[0] === 'R') {
68684      dots = [x, y].concat(pa.slice(1));
68685      res.pop();
68686      res = res.concat(catmullRom2bezier(dots, crz));
68687      r = ['R'].concat(pa.slice(-2));
68688    } else {
68689      for (var k = 0, kk = pa.length; k < kk; k++) {
68690        r[k] = pa[k];
68691      }
68692    }
68693    switch (r[0]) {
68694      case 'Z':
68695        x = mx;
68696        y = my;
68697        break;
68698      case 'H':
68699        x = r[1];
68700        break;
68701      case 'V':
68702        y = r[1];
68703        break;
68704      case 'M':
68705        mx = r[r.length - 2];
68706        my = r[r.length - 1];
68707        break;
68708      default:
68709        x = r[r.length - 2];
68710        y = r[r.length - 1];
68711    }
68712  }
68713  return res;
68714}
68715
68716function path2curve(path, path2) {
68717  var p = pathToAbsolute(path),
68718    p2 = path2 && pathToAbsolute(path2);
68719  var attrs = { x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null };
68720  var attrs2 = { x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null };
68721  var pcoms1 = []; // path commands of original path p
68722  var pcoms2 = []; // path commands of original path p2
68723  var ii;
68724
68725  var processPath = function(path, d, pcom) {
68726      var nx,
68727        ny,
68728        tq = { T: 1, Q: 1 };
68729      if (!path) {
68730        return ['C', d.x, d.y, d.x, d.y, d.x, d.y];
68731      }
68732      if (!(path[0] in tq)) {
68733        d.qx = d.qy = null;
68734      }
68735      switch (path[0]) {
68736        case 'M':
68737          d.X = path[1];
68738          d.Y = path[2];
68739          break;
68740        case 'A':
68741          path = ['C'].concat(a2c.apply(0, [d.x, d.y].concat(path.slice(1))));
68742          break;
68743        case 'S':
68744          if (pcom === 'C' || pcom === 'S') {
68745            nx = d.x * 2 - d.bx;
68746            ny = d.y * 2 - d.by;
68747          } else {
68748            nx = d.x;
68749            ny = d.y;
68750          }
68751          path = ['C', nx, ny].concat(path.slice(1));
68752          break;
68753        case 'T':
68754          if (pcom === 'Q' || pcom === 'T') {
68755            d.qx = d.x * 2 - d.qx;
68756            d.qy = d.y * 2 - d.qy;
68757          } else {
68758            d.qx = d.x;
68759            d.qy = d.y;
68760          }
68761          path = ['C'].concat(q2c(d.x, d.y, d.qx, d.qy, path[1], path[2]));
68762          break;
68763        case 'Q':
68764          d.qx = path[1];
68765          d.qy = path[2];
68766          path = ['C'].concat(
68767            q2c(d.x, d.y, path[1], path[2], path[3], path[4])
68768          );
68769          break;
68770        case 'L':
68771          path = ['C'].concat(l2c(d.x, d.y, path[1], path[2]));
68772          break;
68773        case 'H':
68774          path = ['C'].concat(l2c(d.x, d.y, path[1], d.y));
68775          break;
68776        case 'V':
68777          path = ['C'].concat(l2c(d.x, d.y, d.x, path[1]));
68778          break;
68779        case 'Z':
68780          path = ['C'].concat(l2c(d.x, d.y, d.X, d.Y));
68781          break;
68782      }
68783      return path;
68784    },
68785    fixArc = function(pp, i) {
68786      if (pp[i].length > 7) {
68787        pp[i].shift();
68788        var pi = pp[i];
68789        while (pi.length) {
68790          pcoms1[i] = 'A';
68791          if (p2) {
68792            pcoms2[i] = 'A';
68793          }
68794          pp.splice(i++, 0, ['C'].concat(pi.splice(0, 6)));
68795        }
68796        pp.splice(i, 1);
68797        ii = Math.max(p.length, (p2 && p2.length) || 0);
68798      }
68799    },
68800    fixM = function(path1, path2, a1, a2, i) {
68801      if (path1 && path2 && path1[i][0] === 'M' && path2[i][0] !== 'M') {
68802        path2.splice(i, 0, ['M', a2.x, a2.y]);
68803        a1.bx = 0;
68804        a1.by = 0;
68805        a1.x = path1[i][1];
68806        a1.y = path1[i][2];
68807        ii = Math.max(p.length, (p2 && p2.length) || 0);
68808      }
68809    };
68810
68811  var pfirst = ''; // temporary holder for original path command
68812  var pcom = ''; // holder for previous path command of original path
68813
68814  ii = Math.max(p.length, (p2 && p2.length) || 0);
68815  for (var i = 0; i < ii; i++) {
68816    if (p[i]) {
68817      pfirst = p[i][0];
68818    } // save current path command
68819
68820    if (pfirst !== 'C') {
68821      pcoms1[i] = pfirst; // Save current path command
68822      if (i) {
68823        pcom = pcoms1[i - 1];
68824      } // Get previous path command pcom
68825    }
68826    p[i] = processPath(p[i], attrs, pcom);
68827
68828    if (pcoms1[i] !== 'A' && pfirst === 'C') {
68829      pcoms1[i] = 'C';
68830    }
68831
68832    fixArc(p, i);
68832 // fixArc adds also the right amount of A:s to pcoms1
68833
68834    if (p2) {
68835      // the same procedures is done to p2
68836      if (p2[i]) {
68837        pfirst = p2[i][0];
68838      }
68839      if (pfirst !== 'C') {
68840        pcoms2[i] = pfirst;
68841        if (i) {
68842          pcom = pcoms2[i - 1];
68843        }
68844      }
68845      p2[i] = processPath(p2[i], attrs2, pcom);
68846
68847      if (pcoms2[i] !== 'A' && pfirst === 'C') {
68848        pcoms2[i] = 'C';
68849      }
68850
68851      fixArc(p2, i);
68852    }
68853    fixM(p, p2, attrs, attrs2, i);
68854    fixM(p2, p, attrs2, attrs, i);
68855    var seg = p[i],
68856      seg2 = p2 && p2[i],
68857      seglen = seg.length,
68858      seg2len = p2 && seg2.length;
68859    attrs.x = seg[seglen - 2];
68860    attrs.y = seg[seglen - 1];
68861    attrs.bx = parseFloat(seg[seglen - 4]) || attrs.x;
68862    attrs.by = parseFloat(seg[seglen - 3]) || attrs.y;
68863    attrs2.bx = p2 && (parseFloat(seg2[seg2len - 4]) || attrs2.x);
68864    attrs2.by = p2 && (parseFloat(seg2[seg2len - 3]) || attrs2.y);
68865    attrs2.x = p2 && seg2[seg2len - 2];
68866    attrs2.y = p2 && seg2[seg2len - 1];
68867  }
68868
68869  return p2 ? [p, p2] : p;
68870}
68871
68872function a2c(x1, y1, rx, ry, angle, lac, sweep_flag, x2, y2, recursive) {
68873  // for more information of where this Math came from visit:
68874  // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
68875  var PI = Math.PI,
68876    _120 = PI * 120 / 180,
68877    f1,
68878    f2,
68879    cx,
68880    cy,
68881    rad = PI / 180 * (+angle || 0),
68882    res = [],
68883    xy,
68884    rotate = function(x, y, rad) {
68885      var X = x * Math.cos(rad) - y * Math.sin(rad),
68886        Y = x * Math.sin(rad) + y * Math.cos(rad);
68887      return { x: X, y: Y };
68888    };
68889  if (!recursive) {
68890    xy = rotate(x1, y1, -rad);
68891    x1 = xy.x;
68892    y1 = xy.y;
68893    xy = rotate(x2, y2, -rad);
68894    x2 = xy.x;
68895    y2 = xy.y;
68896    var x = (x1 - x2) / 2,
68897      y = (y1 - y2) / 2,
68898      h = x * x / (rx * rx) + y * y / (ry * ry);
68899    if (h > 1) {
68900      h = Math.sqrt(h);
68901      rx = h * rx;
68902      ry = h * ry;
68903    }
68904    var rx2 = rx * rx,
68905      ry2 = ry * ry;
68906    var k =
68907      (lac === sweep_flag ? -1 : 1) *
68908      Math.sqrt(
68909        Math.abs(
68910          (rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x)
68911        )
68912      );
68913
68914    cx = k * rx * y / ry + (x1 + x2) / 2;
68915    cy = k * -ry * x / rx + (y1 + y2) / 2;
68916    f1 = Math.asin(((y1 - cy) / ry).toFixed(9));
68917    f2 = Math.asin(((y2 - cy) / ry).toFixed(9));
68918
68919    f1 = x1 < cx ? PI - f1 : f1;
68920    f2 = x2 < cx ? PI - f2 : f2;
68921
68922    if (f1 < 0) {
68923      f1 = PI * 2 + f1;
68924    }
68925    if (f2 < 0) {
68926      f2 = PI * 2 + f2;
68927    }
68928
68929    if (sweep_flag && f1 > f2) {
68930      f1 = f1 - PI * 2;
68931    }
68932    if (!sweep_flag && f2 > f1) {
68933      f2 = f2 - PI * 2;
68934    }
68935  } else {
68936    f1 = recursive[0];
68937    f2 = recursive[1];
68938    cx = recursive[2];
68939    cy = recursive[3];
68940  }
68941  var df = f2 - f1;
68942  if (Math.abs(df) > _120) {
68943    var f2old = f2,
68944      x2old = x2,
68945      y2old = y2;
68946    f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1);
68947    x2 = cx + rx * Math.cos(f2);
68948    y2 = cy + ry * Math.sin(f2);
68949    res = a2c(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [
68950      f2,
68951      f2old,
68952      cx,
68953      cy
68954    ]);
68955  }
68956  df = f2 - f1;
68957  var c1 = Math.cos(f1),
68958    s1 = Math.sin(f1),
68959    c2 = Math.cos(f2),
68960    s2 = Math.sin(f2),
68961    t = Math.tan(df / 4),
68962    hx = 4 / 3 * rx * t,
68963    hy = 4 / 3 * ry * t,
68964    m1 = [x1, y1],
68965    m2 = [x1 + hx * s1, y1 - hy * c1],
68966    m3 = [x2 + hx * s2, y2 - hy * c2],
68967    m4 = [x2, y2];
68968  m2[0] = 2 * m1[0] - m2[0];
68969  m2[1] = 2 * m1[1] - m2[1];
68970  if (recursive) {
68971    return [m2, m3, m4].concat(res);
68972  } else {
68973    res = [m2, m3, m4]
68974      .concat(res)
68975      .join()
68976      .split(',');
68977    var newres = [];
68978    for (var i = 0, ii = res.length; i < ii; i++) {
68979      newres[i] =
68980        i % 2
68981          ? rotate(res[i - 1], res[i], rad).y
68982          : rotate(res[i], res[i + 1], rad).x;
68983    }
68984    return newres;
68985  }
68986}
68987
68988// http://schepers.cc/getting-to-the-point
68989function catmullRom2bezier(crp, z) {
68990  var d = [];
68991  for (var i = 0, iLen = crp.length; iLen - 2 * !z > i; i += 2) {
68992    var p = [
68993      {
68994        x: +crp[i - 2],
68995        y: +crp[i - 1]
68996      },
68997      {
68998        x: +crp[i],
68999        y: +crp[i + 1]
69000      },
69001      {
69002        x: +crp[i + 2],
69003        y: +crp[i + 3]
69004      },
69005      {
69006        x: +crp[i + 4],
69007        y: +crp[i + 5]
69008      }
69009    ];
69010    if (z) {
69011      if (!i) {
69012        p[0] = {
69013          x: +crp[iLen - 2],
69014          y: +crp[iLen - 1]
69015        };
69016      } else if (iLen - 4 === i) {
69017        p[3] = {
69018          x: +crp[0],
69019          y: +crp[1]
69020        };
69021      } else if (iLen - 2 === i) {
69022        p[2] = {
69023          x: +crp[0],
69024          y: +crp[1]
69025        };
69026        p[3] = {
69027          x: +crp[2],
69028          y: +crp[3]
69029        };
69030      }
69031    } else {
69032      if (iLen - 4 === i) {
69033        p[3] = p[2];
69034      } else if (!i) {
69035        p[0] = {
69036          x: +crp[i],
69037          y: +crp[i + 1]
69038        };
69039      }
69040    }
69041    d.push([
69042      'C',
69043      (-p[0].x + 6 * p[1].x + p[2].x) / 6,
69044      (-p[0].y + 6 * p[1].y + p[2].y) / 6,
69045      (p[1].x + 6 * p[2].x - p[3].x) / 6,
69046      (p[1].y + 6 * p[2].y - p[3].y) / 6,
69047      p[2].x,
69048      p[2].y
69049    ]);
69050  }
69051
69052  return d;
69053}
69054
69055function l2c(x1, y1, x2, y2) {
69056  return [x1, y1, x2, y2, x2, y2];
69057}
69058
69059function q2c(x1, y1, ax, ay, x2, y2) {
69060  var _13 = 1 / 3,
69061    _23 = 2 / 3;
69062  return [
69063    _13 * x1 + _23 * ax,
69064    _13 * y1 + _23 * ay,
69065    _13 * x2 + _23 * ax,
69066    _13 * y2 + _23 * ay,
69067    x2,
69068    y2
69069  ];
69070}
69071
69072function bezlen(x1, y1, x2, y2, x3, y3, x4, y4, z) {
69073  if (z == null) {
69074    z = 1;
69075  }
69076  z = z > 1 ? 1 : z < 0 ? 0 : z;
69077  var z2 = z / 2;
69078  var n = 12;
69079  var Tvalues = [
69080    -0.1252,
69081    0.1252,
69082    -0.3678,
69083    0.3678,
69084    -0.5873,
69085    0.5873,
69086    -0.7699,
69087    0.7699,
69088    -0.9041,
69089    0.9041,
69090    -0.9816,
69091    0.9816
69092  ];
69093
69094  var sum = 0;
69095  var Cvalues = [
69096    0.2491,
69097    0.2491,
69098    0.2335,
69099    0.2335,
69100    0.2032,
69101    0.2032,
69102    0.1601,
69103    0.1601,
69104    0.1069,
69105    0.1069,
69106    0.0472,
69107    0.0472
69108  ];
69109
69110  for (var i = 0; i < n; i++) {
69111    var ct = z2 * Tvalues[i] + z2,
69112      xbase = base3(ct, x1, x2, x3, x4),
69113      ybase = base3(ct, y1, y2, y3, y4),
69114      comb = xbase * xbase + ybase * ybase;
69115    sum += Cvalues[i] * Math.sqrt(comb);
69116  }
69117  return z2 * sum;
69118}
69119
69120function getTatLen(x1, y1, x2, y2, x3, y3, x4, y4, ll) {
69121  if (ll < 0 || bezlen(x1, y1, x2, y2, x3, y3, x4, y4) < ll) {
69122    return;
69123  }
69124  var t = 1,
69125    step = t / 2,
69126    t2 = t - step,
69127    l,
69128    e = 0.01;
69129  l = bezlen(x1, y1, x2, y2, x3, y3, x4, y4, t2);
69130  while (Math.abs(l - ll) > e) {
69131    step /= 2;
69132    t2 += (l < ll ? 1 : -1) * step;
69133    l = bezlen(x1, y1, x2, y2, x3, y3, x4, y4, t2);
69134  }
69135  return t2;
69136}
69137
69138function base3(t, p1, p2, p3, p4) {
69139  var t1 = -3 * p1 + 9 * p2 - 9 * p3 + 3 * p4,
69140    t2 = t * t1 + 6 * p1 - 12 * p2 + 6 * p3;
69141  return t * t2 - 3 * p1 + 3 * p2;
69142}
69143
69144function cacheKey() {
69145  var hash = '';
69146  for (var i = arguments.length - 1; i >= 0; --i) {
69147    var v = arguments[i];
69148    hash += v === Object(v) ? JSON.stringify(v) : v;
69149  }
69150  return hash;
69151}
69152
69153module.exports = p5;
69154
69155},{"../core/constants":21,"../core/core":22}],59:[function(_dereq_,module,exports){
69156/**
69157 * @module Data
69158 * @submodule Array Functions
69159 * @for p5
69160 * @requires core
69161 */
69162
69163'use strict';
69164
69165var p5 = _dereq_('../core/core');
69166
69167/**
69168 * Adds a value to the end of an array. Extends the length of
69169 * the array by one. Maps to Array.push().
69170 *
69171 * @method append
69172 * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push">array.push(value)</a> instead.
69173 * @param {Array} array Array to append
69174 * @param {any} value to be added to the Array
69175 * @example
69176 * <div class='norender'><code>
69177 * function setup() {
69178 *   var myArray = ['Mango', 'Apple', 'Papaya'];
69179 *   print(myArray); // ['Mango', 'Apple', 'Papaya']
69180 *
69181 *   append(myArray, 'Peach');
69182 *   print(myArray); // ['Mango', 'Apple', 'Papaya', 'Peach']
69183 * }
69184 * </code></div>
69185 */
69186p5.prototype.append = function(array, value) {
69187  array.push(value);
69188  return array;
69189};
69190
69191/**
69192 * Copies an array (or part of an array) to another array. The src array is
69193 * copied to the dst array, beginning at the position specified by
69194 * srcPosition and into the position specified by dstPosition. The number of
69195 * elements to copy is determined by length. Note that copying values
69196 * overwrites existing values in the destination array. To append values
69197 * instead of overwriting them, use concat().
69198 * <br><br>
69199 * The simplified version with only two arguments, arrayCopy(src, dst),
69200 * copies an entire array to another of the same size. It is equivalent to
69201 * arrayCopy(src, 0, dst, 0, src.length).
69202 * <br><br>
69203 * Using this function is far more efficient for copying array data than
69204 * iterating through a for() loop and copying each element individually.
69205 *
69206 * @method arrayCopy
69207 * @deprecated
69208 * @param {Array}  src           the source Array
69209 * @param {Integer} srcPosition  starting position in the source Array
69210 * @param {Array}  dst           the destination Array
69211 * @param {Integer} dstPosition   starting position in the destination Array
69212 * @param {Integer} length        number of Array elements to be copied
69213 *
69214 * @example
69215 * <div class='norender'><code>
69216 * var src = ['A', 'B', 'C'];
69217 * var dst = [1, 2, 3];
69218 * var srcPosition = 1;
69219 * var dstPosition = 0;
69220 * var length = 2;
69221 *
69222 * print(src); // ['A', 'B', 'C']
69223 * print(dst); // [ 1 ,  2 ,  3 ]
69224 *
69225 * arrayCopy(src, srcPosition, dst, dstPosition, length);
69226 * print(dst); // ['B', 'C', 3]
69227 * </code></div>
69228 */
69229/**
69230 * @method arrayCopy
69231 * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin">arr1.copyWithin(arr2)</a> instead.
69232 * @param {Array}  src
69233 * @param {Array}  dst
69234 * @param {Integer} [length]
69235 */
69236p5.prototype.arrayCopy = function(src, srcPosition, dst, dstPosition, length) {
69237  // the index to begin splicing from dst array
69238  var start;
69239  var end;
69240
69241  if (typeof length !== 'undefined') {
69242    end = Math.min(length, src.length);
69243    start = dstPosition;
69244    src = src.slice(srcPosition, end + srcPosition);
69245  } else {
69246    if (typeof dst !== 'undefined') {
69247      // src, dst, length
69248      // rename  so we don't get confused
69249      end = dst;
69250      end = Math.min(end, src.length);
69251    } else {
69252      // src, dst
69253      end = src.length;
69254    }
69255
69256    start = 0;
69257    // rename  so we don't get confused
69258    dst = srcPosition;
69259    src = src.slice(0, end);
69260  }
69261
69262  // Since we are not returning the array and JavaScript is pass by reference
69263  // we must modify the actual values of the array
69264  // instead of reassigning arrays
69265  Array.prototype.splice.apply(dst, [start, end].concat(src));
69266};
69267
69268/**
69269 * Concatenates two arrays, maps to Array.concat(). Does not modify the
69270 * input arrays.
69271 *
69272 * @method concat
69273 * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat">arr1.concat(arr2)</a> instead.
69274 * @param {Array} a first Array to concatenate
69275 * @param {Array} b second Array to concatenate
69276 * @return {Array} concatenated array
69277 *
69278 * @example
69279 * <div class = 'norender'><code>
69280 * function setup() {
69281 *   var arr1 = ['A', 'B', 'C'];
69282 *   var arr2 = [1, 2, 3];
69283 *
69284 *   print(arr1); // ['A','B','C']
69285 *   print(arr2); // [1,2,3]
69286 *
69287 *   var arr3 = concat(arr1, arr2);
69288 *
69289 *   print(arr1); // ['A','B','C']
69290 *   print(arr2); // [1, 2, 3]
69291 *   print(arr3); // ['A','B','C', 1, 2, 3]
69292 * }
69293 * </code></div>
69294 */
69295p5.prototype.concat = function(list0, list1) {
69296  return list0.concat(list1);
69297};
69298
69299/**
69300 * Reverses the order of an array, maps to Array.reverse()
69301 *
69302 * @method reverse
69303 * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse">array.reverse()</a> instead.
69304 * @param {Array} list Array to reverse
69305 * @example
69306 * <div class='norender'><code>
69307 * function setup() {
69308 *   var myArray = ['A', 'B', 'C'];
69309 *   print(myArray); // ['A','B','C']
69310 *
69311 *   reverse(myArray);
69312 *   print(myArray); // ['C','B','A']
69313 * }
69314 * </code></div>
69315 */
69316p5.prototype.reverse = function(list) {
69317  return list.reverse();
69318};
69319
69320/**
69321 * Decreases an array by one element and returns the shortened array,
69322 * maps to Array.pop().
69323 *
69324 * @method shorten
69325 * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/pop">array.pop()</a> instead.
69326 * @param  {Array} list Array to shorten
69327 * @return {Array} shortened Array
69328 * @example
69329 * <div class = 'norender'><code>
69330 * function setup() {
69331 *   var myArray = ['A', 'B', 'C'];
69332 *   print(myArray); // ['A', 'B', 'C']
69333 *   var newArray = shorten(myArray);
69334 *   print(myArray); // ['A','B','C']
69335 *   print(newArray); // ['A','B']
69336 * }
69337 * </code></div>
69338 */
69339p5.prototype.shorten = function(list) {
69340  list.pop();
69341  return list;
69342};
69343
69344/**
69345 * Randomizes the order of the elements of an array. Implements
69346 * <a href='http://Bost.Ocks.org/mike/shuffle/' target=_blank>
69347 * Fisher-Yates Shuffle Algorithm</a>.
69348 *
69349 * @method shuffle
69350 * @deprecated See <a href="https://stackoverflow.com/questions/6274339/how-can-i-shuffle-an-array">shuffling an array with JS</a> instead.
69351 * @param  {Array}   array  Array to shuffle
69352 * @param  {Boolean} [bool] modify passed array
69353 * @return {Array}   shuffled Array
69354 * @example
69355 * <div><code>
69356 * function setup() {
69357 *   var regularArr = ['ABC', 'def', createVector(), TAU, Math.E];
69358 *   print(regularArr);
69359 *   shuffle(regularArr, true); // force modifications to passed array
69360 *   print(regularArr);
69361 *
69362 *   // By default shuffle() returns a shuffled cloned array:
69363 *   var newArr = shuffle(regularArr);
69364 *   print(regularArr);
69365 *   print(newArr);
69366 * }
69367 * </code></div>
69368 */
69369p5.prototype.shuffle = function(arr, bool) {
69370  var isView = ArrayBuffer && ArrayBuffer.isView && ArrayBuffer.isView(arr);
69371  arr = bool || isView ? arr : arr.slice();
69372
69373  var rnd,
69374    tmp,
69375    idx = arr.length;
69376  while (idx > 1) {
69377    rnd = (Math.random() * idx) | 0;
69378
69379    tmp = arr[--idx];
69380    arr[idx] = arr[rnd];
69381    arr[rnd] = tmp;
69382  }
69383
69384  return arr;
69385};
69386
69387/**
69388 * Sorts an array of numbers from smallest to largest, or puts an array of
69389 * words in alphabetical order. The original array is not modified; a
69390 * re-ordered array is returned. The count parameter states the number of
69391 * elements to sort. For example, if there are 12 elements in an array and
69392 * count is set to 5, only the first 5 elements in the array will be sorted.
69393 *
69394 * @method sort
69395 * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort">array.sort()</a> instead.
69396 * @param {Array} list Array to sort
69397 * @param {Integer} [count] number of elements to sort, starting from 0
69398 *
69399 * @example
69400 * <div class = 'norender'><code>
69401 * function setup() {
69402 *   var words = ['banana', 'apple', 'pear', 'lime'];
69403 *   print(words); // ['banana', 'apple', 'pear', 'lime']
69404 *   var count = 4; // length of array
69405 *
69406 *   words = sort(words, count);
69407 *   print(words); // ['apple', 'banana', 'lime', 'pear']
69408 * }
69409 * </code></div>
69410 * <div class = 'norender'><code>
69411 * function setup() {
69412 *   var numbers = [2, 6, 1, 5, 14, 9, 8, 12];
69413 *   print(numbers); // [2, 6, 1, 5, 14, 9, 8, 12]
69414 *   var count = 5; // Less than the length of the array
69415 *
69416 *   numbers = sort(numbers, count);
69417 *   print(numbers); // [1,2,5,6,14,9,8,12]
69418 * }
69419 * </code></div>
69420 */
69421p5.prototype.sort = function(list, count) {
69422  var arr = count ? list.slice(0, Math.min(count, list.length)) : list;
69423  var rest = count ? list.slice(Math.min(count, list.length)) : [];
69424  if (typeof arr[0] === 'string') {
69425    arr = arr.sort();
69426  } else {
69427    arr = arr.sort(function(a, b) {
69428      return a - b;
69429    });
69430  }
69431  return arr.concat(rest);
69432};
69433
69434/**
69435 * Inserts a value or an array of values into an existing array. The first
69436 * parameter specifies the initial array to be modified, and the second
69437 * parameter defines the data to be inserted. The third parameter is an index
69438 * value which specifies the array position from which to insert data.
69439 * (Remember that array index numbering starts at zero, so the first position
69440 * is 0, the second position is 1, and so on.)
69441 *
69442 * @method splice
69443 * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice">array.splice()</a> instead.
69444 * @param {Array}  list Array to splice into
69445 * @param {any}    value value to be spliced in
69446 * @param {Integer} position in the array from which to insert data
69447 *
69448 * @example
69449 * <div class = 'norender'><code>
69450 * function setup() {
69451 *   var myArray = [0, 1, 2, 3, 4];
69452 *   var insArray = ['A', 'B', 'C'];
69453 *   print(myArray); // [0, 1, 2, 3, 4]
69454 *   print(insArray); // ['A','B','C']
69455 *
69456 *   splice(myArray, insArray, 3);
69457 *   print(myArray); // [0,1,2,'A','B','C',3,4]
69458 * }
69459 * </code></div>
69460 */
69461p5.prototype.splice = function(list, value, index) {
69462  // note that splice returns spliced elements and not an array
69463  Array.prototype.splice.apply(list, [index, 0].concat(value));
69464
69465  return list;
69466};
69467
69468/**
69469 * Extracts an array of elements from an existing array. The list parameter
69470 * defines the array from which the elements will be copied, and the start
69471 * and count parameters specify which elements to extract. If no count is
69472 * given, elements will be extracted from the start to the end of the array.
69473 * When specifying the start, remember that the first array element is 0.
69474 * This function does not change the source array.
69475 *
69476 * @method subset
69477 * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice">array.slice()</a> instead.
69478 * @param  {Array}  list    Array to extract from
69479 * @param  {Integer} start   position to begin
69480 * @param  {Integer} [count] number of values to extract
69481 * @return {Array}          Array of extracted elements
69482 *
69483 * @example
69484 * <div class = 'norender'><code>
69485 * function setup() {
69486 *   var myArray = [1, 2, 3, 4, 5];
69487 *   print(myArray); // [1, 2, 3, 4, 5]
69488 *
69489 *   var sub1 = subset(myArray, 0, 3);
69490 *   var sub2 = subset(myArray, 2, 2);
69491 *   print(sub1); // [1,2,3]
69492 *   print(sub2); // [3,4]
69493 * }
69494 * </code></div>
69495 */
69496p5.prototype.subset = function(list, start, count) {
69497  if (typeof count !== 'undefined') {
69498    return list.slice(start, start + count);
69499  } else {
69500    return list.slice(start, list.length);
69501  }
69502};
69503
69504module.exports = p5;
69505
69506},{"../core/core":22}],60:[function(_dereq_,module,exports){
69507/**
69508 * @module Data
69509 * @submodule Conversion
69510 * @for p5
69511 * @requires core
69512 */
69513
69514'use strict';
69515
69516var p5 = _dereq_('../core/core');
69517
69518/**
69519 * Converts a string to its floating point representation. The contents of a
69520 * string must resemble a number, or NaN (not a number) will be returned.
69521 * For example, float("1234.56") evaluates to 1234.56, but float("giraffe")
69522 * will return NaN.
69523 *
69524 * When an array of values is passed in, then an array of floats of the same
69525 * length is returned.
69526 *
69527 * @method float
69528 * @param {String}  str float string to parse
69529 * @return {Number}
69529     floating point representation of string
69530 * @example
69531 * <div><code>
69532 * var str = '20';
69533 * var diameter = float(str);
69534 * ellipse(width / 2, height / 2, diameter, diameter);
69535 * </code></div>
69536 *
69537 * @alt
69538 * 20 by 20 white ellipse in the center of the canvas
69539 *
69540 */
69541p5.prototype.float = function(str) {
69542  if (str instanceof Array) {
69543    return str.map(parseFloat);
69544  }
69545  return parseFloat(str);
69546};
69547
69548/**
69549 * Converts a boolean, string, or float to its integer representation.
69550 * When an array of values is passed in, then an int array of the same length
69551 * is returned.
69552 *
69553 * @method int
69554 * @param {String|Boolean|Number}       n value to parse
69555 * @param {Integer}       [radix] the radix to convert to (default: 10)
69556 * @return {Number}                     integer representation of value
69557 *
69558 * @example
69559 * <div class='norender'><code>
69560 * print(int('10')); // 10
69561 * print(int(10.31)); // 10
69562 * print(int(-10)); // -10
69563 * print(int(true)); // 1
69564 * print(int(false)); // 0
69565 * print(int([false, true, '10.3', 9.8])); // [0, 1, 10, 9]
69566 * </code></div>
69567 */
69568/**
69569 * @method int
69570 * @param {Array} ns                    values to parse
69571 * @return {Number[]}                   integer representation of values
69572 */
69573p5.prototype.int = function(n, radix) {
69574  radix = radix || 10;
69575  if (typeof n === 'string') {
69576    return parseInt(n, radix);
69577  } else if (typeof n === 'number') {
69578    return n | 0;
69579  } else if (typeof n === 'boolean') {
69580    return n ? 1 : 0;
69581  } else if (n instanceof Array) {
69582    return n.map(function(n) {
69583      return p5.prototype.int(n, radix);
69584    });
69585  }
69586};
69587
69588/**
69589 * Converts a boolean, string or number to its string representation.
69590 * When an array of values is passed in, then an array of strings of the same
69591 * length is returned.
69592 *
69593 * @method str
69594 * @param {String|Boolean|Number|Array} n value to parse
69595 * @return {String}                     string representation of value
69596 * @example
69597 * <div class='norender'><code>
69598 * print(str('10')); // "10"
69599 * print(str(10.31)); // "10.31"
69600 * print(str(-10)); // "-10"
69601 * print(str(true)); // "true"
69602 * print(str(false)); // "false"
69603 * print(str([true, '10.3', 9.8])); // [ "true", "10.3", "9.8" ]
69604 * </code></div>
69605 */
69606p5.prototype.str = function(n) {
69607  if (n instanceof Array) {
69608    return n.map(p5.prototype.str);
69609  } else {
69610    return String(n);
69611  }
69612};
69613
69614/**
69615 * Converts a number or string to its boolean representation.
69616 * For a number, any non-zero value (positive or negative) evaluates to true,
69617 * while zero evaluates to false. For a string, the value "true" evaluates to
69618 * true, while any other value evaluates to false. When an array of number or
69619 * string values is passed in, then a array of booleans of the same length is
69620 * returned.
69621 *
69622 * @method boolean
69623 * @param {String|Boolean|Number|Array} n value to parse
69624 * @return {Boolean}                    boolean representation of value
69625 * @example
69626 * <div class='norender'><code>
69627 * print(boolean(0)); // false
69628 * print(boolean(1)); // true
69629 * print(boolean('true')); // true
69630 * print(boolean('abcd')); // false
69631 * print(boolean([0, 12, 'true'])); // [false, true, false]
69632 * </code></div>
69633 */
69634p5.prototype.boolean = function(n) {
69635  if (typeof n === 'number') {
69636    return n !== 0;
69637  } else if (typeof n === 'string') {
69638    return n.toLowerCase() === 'true';
69639  } else if (typeof n === 'boolean') {
69640    return n;
69641  } else if (n instanceof Array) {
69642    return n.map(p5.prototype.boolean);
69643  }
69644};
69645
69646/**
69647 * Converts a number, string representation of a number, or boolean to its byte
69648 * representation. A byte can be only a whole number between -128 and 127, so
69649 * when a value outside of this range is converted, it wraps around to the
69650 * corresponding byte representation. When an array of number, string or boolean
69651 * values is passed in, then an array of bytes the same length is returned.
69652 *
69653 * @method byte
69654 * @param {String|Boolean|Number}       n value to parse
69655 * @return {Number}                     byte representation of value
69656 *
69657 * @example
69658 * <div class='norender'><code>
69659 * print(byte(127)); // 127
69660 * print(byte(128)); // -128
69661 * print(byte(23.4)); // 23
69662 * print(byte('23.4')); // 23
69663 * print(byte('hello')); // NaN
69664 * print(byte(true)); // 1
69665 * print(byte([0, 255, '100'])); // [0, -1, 100]
69666 * </code></div>
69667 */
69668/**
69669 * @method byte
69670 * @param {Array} ns                   values to parse
69671 * @return {Number[]}                  array of byte representation of values
69672 */
69673p5.prototype.byte = function(n) {
69674  var nn = p5.prototype.int(n, 10);
69675  if (typeof nn === 'number') {
69676    return (nn + 128) % 256 - 128;
69677  } else if (nn instanceof Array) {
69678    return nn.map(p5.prototype.byte);
69679  }
69680};
69681
69682/**
69683 * Converts a number or string to its corresponding single-character
69684 * string representation. If a string parameter is provided, it is first
69685 * parsed as an integer and then translated into a single-character string.
69686 * When an array of number or string values is passed in, then an array of
69687 * single-character strings of the same length is returned.
69688 *
69689 * @method char
69690 * @param {String|Number}       n value to parse
69691 * @return {String}
69691             string representation of value
69692 *
69693 * @example
69694 * <div class='norender'><code>
69695 * print(char(65)); // "A"
69696 * print(char('65')); // "A"
69697 * print(char([65, 66, 67])); // [ "A", "B", "C" ]
69698 * print(join(char([65, 66, 67]), '')); // "ABC"
69699 * </code></div>
69700 */
69701/**
69702 * @method char
69703 * @param {Array} ns              values to parse
69704 * @return {String[]}             array of string representation of values
69705 */
69706p5.prototype.char = function(n) {
69707  if (typeof n === 'number' && !isNaN(n)) {
69708    return String.fromCharCode(n);
69709  } else if (n instanceof Array) {
69710    return n.map(p5.prototype.char);
69711  } else if (typeof n === 'string') {
69712    return p5.prototype.char(parseInt(n, 10));
69713  }
69714};
69715
69716/**
69717 * Converts a single-character string to its corresponding integer
69718 * representation. When an array of single-character string values is passed
69719 * in, then an array of integers of the same length is returned.
69720 *
69721 * @method unchar
69722 * @param {String} n     value to parse
69723 * @return {Number}      integer representation of value
69724 *
69725 * @example
69726 * <div class='norender'><code>
69727 * print(unchar('A')); // 65
69728 * print(unchar(['A', 'B', 'C'])); // [ 65, 66, 67 ]
69729 * print(unchar(split('ABC', ''))); // [ 65, 66, 67 ]
69730 * </code></div>
69731 */
69732/**
69733 * @method unchar
69734 * @param {Array} ns       values to parse
69735 * @return {Number[]}      integer representation of values
69736 */
69737p5.prototype.unchar = function(n) {
69738  if (typeof n === 'string' && n.length === 1) {
69739    return n.charCodeAt(0);
69740  } else if (n instanceof Array) {
69741    return n.map(p5.prototype.unchar);
69742  }
69743};
69744
69745/**
69746 * Converts a number to a string in its equivalent hexadecimal notation. If a
69747 * second parameter is passed, it is used to set the number of characters to
69748 * generate in the hexadecimal notation. When an array is passed in, an
69749 * array of strings in hexadecimal notation of the same length is returned.
69750 *
69751 * @method hex
69752 * @param {Number} n     value to parse
69753 * @param {Number} [digits]
69754 * @return {String}      hexadecimal string representation of value
69755 *
69756 * @example
69757 * <div class='norender'><code>
69758 * print(hex(255)); // "000000FF"
69759 * print(hex(255, 6)); // "0000FF"
69760 * print(hex([0, 127, 255], 6)); // [ "000000", "00007F", "0000FF" ]
69761 * </code></div>
69762 */
69763/**
69764 * @method hex
69765 * @param {Number[]} ns    array of values to parse
69766 * @param {Number} [digits]
69767 * @return {String[]}      hexadecimal string representation of values
69768 */
69769p5.prototype.hex = function(n, digits) {
69770  digits = digits === undefined || digits === null ? (digits = 8) : digits;
69771  if (n instanceof Array) {
69772    return n.map(function(n) {
69773      return p5.prototype.hex(n, digits);
69774    });
69775  } else if (typeof n === 'number') {
69776    if (n < 0) {
69777      n = 0xffffffff + n + 1;
69778    }
69779    var hex = Number(n)
69780      .toString(16)
69781      .toUpperCase();
69782    while (hex.length < digits) {
69783      hex = '0' + hex;
69784    }
69785    if (hex.length >= digits) {
69786      hex = hex.substring(hex.length - digits, hex.length);
69787    }
69788    return hex;
69789  }
69790};
69791
69792/**
69793 * Converts a string representation of a hexadecimal number to its equivalent
69794 * integer value. When an array of strings in hexadecimal notation is passed
69795 * in, an array of integers of the same length is returned.
69796 *
69797 * @method unhex
69798 * @param {String} n value to parse
69799 * @return {Number}      integer representation of hexadecimal value
69800 *
69801 * @example
69802 * <div class='norender'><code>
69803 * print(unhex('A')); // 10
69804 * print(unhex('FF')); // 255
69805 * print(unhex(['FF', 'AA', '00'])); // [ 255, 170, 0 ]
69806 * </code></div>
69807 */
69808/**
69809 * @method unhex
69810 * @param {Array} ns values to parse
69811 * @return {Number[]}      integer representations of hexadecimal value
69812 */
69813p5.prototype.unhex = function(n) {
69814  if (n instanceof Array) {
69815    return n.map(p5.prototype.unhex);
69816  } else {
69817    return parseInt('0x' + n, 16);
69818  }
69819};
69820
69821module.exports = p5;
69822
69823},{"../core/core":22}],61:[function(_dereq_,module,exports){
69824/**
69825 * @module Data
69826 * @submodule String Functions
69827 * @for p5
69828 * @requires core
69829 */
69830
69831'use strict';
69832
69833var p5 = _dereq_('../core/core');
69834_dereq_('../core/error_helpers');
69835
69836//return p5; //LM is this a mistake?
69837
69838/**
69839 * Combines an array of Strings into one String, each separated by the
69840 * character(s) used for the separator parameter. To join arrays of ints or
69841 * floats, it's necessary to first convert them to Strings using nf() or
69842 * nfs().
69843 *
69844 * @method join
69845 * @param  {Array}  list      array of Strings to be joined
69846 * @param  {String} separator String to be placed between each item
69847 * @return {String}           joined String
69848 * @example
69849 * <div>
69850 * <code>
69851 * var array = ['Hello', 'world!'];
69852 * var separator = ' ';
69853 * var message = join(array, separator);
69854 * text(message, 5, 50);
69855 * </code>
69856 * </div>
69857 *
69858 * @alt
69859 * "hello world!" displayed middle left of canvas.
69860 *
69861 */
69862p5.prototype.join = function(list, separator) {
69863  p5._validateParameters('join', arguments);
69864  return list.join(separator);
69865};
69866
69867/**
69868 * This function is used to apply a regular expression to a piece of text,
69869 * and return matching groups (elements found inside parentheses) as a
69870 * String array. If there are no matches, a null value will be returned.
69871 * If no groups are specified in the regular expression, but the sequence
69872 * matches, an array of length 1 (with the matched text as the first element
69873 * of the array) will be returned.
69874 * <br><br>
69875 * To use the function, first check to see if the result is null. If the
69876 * result is null, then the sequence did not match at all. If the sequence
69877 * did match, an array is returned.
69878 * <br><br>
69879 * If there are groups (specified by sets of parentheses) in the regular
69880 * expression, then the contents of each will be returned in the array.
69881 * Element [0] of a regular expression match returns the entire matching
69882 * string, and the match groups start at element [1] (the first group is [1],
69883 * the second [2], and so on).
69884 *
69885 * @method match
69886 * @param  {String} str    the String to be searched
69887 * @param  {String} regexp the regexp to be used for matching
69888 * @return {String[]}      Array of Strings found
69889 * @example
69890 * <div>
69891 * <code>
69892 * var string = 'Hello p5js*!';
69893 * var regexp = 'p5js\\*';
69894 * var m = match(string, regexp);
69895 * text(m, 5, 50);
69896 * </code>
69897 * </div>
69898 *
69899 * @alt
69900 * "p5js*" displayed middle left of canvas.
69901 *
69902 */
69903p5.prototype.match = function(str, reg) {
69904  p5._validateParameters('match', arguments);
69905  return str.match(reg);
69906};
69907
69908/**
69909 * This function is used to apply a regular expression to a piece of text,
69910 * and return a list of matching groups (elements found inside parentheses)
69911 * as a two-dimensional String array. If there are no matches, a null value
69912 * will be returned. If no groups are specified in the regular expression,
69913 * but the sequence matches, a two dimensional array is still returned, but
69914 * the second dimension is only of length one.
69915 * <br><br>
69916 * To use the function, first check to see if the result is null. If the
69917 * result is null, then the sequence did not match at all. If the sequence
69918 * did match, a 2D array is returned.
69919 * <br><br>
69920 * If there are groups (specified by sets of parentheses) in the regular
69921 * expression, then the contents of each will be returned in the array.
69922 * Assuming a loop with counter variable i, element [i][0] of a regular
69923 * expression match returns the entire matching string, and the match groups
69924 * start at element [i][1] (the first group is [i][1], the second [i][2],
69925 * and so on).
69926 *
69927 * @method matchAll
69928 * @param  {String} str    the String to be searched
69929 * @param  {String} regexp the regexp to be used for matching
69930 * @return {String[]}         2d Array of Strings found
69931 * @example
69932 * <div class="norender">
69933 * <code>
69934 * var string = 'Hello p5js*! Hello world!';
69935 * var regexp = 'Hello';
69936 * matchAll(string, regexp);
69937 * </code>
69938 * </div>
69939 */
69940p5.prototype.matchAll = function(str, reg) {
69941  p5._validateParameters('matchAll', arguments);
69942  var re = new RegExp(reg, 'g');
69943  var match = re.exec(str);
69944  var matches = [];
69945  while (match !== null) {
69946    matches.push(match);
69947    // matched text: match[0]
69948    // match start: match.index
69949    // capturing group n: match[n]
69950    match = re.exec(str);
69951  }
69952  return matches;
69953};
69954
69955/**
69956 * Utility function for formatting numbers into strings. There are two
69957 * versions: one for formatting floats, and one for formatting ints.
69958 * The values for the digits, left, and right parameters should always
69959 * be positive integers.
69960 *
69961 * @method nf
69962 * @param {Number|String}       num      the Number to format
69963 * @param {Integer|String}      [left]   number of digits to the left of the
69964 *                                decimal point
69965 * @param {Integer|String}      [right]  number of digits to the right of the
69966 *                                decimal point
69967 * @return {String}               formatted String
69968 *
69969 * @example
69970 * <div>
69971 * <code>
69972 * function setup() {
69973 *   background(200);
69974 *   var num = 112.53106115;
69975 *
69976 *   noStroke();
69977 *   fill(0);
69978 *   textSize(14);
69979 *   // Draw formatted numbers
69980 *   text(nf(num, 5, 2), 10, 20);
69981 *
69982 *   text(nf(num, 4, 3), 10, 55);
69983 *
69984 *   text(nf(num, 3, 6), 10, 85);
69985 *
69986 *   // Draw dividing lines
69987 *   stroke(120);
69988 *   line(0, 30, width, 30);
69989 *   line(0, 65, width, 65);
69990 * }
69991 * </code>
69992 * </div>
69993 *
69994 * @alt
69995 * "0011253" top left, "0112.531" mid left, "112.531061" bottom left canvas
69996 */
69997/**
69998 * @method nf
69999 * @param {Array}        nums     the Numbers to format
70000 * @param {Integer|String}      [left]
70001 * @param {Integer|String}      [right]
70002 * @return {String[]}                formatted Strings
70003 */
70004p5.prototype.nf = function(nums, left, right) {
70005  p5._validateParameters('nf', arguments);
70006  if (nums instanceof Array) {
70007    return nums.map(function(x) {
70008      return doNf(x, left, right);
70009    });
70010  } else {
70011    var typeOfFirst = Object.prototype.toString.call(nums);
70012    if (typeOfFirst === '[object Arguments]') {
70013      if (nums.length === 3) {
70014        return this.nf(nums[0], nums[1], nums[2]);
70015      } else if (nums.length === 2) {
70016        return this.nf(nums[0], nums[1]);
70017      } else {
70018        return this.nf(nums[0]);
70019      }
70020    } else {
70021      return doNf(nums, left, right);
70022    }
70023  }
70024};
70025
70026function doNf(num, left, right) {
70027  var neg = num < 0;
70028  var n = neg ? num.toString().substring(1) : num.toString();
70029  var decimalInd = n.indexOf('.');
70030  var intPart = decimalInd !== -1 ? n.substring(0, decimalInd) : n;
70031  var decPart = decimalInd !== -1 ? n.substring(decimalInd + 1) : '';
70032  var str = neg ? '-' : '';
70033  if (typeof right !== 'undefined') {
70034    var decimal = '';
70035    if (decimalInd !== -1 || right - decPart.length > 0) {
70036      decimal = '.';
70037    }
70038    if (decPart.length > right) {
70039      decPart = decPart.substring(0, right);
70040    }
70041    for (var i = 0; i < left - intPart.length; i++) {
70042      str += '0';
70043    }
70044    str += intPart;
70045    str += decimal;
70046    str += decPart;
70047    for (var j = 0; j < right - decPart.length; j++) {
70048      str += '0';
70049    }
70050    return str;
70051  } else {
70052    for (var k = 0; k < Math.max(left - intPart.length, 0); k++) {
70053      str += '0';
70054    }
70055    str += n;
70056    return str;
70057  }
70058}
70059
70060/**
70061 * Utility function for formatting numbers into strings and placing
70062 * appropriate commas to mark units of 1000. There are two versions: one
70063 * for formatting ints, and one for formatting an array of ints. The value
70064 * for the right parameter should always be a positive integer.
70065 *
70066 * @method nfc
70067 * @param  {Number|String}   num     the Number to format
70068 * @param  {Integer|String}  [right] number of digits to the right of the
70069 *                                  decimal point
70070 * @return {String}           formatted String
70071 *
70072 * @example
70073 * <div>
70074 * <code>
70075 * function setup() {
70076 *   background(200);
70077 *   var num = 11253106.115;
70078 *   var numArr = [1, 1, 2];
70079 *
70080 *   noStroke();
70081 *   fill(0);
70082 *   textSize(12);
70083 *
70084 *   // Draw formatted numbers
70085 *   text(nfc(num, 4), 10, 30);
70086 *   text(nfc(numArr, 2), 10, 80);
70087 *
70088 *   // Draw dividing line
70089 *   stroke(120);
70090 *   line(0, 50, width, 50);
70091 * }
70092 * </code>
70093 * </div>
70094 *
70095 * @alt
70096 * "11,253,106.115" top middle and "1.00,1.00,2.00" displayed bottom mid
70097 */
70098/**
70099 * @method nfc
70100 * @param  {Array}    nums     the Numbers to format
70101 * @param  {Integer|String}  [right]
70102 * @return {String[]}           formatted Strings
70103 */
70104p5.prototype.nfc = function(num, right) {
70105  p5._validateParameters('nfc', arguments);
70106  if (num instanceof Array) {
70107    return num.map(function(x) {
70108      return doNfc(x, right);
70109    });
70110  } else {
70111    return doNfc(num, right);
70112  }
70113};
70114function doNfc(num, right) {
70115  num = num.toString();
70116  var dec = num.indexOf('.');
70117  var rem = dec !== -1 ? num.substring(dec) : '';
70118  var n = dec !== -1 ? num.substring(0, dec) : num;
70119  n = n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
70120  if (right === 0) {
70121    rem = '';
70122  } else if (typeof right !== 'undefined') {
70123    if (right > rem.length) {
70124      rem += dec === -1 ? '.' : '';
70125      var len = right - rem.length + 1;
70126      for (var i = 0; i < len; i++) {
70127        rem += '0';
70128      }
70129    } else {
70130      rem = rem.substring(0, right + 1);
70131    }
70132  }
70133  return n + rem;
70134}
70135
70136/**
70137 * Utility function for formatting numbers into strings. Similar to nf() but
70138 * puts a "+" in front of positive numbers and a "-" in front of negative
70139 * numbers. There are two versions: one for formatting floats, and one for
70140 * formatting ints. The values for left, and right parameters
70141 * should always be positive integers.
70142 *
70143 * @method nfp
70144 * @param {Number} num      the Number to format
70145 * @param {Integer}      [left]   number of digits to the left of the decimal
70146 *                                point
70147 * @param {Integer}      [right]  number of digits to the right of the
70148 *                                decimal point
70149 * @return {String}         formatted String
70150 *
70151 * @example
70152 * <div>
70153 * <code>
70154 * function setup() {
70155 *   background(200);
70156 *   var num1 = 11253106.115;
70157 *   var num2 = -11253106.115;
70158 *
70159 *   noStroke();
70160 *   fill(0);
70161 *   textSize(12);
70162 *
70163 *   // Draw formatted numbers
70164 *   text(nfp(num1, 4, 2), 10, 30);
70165 *   text(nfp(num2, 4, 2), 10, 80);
70166 *
70167 *   // Draw dividing line
70168 *   stroke(120);
70169 *   line(0, 50, width, 50);
70170 * }
70171 * </code>
70172 * </div>
70173 *
70174 * @alt
70175 * "+11253106.11" top middle and "-11253106.11" displayed bottom middle
70176 */
70177/**
70178 * @method nfp
70179 * @param {Number[]} nums      the Numbers to format
70180 * @param {Integer}      [left]
70181 * @param {Integer}      [right]
70182 * @return {String[]}         formatted Strings
70183 */
70184p5.prototype.nfp = function() {
70185  p5._validateParameters('nfp', arguments);
70186  var nfRes = p5.prototype.nf.apply(this, arguments);
70187  if (nfRes instanceof Array) {
70188    return nfRes.map(addNfp);
70189  } else {
70190    return addNfp(nfRes);
70191  }
70192};
70193
70194function addNfp(num) {
70195  return parseFloat(num) > 0 ? '+' + num.toString() : num.toString();
70196}
70197
70198/**
70199 * Utility function for formatting numbers into strings. Similar to nf() but
70200 * puts a " " (space) in front of positive numbers and a "-" in front of
70201 * negative numbers. There are two versions: one for formatting floats, and
70202 * one for formatting ints. The values for the digits, left, and right
70203 * parameters should always be positive integers.
70204 *
70205 * @method nfs
70206 * @param {Number}       num      the Number to format
70207 * @param {Integer}      [left]   number of digits to the left of the decimal
70208 *                                point
70209 * @param {Integer}      [right]  number of digits to the right of the
70210 *                                decimal point
70211 * @return {String}         formatted String
70212 *
70213 * @example
70214 * <div>
70215 * <code>
70216 * function setup() {
70217 *   background(200);
70218 *   var num1 = 11253106.115;
70219 *   var num2 = -11253106.115;
70220 *
70221 *   noStroke();
70222 *   fill(0);
70223 *   textSize(12);
70224 *   // Draw formatted numbers
70225 *   text(nfs(num1, 4, 2), 10, 30);
70226 *
70227 *   text(nfs(num2, 4, 2), 10, 80);
70228 *
70229 *   // Draw dividing line
70230 *   stroke(120);
70231 *   line(0, 50, width, 50);
70232 * }
70233 * </code>
70234 * </div>
70235 *
70236 * @alt
70237 * "11253106.11" top middle and "-11253106.11" displayed bottom middle
70238 */
70239/**
70240 * @method nfs
70241 * @param {Array}        nums     the Numbers to format
70242 * @param {Integer}      [left]
70243 * @param {Integer}      [right]
70244 * @return {String[]}         formatted Strings
70245 */
70246p5.prototype.nfs = function() {
70247  p5._validateParameters('nfs', arguments);
70248  var nfRes = p5.prototype.nf.apply(this, arguments);
70249  if (nfRes instanceof Array) {
70250    return nfRes.map(addNfs);
70251  } else {
70252    return addNfs(nfRes);
70253  }
70254};
70255
70256function addNfs(num) {
70257  return parseFloat(num) > 0 ? ' ' + num.toString() : num.toString();
70258}
70259
70260/**
70261 * The split() function maps to String.split(), it breaks a String into
70262 * pieces using a character or string as the delimiter. The delim parameter
70263 * specifies the character or characters that mark the boundaries between
70264 * each piece. A String[] array is returned that contains each of the pieces.
70265 *
70266 * The splitTokens() function works in a similar fashion, except that it
70267 * splits using a range of characters instead of a specific character or
70268 * sequence.
70269 *
70270 * @method split
70271 * @param  {String} value the String to be split
70272 * @param  {String} delim the String used to separate the data
70273 * @return {String[]}  Array of Strings
70274 * @example
70275 * <div>
70276 * <code>
70277 * var names = 'Pat,Xio,Alex';
70278 * var splitString = split(names, ',');
70279 * text(splitString[0], 5, 30);
70280 * text(splitString[1], 5, 50);
70281 * text(splitString[2], 5, 70);
70282 * </code>
70283 * </div>
70284 *
70285 * @alt
70286 * "pat" top left, "Xio" mid left and "Alex" displayed bottom left
70287 *
70288 */
70289p5.prototype.split = function(str, delim) {
70290  p5._validateParameters('split', arguments);
70291  return str.split(delim);
70292};
70293
70294/**
70295 * The splitTokens() function splits a String at one or many character
70296 * delimiters or "tokens." The delim parameter specifies the character or
70297 * characters to be used as a boundary.
70298 * <br><br>
70299 * If no delim characters are specified, any whitespace character is used to
70300 * split. Whitespace characters include tab (\t), line feed (\n), carriage
70301 * return (\r), form feed (\f), and space.
70302 *
70303 * @method splitTokens
70304 * @param  {String} value   the String to be split
70305 * @param  {String} [delim] list of individual Strings that will be used as
70306 *                          separators
70307 * @return {String[]}          Array of Strings
70308 * @example
70309 * <div class = "norender">
70310 * <code>
70311 * function setup() {
70312 *   var myStr = 'Mango, Banana, Lime';
70313 *   var myStrArr = splitTokens(myStr, ',');
70314 *
70315 *   print(myStrArr); // prints : ["Mango"," Banana"," Lime"]
70316 * }
70317 * </code>
70318 * </div>
70319 */
70320p5.prototype.splitTokens = function(value, delims) {
70321  p5._validateParameters('splitTokens', arguments);
70322  var d;
70323  if (typeof delims !== 'undefined') {
70324    var str = delims;
70325    var sqc = /\]/g.exec(str);
70326    var sqo = /\[/g.exec(str);
70327    if (sqo && sqc) {
70328      str = str.slice(0, sqc.index) + str.slice(sqc.index + 1);
70329      sqo = /\[/g.exec(str);
70330      str = str.slice(0, sqo.index) + str.slice(sqo.index + 1);
70331      d = new RegExp('[\\[' + str + '\\]]', 'g');
70332    } else if (sqc) {
70333      str = str.slice(0, sqc.index) + str.slice(sqc.index + 1);
70334      d = new RegExp('[' + str + '\\]]', 'g');
70335    } else if (sqo) {
70336      str = str.slice(0, sqo.index) + str.slice(sqo.index + 1);
70337      d = new RegExp('[' + str + '\\[]', 'g');
70338    } else {
70339      d = new RegExp('[' + str + ']', 'g');
70340    }
70341  } else {
70342    d = /\s/g;
70343  }
70344  return value.split(d).filter(function(n) {
70345    return n;
70346  });
70347};
70348
70349/**
70350 * Removes whitespace characters from the beginning and end of a String. In
70351 * addition to standard whitespace characters such as space, carriage return,
70352 * and tab, this function also removes the Unicode "nbsp" character.
70353 *
70354 * @method trim
70355 * @param  {String} str a String to be trimmed
70356 * @return {String}       a trimmed String
70357 *
70358 * @example
70359 * <div>
70360 * <code>
70361 * var string = trim('  No new lines\n   ');
70362 * text(string + ' here', 2, 50);
70363 * </code>
70364 * </div>
70365 *
70366 * @alt
70367 * "No new lines here" displayed center canvas
70368 */
70369/**
70370 * @method trim
70371 * @param  {Array} strs an Array of Strings to be trimmed
70372 * @return {String[]}   an Array of trimmed Strings
70373 */
70374p5.prototype.trim = function(str) {
70375  p5._validateParameters('trim', arguments);
70376  if (str instanceof Array) {
70377    return str.map(this.trim);
70378  } else {
70379    return str.trim();
70380  }
70381};
70382
70383module.exports = p5;
70384
70385},{"../core/core":22,"../core/error_helpers":25}],62:[function(_dereq_,module,exports){
70386/**
70387 * @module IO
70388 * @submodule Time & Date
70389 * @for p5
70390 * @requires core
70391 */
70392
70393'use strict';
70394
70395var p5 = _dereq_('../core/core');
70396
70397/**
70398 * p5.js communicates with the clock on your computer. The day() function
70399 * returns the current day as a value from 1 - 31.
70400 *
70401 * @method day
70402 * @return {Integer} the current day
70403 * @example
70404 * <div>
70405 * <code>
70406 * var d = day();
70407 * text('Current day: \n' + d, 5, 50);
70408 * </code>
70409 * </div>
70410 *
70411 * @alt
70412 * Current day is displayed
70413 *
70414 */
70415p5.prototype.day = function() {
70416  return new Date().getDate();
70417};
70418
70419/**
70420 * p5.js communicates with the clock on your computer. The hour() function
70421 * returns the current hour as a value from 0 - 23.
70422 *
70423 * @method hour
70424 * @return {Integer} the current hour
70425 * @example
70426 * <div>
70427 * <code>
70428 * var h = hour();
70429 * text('Current hour:\n' + h, 5, 50);
70430 * </code>
70431 * </div>
70432 *
70433 * @alt
70434 * Current hour is displayed
70435 *
70436 */
70437p5.prototype.hour = function() {
70438  return new Date().getHours();
70439};
70440
70441/**
70442 * p5.js communicates with the clock on your computer. The minute() function
70443 * returns the current minute as a value from 0 - 59.
70444 *
70445 * @method minute
70446 * @return {Integer} the current minute
70447 * @example
70448 * <div>
70449 * <code>
70450 * var m = minute();
70451 * text('Current minute: \n' + m, 5, 50);
70452 * </code>
70453 * </div>
70454 *
70455 * @alt
70456 * Current minute is displayed
70457 *
70458 */
70459p5.prototype.minute = function() {
70460  return new Date().getMinutes();
70461};
70462
70463/**
70464 * Returns the number of milliseconds (thousandths of a second) since
70465 * starting the program. This information is often used for timing events and
70466 * animation sequences.
70467 *
70468 * @method millis
70469 * @return {Number} the number of milliseconds since starting the program
70470 * @example
70471 * <div>
70472 * <code>
70473 * var millisecond = millis();
70474 * text('Milliseconds \nrunning: \n' + millisecond, 5, 40);
70475 * </code>
70476 * </div>
70477 *
70478 * @alt
70479 * number of milliseconds since program has started displayed
70480 *
70481 */
70482p5.prototype.millis = function() {
70483  return window.performance.now();
70484};
70485
70486/**
70487 * p5.js communicates with the clock on your computer. The month() function
70488 * returns the current month as a value from 1 - 12.
70489 *
70490 * @method month
70491 * @return {Integer} the current month
70492 * @example
70493 * <div>
70494 * <code>
70495 * var m = month();
70496 * text('Current month: \n' + m, 5, 50);
70497 * </code>
70498 * </div>
70499 *
70500 * @alt
70501 * Current month is displayed
70502 *
70503 */
70504p5.prototype.month = function() {
70505  return new Date().getMonth() + 1; //January is 0!
70506};
70507
70508/**
70509 * p5.js communicates with the clock on your computer. The second() function
70510 * returns the current second as a value from 0 - 59.
70511 *
70512 * @method second
70513 * @return {Integer} the current second
70514 * @example
70515 * <div>
70516 * <code>
70517 * var s = second();
70518 * text('Current second: \n' + s, 5, 50);
70519 * </code>
70520 * </div>
70521 *
70522 * @alt
70523 * Current second is displayed
70524 *
70525 */
70526p5.prototype.second = function() {
70527  return new Date().getSeconds();
70528};
70529
70530/**
70531 * p5.js communicates with the clock on your computer. The year() function
70532 * returns the current year as an integer (2014, 2015, 2016, etc).
70533 *
70534 * @method year
70535 * @return {Integer} the current year
70536 * @example
70537 * <div>
70538 * <code>
70539 * var y = year();
70540 * text('Current year: \n' + y, 5, 50);
70541 * </code>
70542 * </div>
70543 *
70544 * @alt
70545 * Current year is displayed
70546 *
70547 */
70548p5.prototype.year = function() {
70549  return new Date().getFullYear();
70550};
70551
70552module.exports = p5;
70553
70554},{"../core/core":22}],63:[function(_dereq_,module,exports){
70555/**
70556 * @module Lights, Camera
70557 * @submodule Camera
70558 * @for p5
70559 * @requires core
70560 */
70561
70562'use strict';
70563
70564var p5 = _dereq_('../core/core');
70565
70566/**
70567 * Sets camera position for a 3D sketch. The function behaves similarly
70568 * gluLookAt, except that it replaces the existing modelview matrix instead
70569 * of applying any transformations calculated here on top of the existing
70570 * model view.
70571 * When called with no arguments, this function
70572 * sets a default camera equivalent to calling
70573 * camera(0, 0, (height/2.0) / tan(PI*30.0 / 180.0), 0, 0, 0, 0, 1, 0);
70574 * @method camera
70575 * @param  {Number} [x]        camera position value on x axis
70576 * @param  {Number} [y]        camera position value on y axis
70577 * @param  {Number} [z]        camera position value on z axis
70578 * @param  {Number} [centerX]  x coordinate representing center of the sketch
70579 * @param  {Number} [centerY]  y coordinate representing center of the sketch
70580 * @param  {Number} [centerZ]  z coordinate representing center of the sketch
70581 * @param  {Number} [upX]      x component of direction 'up' from camera
70582 * @param  {Number} [upY]      y component of direction 'up' from camera
70583 * @param  {Number} [upZ]      z component of direction 'up' from camera
70584 * @chainable
70585 * @example
70586 * <div>
70587 * <code>
70588 * function setup() {
70589 *   createCanvas(100, 100, WEBGL);
70590 * }
70591 * function draw() {
70592 *   //move the camera away from the plane by a sin wave
70593 *   camera(0, 0, sin(frameCount * 0.01) * 100, 0, 0, 0, 0, 1, 0);
70594 *   plane(120, 120);
70595 * }
70596 * </code>
70597 * </div>
70598 *
70599 * @alt
70600 * blue square shrinks in size grows to fill canvas. disappears then loops.
70601 *
70602 */
70603p5.prototype.camera = function() {
70604  this._assert3d('camera');
70605  p5._validateParameters('camera', arguments);
70606  this._renderer.camera.apply(this._renderer, arguments);
70607  return this;
70608};
70609
70610p5.RendererGL.prototype.camera = function(
70611  eyeX,
70612  eyeY,
70613  eyeZ,
70614  centerX,
70615  centerY,
70616  centerZ,
70617  upX,
70618  upY,
70619  upZ
70620) {
70621  if (typeof eyeX === 'undefined') {
70622    eyeX = this.defaultCameraX;
70623    eyeY = this.defaultCameraY;
70624    eyeZ = this.defaultCameraZ;
70625    centerX = eyeX;
70626    centerY = eyeY;
70627    centerZ = 0;
70628    upX = 0;
70629    upY = 1;
70630    upZ = 0;
70631  }
70632
70633  this.cameraX = eyeX;
70634  this.cameraY = eyeY;
70635  this.cameraZ = eyeZ;
70636
70637  // calculate camera Z vector
70638  var z0 = eyeX - centerX;
70639  var z1 = eyeY - centerY;
70640  var z2 = eyeZ - centerZ;
70641
70642  this.eyeDist = Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2);
70643  if (this.eyeDist !== 0) {
70644    z0 /= this.eyeDist;
70645    z1 /= this.eyeDist;
70646    z2 /= this.eyeDist;
70647  }
70648
70649  // calculate camera Y vector
70650  var y0 = upX;
70651  var y1 = upY;
70652  var y2 = upZ;
70653
70654  // computer x vector as y cross z
70655  var x0 = y1 * z2 - y2 * z1;
70656  var x1 = -y0 * z2 + y2 * z0;
70657  var x2 = y0 * z1 - y1 * z0;
70658
70659  // recomputer y = z cross x
70660  y0 = z1 * x2 - z2 * x1;
70661  y1 = -z0 * x2 + z2 * x0;
70662  y2 = z0 * x1 - z1 * x0;
70663
70664  // cross product gives area of parallelogram, which is < 1.0 for
70665  // non-perpendicular unit-length vectors; so normalize x, y here:
70666  var xmag = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2);
70667  if (xmag !== 0) {
70668    x0 /= xmag;
70669    x1 /= xmag;
70670    x2 /= xmag;
70671  }
70672
70673  var ymag = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2);
70674  if (ymag !== 0) {
70675    y0 /= ymag;
70676    y1 /= ymag;
70677    y2 /= ymag;
70678  }
70679
70680  // the camera affects the model view matrix, insofar as it
70681  // inverse translates the world to the eye position of the camera
70682  // and rotates it.
70683  // prettier-ignore
70684  this.cameraMatrix.set(x0, y0, z0, 0,
70685                        x1, y1, z1, 0,
70686                        x2, y2, z2, 0,
70687                        0,   0,  0, 1);
70688
70689  var tx = -eyeX;
70690  var ty = -eyeY;
70691  var tz = -eyeZ;
70692
70693  this.cameraMatrix.translate([tx, ty, tz]);
70694  this.uMVMatrix.set(
70695    this.cameraMatrix.mat4[0],
70696    this.cameraMatrix.mat4[1],
70697    this.cameraMatrix.mat4[2],
70698    this.cameraMatrix.mat4[3],
70699    this.cameraMatrix.mat4[4],
70700    this.cameraMatrix.mat4[5],
70701    this.cameraMatrix.mat4[6],
70702    this.cameraMatrix.mat4[7],
70703    this.cameraMatrix.mat4[8],
70704    this.cameraMatrix.mat4[9],
70705    this.cameraMatrix.mat4[10],
70706    this.cameraMatrix.mat4[11],
70707    this.cameraMatrix.mat4[12],
70708    this.cameraMatrix.mat4[13],
70709    this.cameraMatrix.mat4[14],
70710    this.cameraMatrix.mat4[15]
70711  );
70712  return this;
70713};
70714
70715/**
70716 * Sets perspective camera. When called with no arguments, the defaults
70717 * provided are equivalent to
70718 * perspective(PI/3.0, width/height, cameraZ/10.0, cameraZ*10.0)
70719 * where cameraZ is ((height/2.0) / tan(PI*60.0/360.0));
70720 * @method  perspective
70721 * @param  {Number} [fovy]   camera frustum vertical field of view,
70722 *                           from bottom to top of view, in angleMode units
70723 * @param  {Number} [aspect] camera frustum aspect ratio
70724 * @param  {Number} [near]   frustum near plane length
70725 * @param  {Number} [far]    frustum far plane length
70726 * @chainable
70727 * @example
70728 * <div>
70729 * <code>
70730 * //drag mouse to toggle the world!
70731 * //you will see there's a vanish point
70732 * function setup() {
70733 *   createCanvas(100, 100, WEBGL);
70734 *   var fov = 60 / 180 * PI;
70735 *   var cameraZ = height / 2.0 / tan(fov / 2.0);
70736 *   perspective(60 / 180 * PI, width / height, cameraZ * 0.1, cameraZ * 10);
70737 * }
70738 * function draw() {
70739 *   background(200);
70740 *   orbitControl();
70741 *   for (var i = -1; i < 2; i++) {
70742 *     for (var j = -2; j < 3; j++) {
70743 *       push();
70744 *       translate(i * 160, 0, j * 160);
70745 *       box(40, 40, 40);
70746 *       pop();
70747 *     }
70748 *   }
70749 * }
70750 * </code>
70751 * </div>
70752 *
70753 * @alt
70754 * colored 3d boxes toggleable with mouse position
70755 *
70756 */
70757p5.prototype.perspective = function() {
70758  this._assert3d('perspective');
70759  p5._validateParameters('perspective', arguments);
70760  this._renderer.perspective.apply(this._renderer, arguments);
70761  return this;
70762};
70763
70764p5.RendererGL.prototype.perspective = function(fovy, aspect, near, far) {
70765  if (typeof fovy === 'undefined') {
70766    fovy = this.defaultCameraFOV;
70767  }
70768  if (typeof aspect === 'undefined') {
70769    aspect = this.defaultCameraAspect;
70770  }
70771  if (typeof near === 'undefined') {
70772    near = this.defaultCameraNear;
70773  }
70774  if (typeof far === 'undefined') {
70775    far = this.defaultCameraFar;
70776  }
70777
70778  this.cameraFOV = this._pInst._toRadians(fovy);
70779  this.cameraAspect = aspect;
70780  this.cameraNear = near;
70781  this.cameraFar = far;
70782
70783  this.uPMatrix = p5.Matrix.identity();
70784
70785  var f = 1.0 / Math.tan(this.cameraFOV / 2);
70786  var nf = 1.0 / (this.cameraNear - this.cameraFar);
70787
70788  // prettier-ignore
70789  this.uPMatrix.set(f / aspect,  0,                     0,  0,
70790                    0,          -f,                     0,  0,
70791                    0,           0,     (far + near) * nf, -1,
70792                    0,           0, (2 * far * near) * nf,  0);
70793
70794  this._curCamera = 'custom';
70795};
70796
70797/**
70798 * Setup ortho camera
70799 * @method  ortho
70800 * @param  {Number} [left]   camera frustum left plane
70801 * @param  {Number} [right]  camera frustum right plane
70802 * @param  {Number} [bottom] camera frustum bottom plane
70803 * @param  {Number} [top]    camera frustum top plane
70804 * @param  {Number} [near]   camera frustum near plane
70805 * @param  {Number} [far]    camera frustum far plane
70806 * @chainable
70807 * @example
70808 * <div>
70809 * <code>
70810 * //drag mouse to toggle the world!
70811 * //there's no vanish point
70812 * function setup() {
70813 *   createCanvas(100, 100, WEBGL);
70814 *   ortho(-width / 2, width / 2, height / 2, -height / 2, 0, 500);
70815 * }
70816 * function draw() {
70817 *   background(200);
70818 *   orbitControl();
70819 *   strokeWeight(0.1);
70820 *   for (var i = -1; i < 2; i++) {
70821 *     for (var j = -2; j < 3; j++) {
70822 *       push();
70823 *       translate(i * 160, 0, j * 160);
70824 *       box(40, 40, 40);
70825 *       pop();
70826 *     }
70827 *   }
70828 * }
70829 * </code>
70830 * </div>
70831 *
70832 * @alt
70833 * 3 3d boxes, reveal several more boxes on 3d plane when mouse used to toggle
70834 *
70835 */
70836p5.prototype.ortho = function() {
70837  this._assert3d('ortho');
70838  p5._validateParameters('ortho', arguments);
70839  this._renderer.ortho.apply(this._renderer, arguments);
70840  return this;
70841};
70842
70843p5.RendererGL.prototype.ortho = function(left, right, bottom, top, near, far) {
70844  if (left === undefined) left = -this.width / 2;
70845  if (right === undefined) right = +this.width / 2;
70846  if (bottom === undefined) bottom = -this.height / 2;
70847  if (top === undefined) top = +this.height / 2;
70848  if (near === undefined) near = 0;
70849  if (far === undefined) far = Math.max(this.width, this.height);
70850
70851  var w = right - left;
70852  var h = top - bottom;
70853  var d = far - near;
70854
70855  var x = +2.0 / w;
70856  var y = +2.0 / h;
70857  var z = -2.0 / d;
70858
70859  var tx = -(right + left) / w;
70860  var ty = -(top + bottom) / h;
70861  var tz = -(far + near) / d;
70862
70863  this.uPMatrix = p5.Matrix.identity();
70864
70865  // prettier-ignore
70866  this.uPMatrix.set(  x,  0,  0,  0, 
70867                      0, -y,  0,  0, 
70868                      0,  0,  z,  0, 
70869                     tx, ty, tz,  1);
70870
70871  this._curCamera = 'custom';
70872};
70873
70874module.exports = p5;
70875
70876},{"../core/core":22}],64:[function(_dereq_,module,exports){
70877'use strict';
70878
70879var p5 = _dereq_('../core/core');
70880
70881/**
70882 * @method orbitControl
70883 * @for p5
70884 * @chainable
70885 *
70886 * @example
70887 * <div>
70888 * <code>
70889 * function setup() {
70890 *   createCanvas(100, 100, WEBGL);
70891 * }
70892 *
70893 * function draw() {
70894 *   background(50);
70895 *   // Orbit control allows the camera to orbit around a target.
70896 *   orbitControl();
70897 *   box(30, 50);
70898 * }
70899 * </code>
70900 * </div>
70901 *
70902 * @alt
70903 * Camera orbits around box when mouse is hold-clicked & then moved.
70904 */
70905//@TODO: implement full orbit controls including
70906//pan, zoom, quaternion rotation, etc.
70907p5.prototype.orbitControl = function() {
70908  this._assert3d('orbitControl');
70909  p5._validateParameters('orbitControl', arguments);
70910  if (this.mouseIsPressed) {
70911    this.rotateY((this.mouseX - this.width / 2) / (this.width / 2));
70912    this.rotateX((this.mouseY - this.height / 2) / (this.width / 2));
70913  }
70914  return this;
70915};
70916
70917module.exports = p5;
70918
70919},{"../core/core":22}],65:[function(_dereq_,module,exports){
70920/**
70921 * @module Lights, Camera
70922 * @submodule Lights
70923 * @for p5
70924 * @requires core
70925 */
70926
70927'use strict';
70928
70929var p5 = _dereq_('../core/core');
70930
70931/**
70932 * Creates an ambient light with a color
70933 *
70934 * @method ambientLight
70935 * @param  {Number}        v1      red or hue value relative to
70936 *                                 the current color range
70937 * @param  {Number}        v2      green or saturation value
70938 *                                 relative to the current color range
70939 * @param  {Number}        v3      blue or brightness value
70940 *                                 relative to the current color range
70941 * @param  {Number}        [alpha]
70942 * @chainable
70943 *
70944 * @example
70945 * <div>
70946 * <code>
70947 * function setup() {
70948 *   createCanvas(100, 100, WEBGL);
70949 * }
70950 * function draw() {
70951 *   background(0);
70952 *   ambientLight(150);
70953 *   ambientMaterial(250);
70954 *   noStroke();
70955 *   sphere(25);
70956 * }
70957 * </code>
70958 * </div>
70959 *
70960 * @alt
70961 * evenly distributed light across a sphere
70962 *
70963 */
70964
70965/**
70966 * @method ambientLight
70967 * @param  {String}        value   a color string
70968 * @chainable
70969 */
70970
70971/**
70972 * @method ambientLight
70973 * @param  {Number}        gray   a gray value
70974 * @param  {Number}        [alpha]
70975 * @chainable
70976 */
70977
70978/**
70979 * @method ambientLight
70980 * @param  {Number[]}      values  an array containing the red,green,blue &
70981 *                                 and alpha components of the color
70982 * @chainable
70983 */
70984
70985/**
70986 * @method ambientLight
70987 * @param  {p5.Color}      color   the ambient light color
70988 * @chainable
70989 */
70990p5.prototype.ambientLight = function(v1, v2, v3, a) {
70991  this._assert3d('ambientLight');
70992  p5._validateParameters('ambientLight', arguments);
70993  var color = this.color.apply(this, arguments);
70994
70995  var shader = this._renderer._useLightShader();
70996
70997  //@todo this is a bit icky. array uniforms have
70998  //to be multiples of the type 3(rgb) in this case.
70999  //a preallocated Float32Array(24) that we copy into
71000  //would be better
71001  shader.setUniform('uUseLighting', true);
71002  //in case there's no material color for the geometry
71003  shader.setUniform('uMaterialColor', this._renderer.curFillColor);
71004
71005  this._renderer.ambientLightColors.push(
71006    color._array[0],
71007    color._array[1],
71008    color._array[2]
71009  );
71010  shader.setUniform('uAmbientColor', this._renderer.ambientLightColors);
71011
71012  shader.setUniform(
71013    'uAmbientLightCount',
71014    this._renderer.ambientLightColors.length / 3
71015  );
71016
71017  return this;
71018};
71019
71020/**
71021 * Creates a directional light with a color and a direction
71022 * @method directionalLight
71023 * @param  {Number}    v1       red or hue value (depending on the current
71024 * color mode),
71025 * @param  {Number}    v2       green or saturation value
71026 * @param  {Number}    v3       blue or brightness value
71027 * @param  {p5.Vector} position the direction of the light
71028 * @chainable
71029 * @example
71030 * <div>
71031 * <code>
71032 * function setup() {
71033 *   createCanvas(100, 100, WEBGL);
71034 * }
71035 * function draw() {
71036 *   background(0);
71037 *   //move your mouse to change light direction
71038 *   var dirX = (mouseX / width - 0.5) * 2;
71039 *   var dirY = (mouseY / height - 0.5) * 2;
71040 *   directionalLight(250, 250, 250, -dirX, -dirY, 0.25);
71041 *   ambientMaterial(250);
71042 *   noStroke();
71043 *   sphere(25);
71044 * }
71045 * </code>
71046 * </div>
71047 *
71048 * @alt
71049 * light source on canvas changeable with mouse position
71050 *
71051 */
71052
71053/**
71054 * @method directionalLight
71055 * @param  {Number[]|String|p5.Color} color   color Array, CSS color string,
71056 *                                             or p5.Color value
71057 * @param  {Number}                   x       x axis direction
71058 * @param  {Number}                   y       y axis direction
71059 * @param  {Number}                   z       z axis direction
71060 * @chainable
71061 */
71062
71063/**
71064 * @method directionalLight
71065 * @param  {Number[]|String|p5.Color} color
71066 * @param  {p5.Vector}                position
71067 * @chainable
71068 */
71069
71070/**
71071 * @method directionalLight
71072 * @param  {Number}    v1
71073 * @param  {Number}    v2
71074 * @param  {Number}    v3
71075 * @param  {Number}    x
71076 * @param  {Number}    y
71077 * @param  {Number}    z
71078 * @chainable
71079 */
71080p5.prototype.directionalLight = function(v1, v2, v3, x, y, z) {
71081  this._assert3d('directionalLight');
71082  p5._validateParameters('directionalLight', arguments);
71083  var shader = this._renderer._useLightShader();
71084
71085  //@TODO: check parameters number
71086  var color = this.color.apply(this, [v1, v2, v3]);
71087
71088  var _x, _y, _z;
71089  var v = arguments[arguments.length - 1];
71090  if (typeof v === 'number') {
71091    _x = arguments[arguments.length - 3];
71092    _y = arguments[arguments.length - 2];
71093    _z = arguments[arguments.length - 1];
71094  } else {
71095    _x = v.x;
71096    _y = v.y;
71097    _z = v.z;
71098  }
71099  shader.setUniform('uUseLighting', true);
71100  //in case there's no material color for the geometry
71101  shader.setUniform('uMaterialColor', this._renderer.curFillColor);
71102
71103  // normalize direction
71104  var l = Math.sqrt(_x * _x + _y * _y + _z * _z);
71105  this._renderer.directionalLightDirections.push(_x / l, _y / l, _z / l);
71106  shader.setUniform(
71107    'uLightingDirection',
71108    this._renderer.directionalLightDirections
71109  );
71110
71111  this._renderer.directionalLightColors.push(
71112    color._array[0],
71113    color._array[1],
71114    color._array[2]
71115  );
71116  shader.setUniform('uDirectionalColor', this._renderer.directionalLightColors);
71117
71118  shader.setUniform(
71119    'uDirectionalLightCount',
71120    this._renderer.directionalLightColors.length / 3
71121  );
71122
71123  return this;
71124};
71125
71126/**
71127 * Creates a point light with a color and a light position
71128 * @method pointLight
71129 * @param  {Number}    v1       red or hue value (depending on the current
71130 * color mode),
71131 * @param  {Number}    v2       green or saturation value
71132 * @param  {Number}    v3       blue or brightness value
71133 * @param  {Number}    x        x axis position
71134 * @param  {Number}    y        y axis position
71135 * @param  {Number}    z        z axis position
71136 * @chainable
71137 * @example
71138 * <div>
71139 * <code>
71140 * function setup() {
71141 *   createCanvas(100, 100, WEBGL);
71142 * }
71143 * function draw() {
71144 *   background(0);
71145 *   //move your mouse to change light position
71146 *   var locX = mouseX - width / 2;
71147 *   var locY = mouseY - height / 2;
71148 *   // to set the light position,
71149 *   // think of the world's coordinate as:
71150 *   // -width/2,-height/2 -------- width/2,-height/2
71151 *   //                |            |
71152 *   //                |     0,0    |
71153 *   //                |            |
71154 *   // -width/2,height/2--------width/2,height/2
71155 *   pointLight(250, 250, 250, locX, locY, 50);
71156 *   ambientMaterial(250);
71157 *   noStroke();
71158 *   sphere(25);
71159 * }
71160 * </code>
71161 * </div>
71162 *
71163 * @alt
71164 * spot light on canvas changes position with mouse
71165 *
71166 */
71167
71168/**
71169 * @method pointLight
71170 * @param  {Number}    v1
71171 * @param  {Number}    v2
71172 * @param  {Number}    v3
71173 * @param  {p5.Vector} position the position of the light
71174 * @chainable
71175 */
71176
71177/**
71178 * @method pointLight
71179 * @param  {Number[]|String|p5.Color} color   color Array, CSS color string,
71180 * or p5.Color value
71181 * @param  {Number}                   x
71182 * @param  {Number}                   y
71183 * @param  {Number}                   z
71184 * @chainable
71185 */
71186
71187/**
71188 * @method pointLight
71189 * @param  {Number[]|String|p5.Color} color
71190 * @param  {p5.Vector}                position
71191 * @chainable
71192 */
71193p5.prototype.pointLight = function(v1, v2, v3, x, y, z) {
71194  this._assert3d('pointLight');
71195  p5._validateParameters('pointLight', arguments);
71196  //@TODO: check parameters number
71197  var color = this._renderer._pInst.color.apply(this, [v1, v2, v3]);
71198
71199  var _x, _y, _z;
71200  var v = arguments[arguments.length - 1];
71201  if (typeof v === 'number') {
71202    _x = arguments[arguments.length - 3];
71203    _y = arguments[arguments.length - 2];
71204    _z = arguments[arguments.length - 1];
71205  } else {
71206    _x = v.x;
71207    _y = v.y;
71208    _z = v.z;
71209  }
71210
71211  var shader = this._renderer._useLightShader();
71212  shader.setUniform('uUseLighting', true);
71213  //in case there's no material color for the geometry
71214  shader.setUniform('uMaterialColor', this._renderer.curFillColor);
71215
71216  this._renderer.pointLightPositions.push(_x, _y, _z);
71217  shader.setUniform('uPointLightLocation', this._renderer.pointLightPositions);
71218
71219  this._renderer.pointLightColors.push(
71220    color._array[0],
71221    color._array[1],
71222    color._array[2]
71223  );
71224  shader.setUniform('uPointLightColor', this._renderer.pointLightColors);
71225
71226  shader.setUniform(
71227    'uPointLightCount',
71228    this._renderer.pointLightColors.length / 3
71229  );
71230
71231  return this;
71232};
71233
71234module.exports = p5;
71235
71236},{"../core/core":22}],66:[function(_dereq_,module,exports){
71237/**
71238 * @module Shape
71239 * @submodule 3D Models
71240 * @for p5
71241 * @requires core
71242 * @requires p5.Geometry
71243 */
71244
71245'use strict';
71246
71247var p5 = _dereq_('../core/core');
71248_dereq_('./p5.Geometry');
71249
71250/**
71251 * Load a 3d model from an OBJ file.
71252 * <br><br>
71253 * One of the limitations of the OBJ format is that it doesn't have a built-in
71254 * sense of scale. This means that models exported from different programs might
71255 * be very different sizes. If your model isn't displaying, try calling
71256 * loadModel() with the normalized parameter set to true. This will resize the
71257 * model to a scale appropriate for p5. You can also make additional changes to
71258 * the final size of your model with the scale() function.
71259 *
71260 * @method loadModel
71261 * @param  {String} path              Path of the model to be loaded
71262 * @param  {Boolean} normalize        If true, scale the model to a
71263 *                                      standardized size when loading
71264 * @param  {function(p5.Geometry)} [successCallback] Function to be called
71265 *                                     once the model is loaded. Will be passed
71266 *                                     the 3D model object.
71267 * @param  {function(Event)} [failureCallback] called with event error if
71268 *                                         the image fails to load.
71269 * @return {p5.Geometry} the p5.Geometry object
71270 *
71271 * @example
71272 * <div>
71273 * <code>
71274 * //draw a spinning teapot
71275 * var teapot;
71276 *
71277 * function preload() {
71278 *   teapot = loadModel('assets/teapot.obj');
71279 * }
71280 *
71281 * function setup() {
71282 *   createCanvas(100, 100, WEBGL);
71283 * }
71284 *
71285 * function draw() {
71286 *   background(200);
71287 *   rotateX(frameCount * 0.01);
71288 *   rotateY(frameCount * 0.01);
71289 *   model(teapot);
71290 * }
71291 * </code>
71292 * </div>
71293 *
71294 * @alt
71295 * Vertically rotating 3-d teapot with red, green and blue gradient.
71296 */
71297/**
71298 * @method loadModel
71299 * @param  {String} path
71300 * @param  {function(p5.Geometry)} [successCallback]
71301 * @param  {function(Event)} [failureCallback]
71302 * @return {p5.Geometry} the p5.Geometry object
71303 */
71304p5.prototype.loadModel = function(path) {
71305  p5._validateParameters('loadModel', arguments);
71306  var normalize;
71307  var successCallback;
71308  var failureCallback;
71309  if (typeof arguments[1] === 'boolean') {
71310    normalize = arguments[1];
71311    successCallback = arguments[2];
71312    failureCallback = arguments[3];
71313  } else {
71314    normalize = false;
71315    successCallback = arguments[1];
71316    failureCallback = arguments[2];
71317  }
71318
71319  var model = new p5.Geometry();
71320  model.gid = path + '|' + normalize;
71321  var self = this;
71322  this.loadStrings(
71323    path,
71324    function(strings) {
71325      parseObj(model, strings);
71326
71327      if (normalize) {
71328        model.normalize();
71329      }
71330
71331      self._decrementPreload();
71332      if (typeof successCallback === 'function') {
71333        successCallback(model);
71334      }
71335    }.bind(this),
71336    failureCallback
71337  );
71338
71339  return model;
71340};
71341
71342/**
71343 * Parse OBJ lines into model. For reference, this is what a simple model of a
71344 * square might look like:
71345 *
71346 * v -0.5 -0.5 0.5
71347 * v -0.5 -0.5 -0.5
71348 * v -0.5 0.5 -0.5
71349 * v -0.5 0.5 0.5
71350 *
71351 * f 4 3 2 1
71352 */
71353function parseObj(model, lines) {
71354  // OBJ allows a face to specify an index for a vertex (in the above example),
71355  // but it also allows you to specify a custom combination of vertex, UV
71356  // coordinate, and vertex normal. So, "3/4/3" would mean, "use vertex 3 with
71357  // UV coordinate 4 and vertex normal 3". In WebGL, every vertex with different
71358  // parameters must be a different vertex, so loadedVerts is used to
71359  // temporarily store the parsed vertices, normals, etc., and indexedVerts is
71360  // used to map a specific combination (keyed on, for example, the string
71361  // "3/4/3"), to the actual index of the newly created vertex in the final
71362  // object.
71363  var loadedVerts = {
71364    v: [],
71365    vt: [],
71366    vn: []
71367  };
71368  var indexedVerts = {};
71369
71370  for (var line = 0; line < lines.length; ++line) {
71371    // Each line is a separate object (vertex, face, vertex normal, etc)
71372    // For each line, split it into tokens on whitespace. The first token
71373    // describes the type.
71374    var tokens = lines[line].trim().split(/\b\s+/);
71375
71376    if (tokens.length > 0) {
71377      if (tokens[0] === 'v' || tokens[0] === 'vn') {
71378        // Check if this line describes a vertex or vertex normal.
71379        // It will have three numeric parameters.
71380        var vertex = new p5.Vector(
71381          parseFloat(tokens[1]),
71382          parseFloat(tokens[2]),
71383          parseFloat(tokens[3])
71384        );
71385        loadedVerts[tokens[0]].push(vertex);
71386      } else if (tokens[0] === 'vt') {
71387        // Check if this line describes a texture coordinate.
71388        // It will have two numeric parameters.
71389        var texVertex = [parseFloat(tokens[1]), parseFloat(tokens[2])];
71390        loadedVerts[tokens[0]].push(texVertex);
71391      } else if (tokens[0] === 'f') {
71392        // Check if this line describes a face.
71393        // OBJ faces can have more than three points. Triangulate points.
71394        for (var tri = 3; tri < tokens.length; ++tri) {
71395          var face = [];
71396
71397          var vertexTokens = [1, tri - 1, tri];
71398
71399          for (var tokenInd = 0; tokenInd < vertexTokens.length; ++tokenInd) {
71400            // Now, convert the given token into an index
71401            var vertString = tokens[vertexTokens[tokenInd]];
71402            var vertIndex = 0;
71403
71404            // TODO: Faces can technically use negative numbers to refer to the
71405            // previous nth vertex. I haven't seen this used in practice, but
71406            // it might be good to implement this in the future.
71407
71408            if (indexedVerts[vertString] !== undefined) {
71409              vertIndex = indexedVerts[vertString];
71410            } else {
71411              var vertParts = vertString.split('/');
71412              for (var i = 0; i < vertParts.length; i++) {
71413                vertParts[i] = parseInt(vertParts[i]) - 1;
71414              }
71415
71416              vertIndex = indexedVerts[vertString] = model.vertices.length;
71417              model.vertices.push(loadedVerts.v[vertParts[0]].copy());
71418              if (loadedVerts.vt[vertParts[1]]) {
71419                model.uvs.push(loadedVerts.vt[vertParts[1]].slice());
71420              } else {
71421                model.uvs.push([0, 0]);
71422              }
71423
71424              if (loadedVerts.vn[vertParts[2]]) {
71425                model.vertexNormals.push(loadedVerts.vn[vertParts[2]].copy());
71426              }
71427            }
71428
71429            face.push(vertIndex);
71430          }
71431
71432          if (
71433            face[0] !== face[1] &&
71434            face[0] !== face[2] &&
71435            face[1] !== face[2]
71436          ) {
71437            model.faces.push(face);
71438          }
71439        }
71440      }
71441    }
71442  }
71443  // If the model doesn't have normals, compute the normals
71444  if (model.vertexNormals.length === 0) {
71445    model.computeNormals();
71446  }
71447
71448  return model;
71449}
71450
71451/**
71452 * Render a 3d model to the screen.
71453 *
71454 * @method model
71455 * @param  {p5.Geometry} model Loaded 3d model to be rendered
71456 * @example
71457 * <div>
71458 * <code>
71459 * //draw a spinning teapot
71460 * var teapot;
71461 *
71462 * function preload() {
71463 *   teapot = loadModel('assets/teapot.obj');
71464 * }
71465 *
71466 * function setup() {
71467 *   createCanvas(100, 100, WEBGL);
71468 * }
71469 *
71470 * function draw() {
71471 *   background(200);
71472 *   rotateX(frameCount * 0.01);
71473 *   rotateY(frameCount * 0.01);
71474 *   model(teapot);
71475 * }
71476 * </code>
71477 * </div>
71478 *
71479 * @alt
71480 * Vertically rotating 3-d teapot with red, green and blue gradient.
71481 *
71482 */
71483p5.prototype.model = function(model) {
71484  this._assert3d('model');
71485  p5._validateParameters('model', arguments);
71486  if (model.vertices.length > 0) {
71487    if (!this._renderer.geometryInHash(model.gid)) {
71488      model._makeTriangleEdges()._edgesToVertices();
71489      this._renderer.createBuffers(model.gid, model);
71490    }
71491
71492    this._renderer.drawBuffers(model.gid);
71493  }
71494};
71495
71496module.exports = p5;
71497
71498},{"../core/core":22,"./p5.Geometry":68}],67:[function(_dereq_,module,exports){
71499/**
71500 * @module Lights, Camera
71501 * @submodule Material
71502 * @for p5
71503 * @requires core
71504 */
71505
71506'use strict';
71507
71508var p5 = _dereq_('../core/core');
71509var constants = _dereq_('../core/constants');
71510_dereq_('./p5.Texture');
71511
71512/**
71513 * Loads a custom shader from the provided vertex and fragment
71514 * shader paths. The shader files are loaded asynchronously in the
71515 * background, so this method should be used in preload().
71516 *
71517 * For now, there are three main types of shaders. p5 will automatically
71518 * supply appropriate vertices, normals, colors, and lighting attributes
71519 * if the parameters defined in the shader match the names.
71520 *
71521 * @method loadShader
71522 * @param {String} [vertFilename] path to file containing vertex shader
71523 * source code
71524 * @param {String} [fragFilename] path to file containing fragment shader
71525 * source code
71526 * @return {p5.Shader} a shader object created from the provided
71527 * vertex and fragment shader files.
71528 */
71529p5.prototype.loadShader = function(vertFilename, fragFilename) {
71530  p5._validateParameters('loadShader', arguments);
71531  var loadedShader = new p5.Shader();
71532
71533  var self = this;
71534  var loadedFrag = false;
71535  var loadedVert = false;
71536
71537  this.loadStrings(fragFilename, function(result) {
71538    loadedShader._fragSrc = result.join('\n');
71539    loadedFrag = true;
71540    if (loadedVert) {
71541      self._decrementPreload();
71542    }
71543  });
71544  this.loadStrings(vertFilename, function(result) {
71545    loadedShader._vertSrc = result.join('\n');
71546    loadedVert = true;
71547    if (loadedFrag) {
71548      self._decrementPreload();
71549    }
71550  });
71551
71552  return loadedShader;
71553};
71554
71555/**
71556 * @method createShader
71557 * @param {String} vertSrc source code for the vertex shader
71558 * @param {String} fragSrc source code for the fragment shader
71559 * @returns {p5.Shader} a shader object created from the provided
71560 * vertex and fragment shaders.
71561 *
71562 * @example
71563 * <div modernizr='webgl'>
71564 * <code>
71565 * // the 'varying's are shared between both vertex & fragment shaders
71566 * var varying = 'precision highp float; varying vec2 vPos;';
71567 *
71568 * // the vertex shader is called for each vertex
71569 * var vs =
71570 *   varying +
71571 *   'attribute vec3 aPosition;' +
71572 *   'void main() { vPos = (gl_Position = vec4(aPosition,1.0)).xy; }';
71573 *
71574 * // the fragment shader is called for each pixel
71575 * var fs =
71576 *   varying +
71577 *   'uniform vec2 p;' +
71578 *   'uniform float r;' +
71579 *   'const int I = 500;' +
71580 *   'void main() {' +
71581 *   '  vec2 c = p + vPos * r, z = c;' +
71582 *   '  float n = 0.0;' +
71583 *   '  for (int i = I; i > 0; i --) {' +
71584 *   '    if(z.x*z.x+z.y*z.y > 4.0) {' +
71585 *   '      n = float(i)/float(I);' +
71586 *   '      break;' +
71587 *   '    }' +
71588 *   '    z = vec2(z.x*z.x-z.y*z.y, 2.0*z.x*z.y) + c;' +
71589 *   '  }' +
71590 *   '  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);' +
71591 *   '}';
71592 *
71593 * var mandel;
71594 * function setup() {
71595 *   createCanvas(100, 100, WEBGL);
71596 *
71597 *   // create and initialize the shader
71598 *   mandel = createShader(vs, fs);
71599 *   shader(mandel);
71600 *   noStroke();
71601 *
71602 *   // 'p' is the center point of the Mandelbrot image
71603 *   mandel.setUniform('p', [-0.74364388703, 0.13182590421]);
71604 * }
71605 *
71606 * function draw() {
71607 *   // 'r' is the size of the image in Mandelbrot-space
71608 *   mandel.setUniform('r', 1.5 * exp(-6.5 * (1 + sin(millis() / 2000))));
71609 *   quad(-1, -1, 1, -1, 1, 1, -1, 1);
71610 * }
71611 * </code>
71612 * </div>
71613 *
71614 * @alt
71615 * zooming Mandelbrot set. a colorful, infinitely detailed fractal.
71616 */
71617p5.prototype.createShader = function(vertSrc, fragSrc) {
71618  this._assert3d('createShader');
71619  p5._validateParameters('createShader', arguments);
71620  return new p5.Shader(this._renderer, vertSrc, fragSrc);
71621};
71622
71623/**
71624 * The shader() function lets the user provide a custom shader
71625 * to fill in shapes in WEBGL mode. Users can create their
71626 * own shaders by loading vertex and fragment shaders with
71627 * loadShader().
71628 *
71629 * @method shader
71630 * @chainable
71631 * @param {p5.Shader} [s] the desired p5.Shader to use for rendering
71632 * shapes.
71633 */
71634p5.prototype.shader = function(s) {
71635  this._assert3d('shader');
71636  p5._validateParameters('shader', arguments);
71637  if (s._renderer === undefined) {
71638    s._renderer = this._renderer;
71639  }
71640  if (s.isStrokeShader()) {
71641    this._renderer.setStrokeShader(s);
71642  } else {
71643    this._renderer.setFillShader(s);
71644  }
71645  return this;
71646};
71647
71648/**
71649 * Normal material for geometry. You can view all
71650 * possible materials in this
71651 * <a href="https://p5js.org/examples/3d-materials.html">example</a>.
71652 * @method normalMaterial
71653 * @chainable
71654 * @example
71655 * <div>
71656 * <code>
71657 * function setup() {
71658 *   createCanvas(100, 100, WEBGL);
71659 * }
71660 *
71661 * function draw() {
71662 *   background(200);
71663 *   normalMaterial();
71664 *   sphere(50);
71665 * }
71666 * </code>
71667 * </div>
71668 *
71669 * @alt
71670 * Red, green and blue gradient.
71671 *
71672 */
71673p5.prototype.normalMaterial = function() {
71674  this._assert3d('normalMaterial');
71675  p5._validateParameters('normalMaterial', arguments);
71676  this._renderer.drawMode = constants.FILL;
71677  this._renderer.setFillShader(this._renderer._getNormalShader());
71678  this._renderer.curFillColor = [1, 1, 1, 1];
71679  this.noStroke();
71680  return this;
71681};
71682
71683/**
71684 * Texture for geometry.  You can view other possible materials in this
71685 * <a href="https://p5js.org/examples/3d-materials.html">example</a>.
71686 * @method texture
71687 * @param {p5.Image|p5.MediaElement|p5.Graphics} tex 2-dimensional graphics
71688 *                    to render as texture
71689 * @chainable
71690 * @example
71691 * <div>
71692 * <code>
71693 * var img;
71694 * function preload() {
71695 *   img = loadImage('assets/laDefense.jpg');
71696 * }
71697 *
71698 * function setup() {
71699 *   createCanvas(100, 100, WEBGL);
71700 * }
71701 *
71702 * function draw() {
71703 *   background(0);
71704 *   rotateZ(frameCount * 0.01);
71705 *   rotateX(frameCount * 0.01);
71706 *   rotateY(frameCount * 0.01);
71707 *   //pass image as texture
71708 *   texture(img);
71709 *   box(200, 200, 200);
71710 * }
71711 * </code>
71712 * </div>
71713 *
71714 * <div>
71715 * <code>
71716 * var pg;
71717 * function setup() {
71718 *   createCanvas(100, 100, WEBGL);
71719 *   pg = createGraphics(200, 200);
71720 *   pg.textSize(100);
71721 * }
71722 *
71723 * function draw() {
71724 *   background(0);
71725 *   pg.background(255);
71726 *   pg.text('hello!', 0, 100);
71727 *   //pass image as texture
71728 *   texture(pg);
71729 *   plane(200);
71730 * }
71731 * </code>
71732 * </div>
71733 *
71734 * <div>
71735 * <code>
71736 * var vid;
71737 * function preload() {
71738 *   vid = createVideo('assets/fingers.mov');
71739 *   vid.hide();
71740 *   vid.loop();
71741 * }
71742 * function setup() {
71743 *   createCanvas(100, 100, WEBGL);
71744 * }
71745 *
71746 * function draw() {
71747 *   background(0);
71748 *   //pass video frame as texture
71749 *   texture(vid);
71750 *   plane(200);
71751 * }
71752 * </code>
71753 * </div>
71754 *
71755 * @alt
71756 * Rotating view of many images umbrella and grid roof on a 3d plane
71757 * black canvas
71758 * black canvas
71759 *
71760 */
71761p5.prototype.texture = function(tex) {
71762  this._assert3d('texture');
71763  p5._validateParameters('texture', arguments);
71764  this._renderer.drawMode = constants.TEXTURE;
71765  var shader = this._renderer._useLightShader();
71766  shader.setUniform('uSpecular', false);
71767  shader.setUniform('isTexture', true);
71768  shader.setUniform('uSampler', tex);
71769  this.noStroke();
71770  return this;
71771};
71772
71773/**
71774 * Ambient material for geometry with a given color. You can view all
71775 * possible materials in this
71776 * <a href="https://p5js.org/examples/3d-materials.html">example</a>.
71777 * @method  ambientMaterial
71778 * @param  {Number} v1  gray value, red or hue value
71779 *                         (depending on the current color mode),
71780 * @param  {Number} [v2] green or saturation value
71781 * @param  {Number} [v3] blue or brightness value
71782 * @param  {Number} [a]  opacity
71783 * @chainable
71784 * @example
71785 * <div>
71786 * <code>
71787 * function setup() {
71788 *   createCanvas(100, 100, WEBGL);
71789 * }
71790 * function draw() {
71791 *   background(0);
71792 *   ambientLight(100);
71793 *   pointLight(250, 250, 250, 100, 100, 0);
71794 *   ambientMaterial(250);
71795 *   sphere(50);
71796 * }
71797 * </code>
71798 * </div>
71799 *
71800 * @alt
71801 * radiating light source from top right of canvas
71802 *
71803 */
71804/**
71805 * @method  ambientMaterial
71806 * @param  {Number[]|String|p5.Color} color  color, color Array, or CSS color string
71807 * @chainable
71808 */
71809p5.prototype.ambientMaterial = function(v1, v2, v3, a) {
71810  this._assert3d('ambientMaterial');
71811  p5._validateParameters('ambientMaterial', arguments);
71812  var color = p5.prototype.color.apply(this, arguments);
71813  this._renderer.curFillColor = color._array;
71814
71815  var shader = this._renderer._useLightShader();
71816  shader.setUniform('uMaterialColor', this._renderer.curFillColor);
71817  shader.setUniform('uSpecular', false);
71818  shader.setUniform('isTexture', false);
71819  return this;
71820};
71821
71822/**
71823 * Specular material for geometry with a given color. You can view all
71824 * possible materials in this
71825 * <a href="https://p5js.org/examples/3d-materials.html">example</a>.
71826 * @method specularMaterial
71827 * @param  {Number} v1  gray value, red or hue value
71828 *                       (depending on the current color mode),
71829 * @param  {Number} [v2] green or saturation value
71830 * @param  {Number} [v3] blue or brightness value
71831 * @param  {Number} [a]  opacity
71832 * @chainable
71833 * @example
71834 * <div>
71835 * <code>
71836 * function setup() {
71837 *   createCanvas(100, 100, WEBGL);
71838 * }
71839 * function draw() {
71840 *   background(0);
71841 *   ambientLight(100);
71842 *   pointLight(250, 250, 250, 100, 100, 0);
71843 *   specularMaterial(250);
71844 *   sphere(50);
71845 * }
71846 * </code>
71847 * </div>
71848 *
71849 * @alt
71850 * diffused radiating light source from top right of canvas
71851 *
71852 */
71853/**
71854 * @method specularMaterial
71855 * @param  {Number[]|String|p5.Color} color color Array, or CSS color string
71856 * @chainable
71857 */
71858p5.prototype.specularMaterial = function(v1, v2, v3, a) {
71859  this._assert3d('specularMaterial');
71860  p5._validateParameters('specularMaterial', arguments);
71861  var color = p5.prototype.color.apply(this, arguments);
71862  this._renderer.curFillColor = color._array;
71863
71864  var shader = this._renderer._useLightShader();
71865  shader.setUniform('uMaterialColor', this._renderer.curFillColor);
71866  shader.setUniform('uSpecular', true);
71867  shader.setUniform('isTexture', false);
71868  return this;
71869};
71870
71871/**
71872 * @private blends colors according to color components.
71873 * If alpha value is less than 1, we need to enable blending
71874 * on our gl context.  Otherwise opaque objects need to a depthMask.
71875 * @param  {Number[]} color [description]
71876 * @return {Number[]]}  Normalized numbers array
71877 */
71878p5.RendererGL.prototype._applyColorBlend = function(colors) {
71879  var gl = this.GL;
71880
71881  var isTexture = this.drawMode === constants.TEXTURE;
71882  if (isTexture || colors[colors.length - 1] < 1.0) {
71883    gl.depthMask(isTexture);
71884    gl.enable(gl.BLEND);
71885    gl.blendEquation(gl.FUNC_ADD);
71886    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
71887  } else {
71888    gl.depthMask(true);
71889    gl.disable(gl.BLEND);
71890  }
71891  return colors;
71892};
71893
71894module.exports = p5;
71895
71896},{"../core/constants":21,"../core/core":22,"./p5.Texture":74}],68:[function(_dereq_,module,exports){
71897//some of the functions are adjusted from Three.js(http://threejs.org)
71898
71899'use strict';
71900
71901var p5 = _dereq_('../core/core');
71902/**
71903 * p5 Geometry class
71904 * @class p5.Geometry
71905 * @constructor
71906 * @param  {function | Object} vertData callback function or Object
71907 *                     containing routine(s) for vertex data generation
71908 * @param  {Integer} [detailX] number of vertices on horizontal surface
71909 * @param  {Integer} [detailY] number of vertices on horizontal surface
71910 * @param {function} [callback] function to call upon object instantiation.
71911 *
71912 */
71913p5.Geometry = function(detailX, detailY, callback) {
71914  //an array containing every vertex
71915  //@type [p5.Vector]
71916  this.vertices = [];
71917
71918  //an array containing every vertex for stroke drawing
71919  this.lineVertices = [];
71920
71921  //an array 1 normal per lineVertex with
71922  //final position representing which direction to
71923  //displace for strokeWeight
71924  //[[0,0,-1,1], [0,1,0,-1] ...];
71925  this.lineNormals = [];
71926
71927  //an array containing 1 normal per vertex
71928  //@type [p5.Vector]
71929  //[p5.Vector, p5.Vector, p5.Vector,p5.Vector, p5.Vector, p5.Vector,...]
71930  this.vertexNormals = [];
71931  //an array containing each three vertex indices that form a face
71932  //[[0, 1, 2], [2, 1, 3], ...]
71933  this.faces = [];
71934  //a 2D array containing uvs for every vertex
71935  //[[0.0,0.0],[1.0,0.0], ...]
71936  this.uvs = [];
71937  // a 2D array containing edge connectivity pattern for create line vertices
71938  //based on faces for most objects;
71939  this.edges = [];
71940  this.detailX = detailX !== undefined ? detailX : 1;
71941  this.detailY = detailY !== undefined ? detailY : 1;
71942  if (callback instanceof Function) {
71943    callback.call(this);
71944  }
71945  return this; // TODO: is this a constructor?
71946};
71947
71948/**
71949 * @method computeFaces
71950 * @chainable
71951 */
71952p5.Geometry.prototype.computeFaces = function() {
71953  this.faces.length = 0;
71954  var sliceCount = this.detailX + 1;
71955  var a, b, c, d;
71956  for (var i = 0; i < this.detailY; i++) {
71957    for (var j = 0; j < this.detailX; j++) {
71958      a = i * sliceCount + j; // + offset;
71959      b = i * sliceCount + j + 1; // + offset;
71960      c = (i + 1) * sliceCount + j + 1; // + offset;
71961      d = (i + 1) * sliceCount + j; // + offset;
71962      this.faces.push([a, b, d]);
71963      this.faces.push([d, b, c]);
71964    }
71965  }
71966  return this;
71967};
71968
71969p5.Geometry.prototype._getFaceNormal = function(faceId) {
71970  //This assumes that vA->vB->vC is a counter-clockwise ordering
71971  var face = this.faces[faceId];
71972  var vA = this.vertices[face[0]];
71973  var vB = this.vertices[face[1]];
71974  var vC = this.vertices[face[2]];
71975  var ab = p5.Vector.sub(vB, vA);
71976  var ac = p5.Vector.sub(vC, vA);
71977  var n = p5.Vector.cross(ab, ac);
71978  var ln = p5.Vector.mag(n);
71979  var sinAlpha = ln / (p5.Vector.mag(ab) * p5.Vector.mag(ac));
71980  if (sinAlpha === 0 || isNaN(sinAlpha)) {
71981    console.warn(
71982      'p5.Geometry.prototype._getFaceNormal:',
71983      'face has colinear sides or a repeated vertex'
71984    );
71985    return n;
71986  }
71987  if (sinAlpha > 1) sinAlpha = 1; // handle float rounding error
71988  return n.mult(Math.asin(sinAlpha) / ln);
71989};
71990/**
71991 * computes smooth normals per vertex as an average of each
71992 * face.
71993 * @method computeNormals
71994 * @chainable
71995 */
71996p5.Geometry.prototype.computeNormals = function() {
71997  var vertexNormals = this.vertexNormals;
71998  var vertices = this.vertices;
71999  var faces = this.faces;
72000  var iv;
72001
72002  // initialize the vertexNormals array with empty vectors
72003  vertexNormals.length = 0;
72004  for (iv = 0; iv < vertices.length; ++iv) {
72005    vertexNormals.push(new p5.Vector());
72006  }
72007
72008  // loop through all the faces adding its normal to the normal
72009  // of each of its vertices
72010  for (var f = 0; f < faces.length; ++f) {
72011    var face = faces[f];
72012    var faceNormal = this._getFaceNormal(f);
72013
72014    // all three vertices get the normal added
72015    for (var fv = 0; fv < 3; ++fv) {
72016      var vertexIndex = face[fv];
72017      vertexNormals[vertexIndex].add(faceNormal);
72018    }
72019  }
72020
72021  // normalize the normals
72022  for (iv = 0; iv < vertices.length; ++iv) {
72023    vertexNormals[iv].normalize();
72024  }
72025
72026  return this;
72027};
72028
72029/**
72030 * Averages the vertex normals. Used in curved
72031 * surfaces
72032 * @method averageNormals
72033 * @chainable
72034 */
72035p5.Geometry.prototype.averageNormals = function() {
72036  for (var i = 0; i <= this.detailY; i++) {
72037    var offset = this.detailX + 1;
72038    var temp = p5.Vector.add(
72039      this.vertexNormals[i * offset],
72040      this.vertexNormals[i * offset + this.detailX]
72041    );
72042
72043    temp = p5.Vector.div(temp, 2);
72044    this.vertexNormals[i * offset] = temp;
72045    this.vertexNormals[i * offset + this.detailX] = temp;
72046  }
72047  return this;
72048};
72049
72050/**
72051 * Averages pole normals.  Used in spherical primitives
72052 * @method averagePoleNormals
72053 * @chainable
72054 */
72055p5.Geometry.prototype.averagePoleNormals = function() {
72056  //average the north pole
72057  var sum = new p5.Vector(0, 0, 0);
72058  for (var i = 0; i < this.detailX; i++) {
72059    sum.add(this.vertexNormals[i]);
72060  }
72061  sum = p5.Vector.div(sum, this.detailX);
72062
72063  for (i = 0; i < this.detailX; i++) {
72064    this.vertexNormals[i] = sum;
72065  }
72066
72067  //average the south pole
72068  sum = new p5.Vector(0, 0, 0);
72069  for (
72070    i = this.vertices.length - 1;
72071    i > this.vertices.length - 1 - this.detailX;
72072    i--
72073  ) {
72074    sum.add(this.vertexNormals[i]);
72075  }
72076  sum = p5.Vector.div(sum, this.detailX);
72077
72078  for (
72079    i = this.vertices.length - 1;
72080    i > this.vertices.length - 1 - this.detailX;
72081    i--
72082  ) {
72083    this.vertexNormals[i] = sum;
72084  }
72085  return this;
72086};
72087
72088/**
72089 * Create a 2D array for establishing stroke connections
72090 * @private
72091 * @chainable
72092 */
72093p5.Geometry.prototype._makeTriangleEdges = function() {
72094  this.edges.length = 0;
72095  if (Array.isArray(this.strokeIndices)) {
72096    for (var i = 0, max = this.strokeIndices.length; i < max; i++) {
72097      this.edges.push(this.strokeIndices[i]);
72098    }
72099  } else {
72100    for (var j = 0; j < this.faces.length; j++) {
72101      this.edges.push([this.faces[j][0], this.faces[j][1]]);
72102      this.edges.push([this.faces[j][1], this.faces[j][2]]);
72103      this.edges.push([this.faces[j][2], this.faces[j][0]]);
72104    }
72105  }
72106  return this;
72107};
72108
72109/**
72110 * Create 4 vertices for each stroke line, two at the beginning position
72111 * and two at the end position. These vertices are displaced relative to
72112 * that line's normal on the GPU
72113 * @private
72114 * @chainable
72115 */
72116p5.Geometry.prototype._edgesToVertices = function() {
72117  this.lineVertices.length = 0;
72118  this.lineNormals.length = 0;
72119
72120  for (var i = 0; i < this.edges.length; i++) {
72121    var begin = this.vertices[this.edges[i][0]];
72122    var end = this.vertices[this.edges[i][1]];
72123    var dir = end
72124      .copy()
72125      .sub(begin)
72126      .normalize();
72127    var a = begin.array();
72128    var b = begin.array();
72129    var c = end.array();
72130    var d = end.array();
72131    var dirAdd = dir.array();
72132    var dirSub = dir.array();
72133    // below is used to displace the pair of vertices at beginning and end
72134    // in opposite directions
72135    dirAdd.push(1);
72136    dirSub.push(-1);
72137    this.lineNormals.push(dirAdd, dirSub, dirAdd, dirAdd, dirSub, dirSub);
72138    this.lineVertices.push(a, b, c, c, b, d);
72139  }
72140  return this;
72141};
72142
72143/**
72144 * Modifies all vertices to be centered within the range -100 to 100.
72145 * @method normalize
72146 * @chainable
72147 */
72148p5.Geometry.prototype.normalize = function() {
72149  if (this.vertices.length > 0) {
72150    // Find the corners of our bounding box
72151    var maxPosition = this.vertices[0].copy();
72152    var minPosition = this.vertices[0].copy();
72153
72154    for (var i = 0; i < this.vertices.length; i++) {
72155      maxPosition.x = Math.max(maxPosition.x, this.vertices[i].x);
72156      minPosition.x = Math.min(minPosition.x, this.vertices[i].x);
72157      maxPosition.y = Math.max(maxPosition.y, this.vertices[i].y);
72158      minPosition.y = Math.min(minPosition.y, this.vertices[i].y);
72159      maxPosition.z = Math.max(maxPosition.z, this.vertices[i].z);
72160      minPosition.z = Math.min(minPosition.z, this.vertices[i].z);
72161    }
72162
72163    var center = p5.Vector.lerp(maxPosition, minPosition, 0.5);
72164    var dist = p5.Vector.sub(maxPosition, minPosition);
72165    var longestDist = Math.max(Math.max(dist.x, dist.y), dist.z);
72166    var scale = 200 / longestDist;
72167
72168    for (i = 0; i < this.vertices.length; i++) {
72169      this.vertices[i].sub(center);
72170      this.vertices[i].mult(scale);
72171    }
72172  }
72173  return this;
72174};
72175
72176module.exports = p5.Geometry;
72177
72178},{"../core/core":22}],69:[function(_dereq_,module,exports){
72179/**
72180 * @requires constants
72181 * @todo see methods below needing further implementation.
72182 * future consideration: implement SIMD optimizations
72183 * when browser compatibility becomes available
72184 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/
72185 *   Reference/Global_Objects/SIMD
72186 */
72187
72188'use strict';
72189
72190var p5 = _dereq_('../core/core');
72191
72192var GLMAT_ARRAY_TYPE = Array;
72193var isMatrixArray = function(x) {
72194  return x instanceof Array;
72195};
72196if (typeof Float32Array !== 'undefined') {
72197  GLMAT_ARRAY_TYPE = Float32Array;
72198  isMatrixArray = function(x) {
72199    return x instanceof Array || x instanceof Float32Array;
72200  };
72201}
72202
72203/**
72204 * A class to describe a 4x4 matrix
72205 * for model and view matrix manipulation in the p5js webgl renderer.
72206 * @class p5.Matrix
72207 * @private
72208 * @constructor
72209 * @param {Array} [mat4] array literal of our 4x4 matrix
72210 */
72211p5.Matrix = function() {
72212  var args = new Array(arguments.length);
72213  for (var i = 0; i < args.length; ++i) {
72214    args[i] = arguments[i];
72215  }
72216
72217  // This is default behavior when object
72218  // instantiated using createMatrix()
72219  // @todo implement createMatrix() in core/math.js
72220  if (args.length && args[args.length - 1] instanceof p5) {
72221    this.p5 = args[args.length - 1];
72222  }
72223
72224  if (args[0] === 'mat3') {
72225    this.mat3 = Array.isArray(args[1])
72226      ? args[1]
72227      : new GLMAT_ARRAY_TYPE([1, 0, 0, 0, 1, 0, 0, 0, 1]);
72228  } else {
72229    this.mat4 = Array.isArray(args[0])
72230      ? args[0]
72231      : new GLMAT_ARRAY_TYPE([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
72232  }
72233  return this;
72234};
72235
72236/**
72237 * Sets the x, y, and z component of the vector using two or three separate
72238 * variables, the data from a p5.Matrix, or the values from a float array.
72239 *
72240 * @method set
72241 * @param {p5.Matrix|Float32Array|Number[]} [inMatrix] the input p5.Matrix or
72242 *                                     an Array of length 16
72243 * @chainable
72244 */
72245/**
72246 * @method set
72247 * @param {Number[]} elements 16 numbers passed by value to avoid
72248 *                                     array copying.
72249 * @chainable
72250 */
72251p5.Matrix.prototype.set = function(inMatrix) {
72252  if (inMatrix instanceof p5.Matrix) {
72253    this.mat4 = inMatrix.mat4;
72254    return this;
72255  } else if (isMatrixArray(inMatrix)) {
72256    this.mat4 = inMatrix;
72257    return this;
72258  } else if (arguments.length === 16) {
72259    this.mat4[0] = arguments[0];
72260    this.mat4[1] = arguments[1];
72261    this.mat4[2] = arguments[2];
72262    this.mat4[3] = arguments[3];
72263    this.mat4[4] = arguments[4];
72264    this.mat4[5] = arguments[5];
72265    this.mat4[6] = arguments[6];
72266    this.mat4[7] = arguments[7];
72267    this.mat4[8] = arguments[8];
72268    this.mat4[9] = arguments[9];
72269    this.mat4[10] = arguments[10];
72270    this.mat4[11] = arguments[11];
72271    this.mat4[12] = arguments[12];
72272    this.mat4[13] = arguments[13];
72273    this.mat4[14] = arguments[14];
72274    this.mat4[15] = arguments[15];
72275  }
72276  return this;
72277};
72278
72279/**
72280 * Gets a copy of the vector, returns a p5.Matrix object.
72281 *
72282 * @method get
72283 * @return {p5.Matrix} the copy of the p5.Matrix object
72284 */
72285p5.Matrix.prototype.get = function() {
72286  return new p5.Matrix(this.mat4, this.p5);
72287};
72288
72289/**
72290 * return a copy of a matrix
72291 * @method copy
72292 * @return {p5.Matrix}   the result matrix
72293 */
72294p5.Matrix.prototype.copy = function() {
72295  var copied = new p5.Matrix(this.p5);
72296  copied.mat4[0] = this.mat4[0];
72297  copied.mat4[1] = this.mat4[1];
72298  copied.mat4[2] = this.mat4[2];
72299  copied.mat4[3] = this.mat4[3];
72300  copied.mat4[4] = this.mat4[4];
72301  copied.mat4[5] = this.mat4[5];
72302  copied.mat4[6] = this.mat4[6];
72303  copied.mat4[7] = this.mat4[7];
72304  copied.mat4[8] = this.mat4[8];
72305  copied.mat4[9] = this.mat4[9];
72306  copied.mat4[10] = this.mat4[10];
72307  copied.mat4[11] = this.mat4[11];
72308  copied.mat4[12] = this.mat4[12];
72309  copied.mat4[13] = this.mat4[13];
72310  copied.mat4[14] = this.mat4[14];
72311  copied.mat4[15] = this.mat4[15];
72312  return copied;
72313};
72314
72315/**
72316 * return an identity matrix
72317 * @method identity
72318 * @return {p5.Matrix}   the result matrix
72319 */
72320p5.Matrix.identity = function(pInst) {
72321  return new p5.Matrix(pInst);
72322};
72323
72324/**
72325 * transpose according to a given matrix
72326 * @method transpose
72327 * @param  {p5.Matrix|Float32Array|Number[]} a  the matrix to be
72328 *                                               based on to transpose
72329 * @chainable
72330 */
72331p5.Matrix.prototype.transpose = function(a) {
72332  var a01, a02, a03, a12, a13, a23;
72333  if (a instanceof p5.Matrix) {
72334    a01 = a.mat4[1];
72335    a02 = a.mat4[2];
72336    a03 = a.mat4[3];
72337    a12 = a.mat4[6];
72338    a13 = a.mat4[7];
72339    a23 = a.mat4[11];
72340
72341    this.mat4[0] = a.mat4[0];
72342    this.mat4[1] = a.mat4[4];
72343    this.mat4[2] = a.mat4[8];
72344    this.mat4[3] = a.mat4[12];
72345    this.mat4[4] = a01;
72346    this.mat4[5] = a.mat4[5];
72347    this.mat4[6] = a.mat4[9];
72348    this.mat4[7] = a.mat4[13];
72349    this.mat4[8] = a02;
72350    this.mat4[9] = a12;
72351    this.mat4[10] = a.mat4[10];
72352    this.mat4[11] = a.mat4[14];
72353    this.mat4[12] = a03;
72354    this.mat4[13] = a13;
72355    this.mat4[14] = a23;
72356    this.mat4[15] = a.mat4[15];
72357  } else if (isMatrixArray(a)) {
72358    a01 = a[1];
72359    a02 = a[2];
72360    a03 = a[3];
72361    a12 = a[6];
72362    a13 = a[7];
72363    a23 = a[11];
72364
72365    this.mat4[0] = a[0];
72366    this.mat4[1] = a[4];
72367    this.mat4[2] = a[8];
72368    this.mat4[3] = a[12];
72369    this.mat4[4] = a01;
72370    this.mat4[5] = a[5];
72371    this.mat4[6] = a[9];
72372    this.mat4[7] = a[13];
72373    this.mat4[8] = a02;
72374    this.mat4[9] = a12;
72375    this.mat4[10] = a[10];
72376    this.mat4[11] = a[14];
72377    this.mat4[12] = a03;
72378    this.mat4[13] = a13;
72379    this.mat4[14] = a23;
72380    this.mat4[15] = a[15];
72381  }
72382  return this;
72383};
72384
72385/**
72386 * invert  matrix according to a give matrix
72387 * @method invert
72388 * @param  {p5.Matrix|Float32Array|Number[]} a   the matrix to be
72389 *                                                based on to invert
72390 * @chainable
72391 */
72392p5.Matrix.prototype.invert = function(a) {
72393  var a00, a01, a02, a03, a10, a11, a12, a13;
72394  var a20, a21, a22, a23, a30, a31, a32, a33;
72395  if (a instanceof p5.Matrix) {
72396    a00 = a.mat4[0];
72397    a01 = a.mat4[1];
72398    a02 = a.mat4[2];
72399    a03 = a.mat4[3];
72400    a10 = a.mat4[4];
72401    a11 = a.mat4[5];
72402    a12 = a.mat4[6];
72403    a13 = a.mat4[7];
72404    a20 = a.mat4[8];
72405    a21 = a.mat4[9];
72406    a22 = a.mat4[10];
72407    a23 = a.mat4[11];
72408    a30 = a.mat4[12];
72409    a31 = a.mat4[13];
72410    a32 = a.mat4[14];
72411    a33 = a.mat4[15];
72412  } else if (isMatrixArray(a)) {
72413    a00 = a[0];
72414    a01 = a[1];
72415    a02 = a[2];
72416    a03 = a[3];
72417    a10 = a[4];
72418    a11 = a[5];
72419    a12 = a[6];
72420    a13 = a[7];
72421    a20 = a[8];
72422    a21 = a[9];
72423    a22 = a[10];
72424    a23 = a[11];
72425    a30 = a[12];
72426    a31 = a[13];
72427    a32 = a[14];
72428    a33 = a[15];
72429  }
72430  var b00 = a00 * a11 - a01 * a10;
72431  var b01 = a00 * a12 - a02 * a10;
72432  var b02 = a00 * a13 - a03 * a10;
72433  var b03 = a01 * a12 - a02 * a11;
72434  var b04 = a01 * a13 - a03 * a11;
72435  var b05 = a02 * a13 - a03 * a12;
72436  var b06 = a20 * a31 - a21 * a30;
72437  var b07 = a20 * a32 - a22 * a30;
72438  var b08 = a20 * a33 - a23 * a30;
72439  var b09 = a21 * a32 - a22 * a31;
72440  var b10 = a21 * a33 - a23 * a31;
72441  var b11 = a22 * a33 - a23 * a32;
72442
72443  // Calculate the determinant
72444  var det =
72445    b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
72446
72447  if (!det) {
72448    return null;
72449  }
72450  det = 1.0 / det;
72451
72452  this.mat4[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
72453  this.mat4[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
72454  this.mat4[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
72455  this.mat4[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
72456  this.mat4[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
72457  this.mat4[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
72458  this.mat4[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
72459  this.mat4[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
72460  this.mat4[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
72461  this.mat4[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
72462  this.mat4[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
72463  this.mat4[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
72464  this.mat4[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
72465  this.mat4[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
72466  this.mat4[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
72467  this.mat4[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
72468
72469  return this;
72470};
72471
72472/**
72473 * Inverts a 3x3 matrix
72474 * @method invert3x3
72475 * @chainable
72476 */
72477p5.Matrix.prototype.invert3x3 = function() {
72478  var a00 = this.mat3[0];
72479  var a01 = this.mat3[1];
72480  var a02 = this.mat3[2];
72481  var a10 = this.mat3[3];
72482  var a11 = this.mat3[4];
72483  var a12 = this.mat3[5];
72484  var a20 = this.mat3[6];
72485  var a21 = this.mat3[7];
72486  var a22 = this.mat3[8];
72487  var b01 = a22 * a11 - a12 * a21;
72488  var b11 = -a22 * a10 + a12 * a20;
72489  var b21 = a21 * a10 - a11 * a20;
72490
72491  // Calculate the determinant
72492  var det = a00 * b01 + a01 * b11 + a02 * b21;
72493  if (!det) {
72494    return null;
72495  }
72496  det = 1.0 / det;
72497  this.mat3[0] = b01 * det;
72498  this.mat3[1] = (-a22 * a01 + a02 * a21) * det;
72499  this.mat3[2] = (a12 * a01 - a02 * a11) * det;
72500  this.mat3[3] = b11 * det;
72501  this.mat3[4] = (a22 * a00 - a02 * a20) * det;
72502  this.mat3[5] = (-a12 * a00 + a02 * a10) * det;
72503  this.mat3[6] = b21 * det;
72504  this.mat3[7] = (-a21 * a00 + a01 * a20) * det;
72505  this.mat3[8] = (a11 * a00 - a01 * a10) * det;
72506  return this;
72507};
72508
72509/**
72510 * transposes a 3x3 p5.Matrix by a mat3
72511 * @method transpose3x3
72512 * @param  {Number[]} mat3 1-dimensional array
72513 * @chainable
72514 */
72515p5.Matrix.prototype.transpose3x3 = function(mat3) {
72516  var a01 = mat3[1],
72517    a02 = mat3[2],
72518    a12 = mat3[5];
72519  this.mat3[1] = mat3[3];
72520  this.mat3[2] = mat3[6];
72521  this.mat3[3] = a01;
72522  this.mat3[5] = mat3[7];
72523  this.mat3[6] = a02;
72524  this.mat3[7] = a12;
72525  return this;
72526};
72527
72528/**
72529 * converts a 4x4 matrix to its 3x3 inverse tranform
72530 * commonly used in MVMatrix to NMatrix conversions.
72531 * @method invertTranspose
72532 * @param  {p5.Matrix} mat4 the matrix to be based on to invert
72533 * @chainable
72534 * @todo  finish implementation
72535 */
72536p5.Matrix.prototype.inverseTranspose = function(matrix) {
72537  if (this.mat3 === undefined) {
72538    console.error('sorry, this function only works with mat3');
72539  } else {
72540    //convert mat4 -> mat3
72541    this.mat3[0] = matrix.mat4[0];
72542    this.mat3[1] = matrix.mat4[1];
72543    this.mat3[2] = matrix.mat4[2];
72544    this.mat3[3] = matrix.mat4[4];
72545    this.mat3[4] = matrix.mat4[5];
72546    this.mat3[5] = matrix.mat4[6];
72547    this.mat3[6] = matrix.mat4[8];
72548    this.mat3[7] = matrix.mat4[9];
72549    this.mat3[8] = matrix.mat4[10];
72550  }
72551
72552  var inverse = this.invert3x3();
72553  // check inverse succeded
72554  if (inverse) {
72555    inverse.transpose3x3(this.mat3);
72556  } else {
72557    // in case of singularity, just zero the matrix
72558    for (var i = 0; i < 9; i++) {
72559      this.mat
725593[i] = 0;
72560    }
72561  }
72562  return this;
72563};
72564
72565/**
72566 * inspired by Toji's mat4 determinant
72567 * @method determinant
72568 * @return {Number} Determinant of our 4x4 matrix
72569 */
72570p5.Matrix.prototype.determinant = function() {
72571  var d00 = this.mat4[0] * this.mat4[5] - this.mat4[1] * this.mat4[4],
72572    d01 = this.mat4[0] * this.mat4[6] - this.mat4[2] * this.mat4[4],
72573    d02 = this.mat4[0] * this.mat4[7] - this.mat4[3] * this.mat4[4],
72574    d03 = this.mat4[1] * this.mat4[6] - this.mat4[2] * this.mat4[5],
72575    d04 = this.mat4[1] * this.mat4[7] - this.mat4[3] * this.mat4[5],
72576    d05 = this.mat4[2] * this.mat4[7] - this.mat4[3] * this.mat4[6],
72577    d06 = this.mat4[8] * this.mat4[13] - this.mat4[9] * this.mat4[12],
72578    d07 = this.mat4[8] * this.mat4[14] - this.mat4[10] * this.mat4[12],
72579    d08 = this.mat4[8] * this.mat4[15] - this.mat4[11] * this.mat4[12],
72580    d09 = this.mat4[9] * this.mat4[14] - this.mat4[10] * this.mat4[13],
72581    d10 = this.mat4[9] * this.mat4[15] - this.mat4[11] * this.mat4[13],
72582    d11 = this.mat4[10] * this.mat4[15] - this.mat4[11] * this.mat4[14];
72583
72584  // Calculate the determinant
72585  return d00 * d11 - d01 * d10 + d02 * d09 + d03 * d08 - d04 * d07 + d05 * d06;
72586};
72587
72588/**
72589 * multiply two mat4s
72590 * @method mult
72591 * @param {p5.Matrix|Float32Array|Number[]} multMatrix The matrix
72592 *                                                we want to multiply by
72593 * @chainable
72594 */
72595p5.Matrix.prototype.mult = function(multMatrix) {
72596  var _src;
72597
72598  if (multMatrix === this || multMatrix === this.mat4) {
72599    _src = this.copy().mat4; // only need to allocate in this rare case
72600  } else if (multMatrix instanceof p5.Matrix) {
72601    _src = multMatrix.mat4;
72602  } else if (isMatrixArray(multMatrix)) {
72603    _src = multMatrix;
72604  } else {
72605    return; // nothing to do.
72606  }
72607
72608  // each row is used for the multiplier
72609  var b0 = this.mat4[0],
72610    b1 = this.mat4[1],
72611    b2 = this.mat4[2],
72612    b3 = this.mat4[3];
72613  this.mat4[0] = b0 * _src[0] + b1 * _src[4] + b2 * _src[8] + b3 * _src[12];
72614  this.mat4[1] = b0 * _src[1] + b1 * _src[5] + b2 * _src[9] + b3 * _src[13];
72615  this.mat4[2] = b0 * _src[2] + b1 * _src[6] + b2 * _src[10] + b3 * _src[14];
72616  this.mat4[3] = b0 * _src[3] + b1 * _src[7] + b2 * _src[11] + b3 * _src[15];
72617
72618  b0 = this.mat4[4];
72619  b1 = this.mat4[5];
72620  b2 = this.mat4[6];
72621  b3 = this.mat4[7];
72622  this.mat4[4] = b0 * _src[0] + b1 * _src[4] + b2 * _src[8] + b3 * _src[12];
72623  this.mat4[5] = b0 * _src[1] + b1 * _src[5] + b2 * _src[9] + b3 * _src[13];
72624  this.mat4[6] = b0 * _src[2] + b1 * _src[6] + b2 * _src[10] + b3 * _src[14];
72625  this.mat4[7] = b0 * _src[3] + b1 * _src[7] + b2 * _src[11] + b3 * _src[15];
72626
72627  b0 = this.mat4[8];
72628  b1 = this.mat4[9];
72629  b2 = this.mat4[10];
72630  b3 = this.mat4[11];
72631  this.mat4[8] = b0 * _src[0] + b1 * _src[4] + b2 * _src[8] + b3 * _src[12];
72632  this.mat4[9] = b0 * _src[1] + b1 * _src[5] + b2 * _src[9] + b3 * _src[13];
72633  this.mat4[10] = b0 * _src[2] + b1 * _src[6] + b2 * _src[10] + b3 * _src[14];
72634  this.mat4[11] = b0 * _src[3] + b1 * _src[7] + b2 * _src[11] + b3 * _src[15];
72635
72636  b0 = this.mat4[12];
72637  b1 = this.mat4[13];
72638  b2 = this.mat4[14];
72639  b3 = this.mat4[15];
72640  this.mat4[12] = b0 * _src[0] + b1 * _src[4] + b2 * _src[8] + b3 * _src[12];
72641  this.mat4[13] = b0 * _src[1] + b1 * _src[5] + b2 * _src[9] + b3 * _src[13];
72642  this.mat4[14] = b0 * _src[2] + b1 * _src[6] + b2 * _src[10] + b3 * _src[14];
72643  this.mat4[15] = b0 * _src[3] + b1 * _src[7] + b2 * _src[11] + b3 * _src[15];
72644
72645  return this;
72646};
72647
72648/**
72649 * scales a p5.Matrix by scalars or a vector
72650 * @method scale
72651 * @param  {p5.Vector|Float32Array|Number[]} s vector to scale by
72652 * @chainable
72653 */
72654p5.Matrix.prototype.scale = function(x, y, z) {
72655  if (x instanceof p5.Vector) {
72656    // x is a vector, extract the components from it.
72657    y = x.y;
72658    z = x.z;
72659    x = x.x; // must be last
72660  } else if (x instanceof Array) {
72661    // x is an array, extract the components from it.
72662    y = x[1];
72663    z = x[2];
72664    x = x[0]; // must be last
72665  }
72666
72667  this.mat4[0] *= x;
72668  this.mat4[1] *= x;
72669  this.mat4[2] *= x;
72670  this.mat4[3] *= x;
72671  this.mat4[4] *= y;
72672  this.mat4[5] *= y;
72673  this.mat4[6] *= y;
72674  this.mat4[7] *= y;
72675  this.mat4[8] *= z;
72676  this.mat4[9] *= z;
72677  this.mat4[10] *= z;
72678  this.mat4[11] *= z;
72679
72680  return this;
72681};
72682
72683/**
72684 * rotate our Matrix around an axis by the given angle.
72685 * @method rotate
72686 * @param  {Number} a The angle of rotation in radians
72687 * @param  {p5.Vector|Number[]} axis  the axis(es) to rotate around
72688 * @chainable
72689 * inspired by Toji's gl-matrix lib, mat4 rotation
72690 */
72691p5.Matrix.prototype.rotate = function(a, x, y, z) {
72692  var _a = this.p5 ? this.p5._toRadians(a) : a;
72693
72694  if (x instanceof p5.Vector) {
72695    // x is a vector, extract the components from it.
72696    y = x.y;
72697    z = x.z;
72698    x = x.x; //must be last
72699  } else if (x instanceof Array) {
72700    // x is an array, extract the components from it.
72701    y = x[1];
72702    z = x[2];
72703    x = x[0]; //must be last
72704  }
72705
72706  var len = Math.sqrt(x * x + y * y + z * z);
72707  x *= 1 / len;
72708  y *= 1 / len;
72709  z *= 1 / len;
72710
72711  var a00 = this.mat4[0];
72712  var a01 = this.mat4[1];
72713  var a02 = this.mat4[2];
72714  var a03 = this.mat4[3];
72715  var a10 = this.mat4[4];
72716  var a11 = this.mat4[5];
72717  var a12 = this.mat4[6];
72718  var a13 = this.mat4[7];
72719  var a20 = this.mat4[8];
72720  var a21 = this.mat4[9];
72721  var a22 = this.mat4[10];
72722  var a23 = this.mat4[11];
72723
72724  //sin,cos, and tan of respective angle
72725  var sA = Math.sin(_a);
72726  var cA = Math.cos(_a);
72727  var tA = 1 - cA;
72728  // Construct the elements of the rotation matrix
72729  var b00 = x * x * tA + cA;
72730  var b01 = y * x * tA + z * sA;
72731  var b02 = z * x * tA - y * sA;
72732  var b10 = x * y * tA - z * sA;
72733  var b11 = y * y * tA + cA;
72734  var b12 = z * y * tA + x * sA;
72735  var b20 = x * z * tA + y * sA;
72736  var b21 = y * z * tA - x * sA;
72737  var b22 = z * z * tA + cA;
72738
72739  // rotation-specific matrix multiplication
72740  this.mat4[0] = a00 * b00 + a10 * b01 + a20 * b02;
72741  this.mat4[1] = a01 * b00 + a11 * b01 + a21 * b02;
72742  this.mat4[2] = a02 * b00 + a12 * b01 + a22 * b02;
72743  this.mat4[3] = a03 * b00 + a13 * b01 + a23 * b02;
72744  this.mat4[4] = a00 * b10 + a10 * b11 + a20 * b12;
72745  this.mat4[5] = a01 * b10 + a11 * b11 + a21 * b12;
72746  this.mat4[6] = a02 * b10 + a12 * b11 + a22 * b12;
72747  this.mat4[7] = a03 * b10 + a13 * b11 + a23 * b12;
72748  this.mat4[8] = a00 * b20 + a10 * b21 + a20 * b22;
72749  this.mat4[9] = a01 * b20 + a11 * b21 + a21 * b22;
72750  this.mat4[10] = a02 * b20 + a12 * b21 + a22 * b22;
72751  this.mat4[11] = a03 * b20 + a13 * b21 + a23 * b22;
72752
72753  return this;
72754};
72755
72756/**
72757 * @todo  finish implementing this method!
72758 * translates
72759 * @method translate
72760 * @param  {Number[]} v vector to translate by
72761 * @chainable
72762 */
72763p5.Matrix.prototype.translate = function(v) {
72764  var x = v[0],
72765    y = v[1],
72766    z = v[2] || 0;
72767  this.mat4[12] += this.mat4[0] * x + this.mat4[4] * y + this.mat4[8] * z;
72768  this.mat4[13] += this.mat4[1] * x + this.mat4[5] * y + this.mat4[9] * z;
72769  this.mat4[14] += this.mat4[2] * x + this.mat4[6] * y + this.mat4[10] * z;
72770  this.mat4[15] += this.mat4[3] * x + this.mat4[7] * y + this.mat4[11] * z;
72771};
72772
72773p5.Matrix.prototype.rotateX = function(a) {
72774  this.rotate(a, 1, 0, 0);
72775};
72776p5.Matrix.prototype.rotateY = function(a) {
72777  this.rotate(a, 0, 1, 0);
72778};
72779p5.Matrix.prototype.rotateZ = function(a) {
72780  this.rotate(a, 0, 0, 1);
72781};
72782
72783/**
72784 * sets the perspective matrix
72785 * @method perspective
72786 * @param  {Number} fovy   [description]
72787 * @param  {Number} aspect [description]
72788 * @param  {Number} near   near clipping plane
72789 * @param  {Number} far    far clipping plane
72790 * @chainable
72791 */
72792p5.Matrix.prototype.perspective = function(fovy, aspect, near, far) {
72793  var f = 1.0 / Math.tan(fovy / 2),
72794    nf = 1 / (near - far);
72795
72796  this.mat4[0] = f / aspect;
72797  this.mat4[1] = 0;
72798  this.mat4[2] = 0;
72799  this.mat4[3] = 0;
72800  this.mat4[4] = 0;
72801  this.mat4[5] = f;
72802  this.mat4[6] = 0;
72803  this.mat4[7] = 0;
72804  this.mat4[8] = 0;
72805  this.mat4[9] = 0;
72806  this.mat4[10] = (far + near) * nf;
72807  this.mat4[11] = -1;
72808  this.mat4[12] = 0;
72809  this.mat4[13] = 0;
72810  this.mat4[14] = 2 * far * near * nf;
72811  this.mat4[15] = 0;
72812
72813  return this;
72814};
72815
72816/**
72817 * sets the ortho matrix
72818 * @method ortho
72819 * @param  {Number} left   [description]
72820 * @param  {Number} right  [description]
72821 * @param  {Number} bottom [description]
72822 * @param  {Number} top    [description]
72823 * @param  {Number} near   near clipping plane
72824 * @param  {Number} far    far clipping plane
72825 * @chainable
72826 */
72827p5.Matrix.prototype.ortho = function(left, right, bottom, top, near, far) {
72828  var lr = 1 / (left - right),
72829    bt = 1 / (bottom - top),
72830    nf = 1 / (near - far);
72831  this.mat4[0] = -2 * lr;
72832  this.mat4[1] = 0;
72833  this.mat4[2] = 0;
72834  this.mat4[3] = 0;
72835  this.mat4[4] = 0;
72836  this.mat4[5] = -2 * bt;
72837  this.mat4[6] = 0;
72838  this.mat4[7] = 0;
72839  this.mat4[8] = 0;
72840  this.mat4[9] = 0;
72841  this.mat4[10] = 2 * nf;
72842  this.mat4[11] = 0;
72843  this.mat4[12] = (left + right) * lr;
72844  this.mat4[13] = (top + bottom) * bt;
72845  this.mat4[14] = (far + near) * nf;
72846  this.mat4[15] = 1;
72847
72848  return this;
72849};
72850
72851/**
72852 * PRIVATE
72853 */
72854// matrix methods adapted from:
72855// https://developer.mozilla.org/en-US/docs/Web/WebGL/
72856// gluPerspective
72857//
72858// function _makePerspective(fovy, aspect, znear, zfar){
72859//    var ymax = znear * Math.tan(fovy * Math.PI / 360.0);
72860//    var ymin = -ymax;
72861//    var xmin = ymin * aspect;
72862//    var xmax = ymax * aspect;
72863//    return _makeFrustum(xmin, xmax, ymin, ymax, znear, zfar);
72864//  }
72865
72866////
72867//// glFrustum
72868////
72869//function _makeFrustum(left, right, bottom, top, znear, zfar){
72870//  var X = 2*znear/(right-left);
72871//  var Y = 2*znear/(top-bottom);
72872//  var A = (right+left)/(right-left);
72873//  var B = (top+bottom)/(top-bottom);
72874//  var C = -(zfar+znear)/(zfar-znear);
72875//  var D = -2*zfar*znear/(zfar-znear);
72876//  var frustrumMatrix =[
72877//  X, 0, A, 0,
72878//  0, Y, B, 0,
72879//  0, 0, C, D,
72880//  0, 0, -1, 0
72881//];
72882//return frustrumMatrix;
72883// }
72884
72885// function _setMVPMatrices(){
72886////an identity matrix
72887////@TODO use the p5.Matrix class to abstract away our MV matrices and
72888///other math
72889//var _mvMatrix =
72890//[
72891//  1.0,0.0,0.0,0.0,
72892//  0.0,1.0,0.0,0.0,
72893//  0.0,0.0,1.0,0.0,
72894//  0.0,0.0,0.0,1.0
72895//];
72896
72897module.exports = p5.Matrix;
72898
72899},{"../core/core":22}],70:[function(_dereq_,module,exports){
72900/**
72901 * Welcome to RendererGL Immediate Mode.
72902 * Immediate mode is used for drawing custom shapes
72903 * from a set of vertices.  Immediate Mode is activated
72904 * when you call beginShape() & de-activated when you call endShape().
72905 * Immediate mode is a style of programming borrowed
72906 * from OpenGL's (now-deprecated) immediate mode.
72907 * It differs from p5.js' default, Retained Mode, which caches
72908 * geometries and buffers on the CPU to reduce the number of webgl
72909 * draw calls. Retained mode is more efficient & performative,
72910 * however, Immediate Mode is useful for sketching quick
72911 * geometric ideas.
72912 */
72913'use strict';
72914
72915var p5 = _dereq_('../core/core');
72916var constants = _dereq_('../core/constants');
72917
72918/**
72919 * Begin shape drawing.  This is a helpful way of generating
72920 * custom shapes quickly.  However in WEBGL mode, application
72921 * performance will likely drop as a result of too many calls to
72922 * beginShape() / endShape().  As a high performance alternative,
72923 * please use p5.js geometry primitives.
72924 * @private
72925 * @method beginShape
72926 * @param  {Number} mode webgl primitives mode.  beginShape supports the
72927 *                       following modes:
72928 *                       POINTS,LINES,LINE_STRIP,LINE_LOOP,TRIANGLES,
72929 *                       TRIANGLE_STRIP,and TRIANGLE_FAN.
72930 * @chainable
72931 */
72932p5.RendererGL.prototype.beginShape = function(mode) {
72933  //default shape mode is line_strip
72934  this.immediateMode.shapeMode =
72935    mode !== undefined ? mode : constants.LINE_STRIP;
72936  //if we haven't yet initialized our
72937  //immediateMode vertices & buffers, create them now!
72938  if (this.immediateMode.vertices === undefined) {
72939    this.immediateMode.vertices = [];
72940    this.immediateMode.edges = [];
72941    this.immediateMode.lineVertices = [];
72942    this.immediateMode.vertexColors = [];
72943    this.immediateMode.lineNormals = [];
72944    this.immediateMode.uvCoords = [];
72945    this.immediateMode.vertexBuffer = this.GL.createBuffer();
72946    this.immediateMode.colorBuffer = this.GL.createBuffer();
72947    this.immediateMode.uvBuffer = this.GL.createBuffer();
72948    this.immediateMode.lineVertexBuffer = this.GL.createBuffer();
72949    this.immediateMode.lineNormalBuffer = this.GL.createBuffer();
72950  } else {
72951    this.immediateMode.vertices.length = 0;
72952    this.immediateMode.edges.length = 0;
72953    this.immediateMode.lineVertices.length = 0;
72954    this.immediateMode.lineNormals.length = 0;
72955    this.immediateMode.vertexColors.length = 0;
72956    this.immediateMode.uvCoords.length = 0;
72957  }
72958  this.isImmediateDrawing = true;
72959  return this;
72960};
72961/**
72962 * adds a vertex to be drawn in a custom Shape.
72963 * @private
72964 * @method vertex
72965 * @param  {Number} x x-coordinate of vertex
72966 * @param  {Number} y y-coordinate of vertex
72967 * @param  {Number} z z-coordinate of vertex
72968 * @chainable
72969 * @TODO implement handling of p5.Vector args
72970 */
72971p5.RendererGL.prototype.vertex = function(x, y) {
72972  var z, u, v;
72973
72974  // default to (x, y) mode: all other arugments assumed to be 0.
72975  z = u = v = 0;
72976
72977  if (arguments.length === 3) {
72978    // (x, y, z) mode: (u, v) assumed to be 0.
72979    z = arguments[2];
72980  } else if (arguments.length === 4) {
72981    // (x, y, u, v) mode: z assumed to be 0.
72982    u = arguments[2];
72983    v = arguments[3];
72984  } else if (arguments.length === 5) {
72985    // (x, y, z, u, v) mode
72986    z = arguments[2];
72987    u = arguments[3];
72988    v = arguments[4];
72989  }
72990  var vert = new p5.Vector(x, y, z);
72991  this.immediateMode.vertices.push(vert);
72992  var vertexColor = this.curFillColor || [0.5, 0.5, 0.5, 1.0];
72993  this.immediateMode.vertexColors.push(
72994    vertexColor[0],
72995    vertexColor[1],
72996    vertexColor[2],
72997    vertexColor[3]
72998  );
72999
73000  this.immediateMode.uvCoords.push(u, v);
73001
73002  return this;
73003};
73004
73005/**
73006 * End shape drawing and render vertices to screen.
73007 * @chainable
73008 */
73009p5.RendererGL.prototype.endShape = function(
73010  mode,
73011  isCurve,
73012  isBezier,
73013  isQuadratic,
73014  isContour,
73015  shapeKind
73016) {
73017  this._useImmediateModeShader();
73018
73019  if (this._doStroke && this.drawMode !== constants.TEXTURE) {
73020    for (var i = 0; i < this.immediateMode.vertices.length - 1; i++) {
73021      this.immediateMode.edges.push([i, i + 1]);
73022    }
73023    if (mode === constants.CLOSE) {
73024      this.immediateMode.edges.push([
73025        this.immediateMode.vertices.length - 1,
73026        0
73027      ]);
73028    }
73029
73030    p5.Geometry.prototype._edgesToVertices.call(this.immediateMode);
73031    this._drawStrokeImmediateMode();
73032  }
73033  if (this._doFill) {
73034    this._drawFillImmediateMode(
73035      mode,
73036      isCurve,
73037      isBezier,
73038      isQuadratic,
73039      isContour,
73040      shapeKind
73041    );
73042  }
73043  //clear out our vertexPositions & colors arrays
73044  //after rendering
73045  this.immediateMode.vertices.length = 0;
73046  this.immediateMode.vertexColors.length = 0;
73047  this.immediateMode.uvCoords.length = 0;
73048  this.isImmediateDrawing = false;
73049
73050  return this;
73051};
73052
73053p5.RendererGL.prototype._drawFillImmediateMode = function(
73054  mode,
73055  isCurve,
73056  isBezier,
73057  isQuadratic,
73058  isContour,
73059  shapeKind
73060) {
73061  var gl = this.GL;
73062  this.curFillShader.bindShader();
73063
73064  // initialize the fill shader's 'aPosition' buffer
73065  if (this.curFillShader.attributes.aPosition) {
73066    //vertex position Attribute
73067    this._bindBuffer(
73068      this.immediateMode.vertexBuffer,
73069      gl.ARRAY_BUFFER,
73070      this._vToNArray(this.immediateMode.vertices),
73071      Float32Array,
73072      gl.DYNAMIC_DRAW
73073    );
73074
73075    this.curFillShader.enableAttrib(
73076      this.curFillShader.attributes.aPosition.location,
73077      3,
73078      gl.FLOAT,
73079      false,
73080      0,
73081      0
73082    );
73083  }
73084
73085  // initialize the fill shader's 'aVertexColor' buffer
73086  if (
73087    this.drawMode === constants.FILL &&
73088    this.curFillShader.attributes.aVertexColor
73089  ) {
73090    this._bindBuffer(
73091      this.immediateMode.colorBuffer,
73092      gl.ARRAY_BUFFER,
73093      this.immediateMode.vertexColors,
73094      Float32Array,
73095      gl.DYNAMIC_DRAW
73096    );
73097
73098    this.curFillShader.enableAttrib(
73099      this.curFillShader.attributes.aVertexColor.location,
73100      4,
73101      gl.FLOAT,
73102      false,
73103      0,
73104      0
73105    );
73106  }
73107
73108  // initialize the fill shader's 'aTexCoord' buffer
73109  if (
73110    this.drawMode === constants.TEXTURE &&
73111    this.curFillShader.attributes.aTexCoord
73112  ) {
73113    //texture coordinate Attribute
73114    this._bindBuffer(
73115      this.immediateMode.uvBuffer,
73116      gl.ARRAY_BUFFER,
73117      this.immediateMode.uvCoords,
73118      Float32Array,
73119      gl.DYNAMIC_DRAW
73120    );
73121
73122    this.curFillShader.enableAttrib(
73123      this.curFillShader.attributes.aTexCoord.location,
73124      2,
73125      gl.FLOAT,
73126      false,
73127      0,
73128      0
73129    );
73130  }
73131
73132  //if (true || mode) {
73133  if (this.drawMode === constants.FILL || this.drawMode === constants.TEXTURE) {
73134    switch (this.immediateMode.shapeMode) {
73135      case constants.LINE_STRIP:
73136      case constants.LINES:
73137      case constants.TRIANGLES:
73138        this.immediateMode.shapeMode = constants.TRIANGLE_FAN;
73139        break;
73140    }
73141  } else {
73142    switch (this.immediateMode.shapeMode) {
73143      case constants.LINE_STRIP:
73144      case constants.LINES:
73145        this.immediateMode.shapeMode = constants.LINE_LOOP;
73146        break;
73147    }
73148  }
73149  //}
73150  //QUADS & QUAD_STRIP are not supported primitives modes
73151  //in webgl.
73152  if (
73153    this.immediateMode.shapeMode === constants.QUADS ||
73154    this.immediateMode.shapeMode === constants.QUAD_STRIP
73155  ) {
73156    throw new Error(
73157      'sorry, ' +
73158        this.immediateMode.shapeMode +
73159        ' not yet implemented in webgl mode.'
73160    );
73161  } else {
73162    this._applyColorBlend(this.curFillColor);
73163    gl.enable(gl.BLEND);
73164    gl.drawArrays(
73165      this.immediateMode.shapeMode,
73166      0,
73167      this.immediateMode.vertices.length
73168    );
73169  }
73170  // todo / optimizations? leave bound until another shader is set?
73171  this.curFillShader.unbindShader();
73172};
73173
73174p5.RendererGL.prototype._drawStrokeImmediateMode = function() {
73175  var gl = this.GL;
73176  this.curStrokeShader.bindShader();
73177
73178  // initialize the stroke shader's 'aPosition' buffer
73179  if (this.curStrokeShader.attributes.aPosition) {
73180    this._bindBuffer(
73181      this.immediateMode.lineVertexBuffer,
73182      gl.ARRAY_BUFFER,
73183      this._flatten(this.immediateMode.lineVertices),
73184      Float32Array,
73185      gl.STATIC_DRAW
73186    );
73187
73188    this.curStrokeShader.enableAttrib(
73189      this.curStrokeShader.attributes.aPosition.location,
73190      3,
73191      gl.FLOAT,
73192      false,
73193      0,
73194      0
73195    );
73196  }
73197
73198  // initialize the stroke shader's 'aDirection' buffer
73199  if (this.curStrokeShader.attributes.aDirection) {
73200    this._bindBuffer(
73201      this.immediateMode.lineNormalBuffer,
73202      gl.ARRAY_BUFFER,
73203      this._flatten(this.immediateMode.lineNormals),
73204      Float32Array,
73205      gl.STATIC_DRAW
73206    );
73207    this.curStrokeShader.enableAttrib(
73208      this.curStrokeShader.attributes.aDirection.location,
73209      4,
73210      gl.FLOAT,
73211      false,
73212      0,
73213      0
73214    );
73215  }
73216
73217  this._applyColorBlend(this.curStrokeColor);
73218  gl.drawArrays(gl.TRIANGLES, 0, this.immediateMode.lineVertices.length);
73219
73220  // todo / optimizations? leave bound until another shader is set?
73221  this.curStrokeShader.unbindShader();
73222};
73223
73224module.exports = p5.RendererGL;
73225
73226},{"../core/constants":21,"../core/core":22}],71:[function(_dereq_,module,exports){
73227//Retained Mode. The default mode for rendering 3D primitives
73228//in WEBGL.
73229'use strict';
73230
73231var p5 = _dereq_('../core/core');
73232
73233var hashCount = 0;
73234/**
73235 * _initBufferDefaults
73236 * @private
73237 * @description initializes buffer defaults. runs each time a new geometry is
73238 * registered
73239 * @param  {String} gId  key of the geometry object
73240 */
73241p5.RendererGL.prototype._initBufferDefaults = function(gId) {
73242  this._freeBuffers(gId);
73243
73244  //@TODO remove this limit on hashes in gHash
73245  hashCount++;
73246  if (hashCount > 1000) {
73247    var key = Object.keys(this.gHash)[0];
73248    delete this.gHash[key];
73249    hashCount--;
73250  }
73251
73252  //create a new entry in our gHash
73253  this.gHash[gId] = {};
73254};
73255
73256p5.RendererGL.prototype._freeBuffers = function(gId) {
73257  var geometry = this.gHash[gId];
73258  if (!geometry) {
73259    return;
73260  }
73261
73262  delete this.gHash[gId];
73263  hashCount--;
73264
73265  var gl = this.GL;
73266  geometry.vertexBuffer && gl.deleteBuffer(geometry.vertexBuffer);
73267  geometry.normalBuffer && gl.deleteBuffer(geometry.normalBuffer);
73268  geometry.lineNormalBuffer && gl.deleteBuffer(geometry.lineNormalBuffer);
73269  geometry.uvBuffer && gl.deleteBuffer(geometry.uvBuffer);
73270  geometry.indexBuffer && gl.deleteBuffer(geometry.indexBuffer);
73271  geometry.lineVertexBuffer && gl.deleteBuffer(geometry.lineVertexBuffer);
73272};
73273/**
73274 * createBuffers description
73275 * @private
73276 * @param  {String} gId    key of the geometry object
73277 * @param  {p5.Geometry}  obj contains geometry data
73278 */
73279p5.RendererGL.prototype.createBuffers = function(gId, obj) {
73280  var gl = this.GL;
73281  this._setDefaultCamera();
73282  //initialize the gl buffers for our geom groups
73283  this._initBufferDefaults(gId);
73284
73285  var geometry = this.gHash[gId];
73286
73287  geometry.numberOfItems = obj.faces.length * 3;
73288  geometry.lineVertexCount = obj.lineVertices.length;
73289
73290  this._useColorShader();
73291
73292  // initialize the stroke shader's 'aPosition' buffer, if used
73293  if (this.curStrokeShader.attributes.aPosition) {
73294    geometry.lineVertexBuffer = gl.createBuffer();
73295
73296    this._bindBuffer(
73297      geometry.lineVertexBuffer,
73298      gl.ARRAY_BUFFER,
73299      this._flatten(obj.lineVertices),
73300      Float32Array,
73301      gl.STATIC_DRAW
73302    );
73303
73304    this.curStrokeShader.enableAttrib(
73305      this.curStrokeShader.attributes.aPosition.location,
73306      3,
73307      gl.FLOAT,
73308      false,
73309      0,
73310      0
73311    );
73312  }
73313
73314  // initialize the stroke shader's 'aDirection' buffer, if used
73315  if (this.curStrokeShader.attributes.aDirection) {
73316    geometry.lineNormalBuffer = gl.createBuffer();
73317
73318    this._bindBuffer(
73319      geometry.lineNormalBuffer,
73320      gl.ARRAY_BUFFER,
73321      this._flatten(obj.lineNormals),
73322      Float32Array,
73323      gl.STATIC_DRAW
73324    );
73325
73326    this.curStrokeShader.enableAttrib(
73327      this.curStrokeShader.attributes.aDirection.location,
73328      4,
73329      gl.FLOAT,
73330      false,
73331      0,
73332      0
73333    );
73334  }
73335
73336  // initialize the fill shader's 'aPosition' buffer, if used
73337  if (this.curFillShader.attributes.aPosition) {
73338    geometry.vertexBuffer = gl.createBuffer();
73339
73340    // allocate space for vertex positions
73341    this._bindBuffer(
73342      geometry.vertexBuffer,
73343      gl.ARRAY_BUFFER,
73344      this._vToNArray(obj.vertices),
73345      Float32Array,
73346      gl.STATIC_DRAW
73347    );
73348
73349    this.curFillShader.enableAttrib(
73350      this.curFillShader.attributes.aPosition.location,
73351      3,
73352      gl.FLOAT,
73353      false,
73354      0,
73355      0
73356    );
73357  }
73358
73359  // allocate space for faces
73360  geometry.indexBuffer = gl.createBuffer();
73361  this._bindBuffer(
73362    geometry.indexBuffer,
73363    gl.ELEMENT_ARRAY_BUFFER,
73364    this._flatten(obj.faces),
73365    Uint16Array,
73366    gl.STATIC_DRAW
73367  );
73368
73369  // initialize the fill shader's 'aNormal' buffer, if used
73370  if (this.curFillShader.attributes.aNormal) {
73371    geometry.normalBuffer = gl.createBuffer();
73372
73373    // allocate space for normals
73374    this._bindBuffer(
73375      geometry.normalBuffer,
73376      gl.ARRAY_BUFFER,
73377      this._vToNArray(obj.vertexNormals),
73378      Float32Array,
73379      gl.STATIC_DRAW
73380    );
73381
73382    this.curFillShader.enableAttrib(
73383      this.curFillShader.attributes.aNormal.location,
73384      3,
73385      gl.FLOAT,
73386      false,
73387      0,
73388      0
73389    );
73390  }
73391
73392  // initialize the fill shader's 'aTexCoord' buffer, if used
73393  if (this.curFillShader.attributes.aTexCoord) {
73394    geometry.uvBuffer = gl.createBuffer();
73395
73396    // tex coords
73397    this._bindBuffer(
73398      geometry.uvBuffer,
73399      gl.ARRAY_BUFFER,
73400      this._flatten(obj.uvs),
73401      Float32Array,
73402      gl.STATIC_DRAW
73403    );
73404
73405    this.curFillShader.enableAttrib(
73406      this.curFillShader.attributes.aTexCoord.location,
73407      2,
73408      gl.FLOAT,
73409      false,
73410      0,
73411      0
73412    );
73413  }
73414  //}
73415};
73416
73417/**
73418 * Draws buffers given a geometry key ID
73419 * @private
73420 * @param  {String} gId     ID in our geom hash
73421 * @chainable
73422 */
73423p5.RendererGL.prototype.drawBuffers = function(gId) {
73424  this._setDefaultCamera();
73425  var gl = this.GL;
73426  this._useColorShader();
73427  var geometry = this.gHash[gId];
73428
73429  if (this._doStroke && geometry.lineVertexCount > 0) {
73430    this.curStrokeShader.bindShader();
73431
73432    // bind the stroke shader's 'aPosition' buffer
73433    if (geometry.lineVertexBuffer) {
73434      this._bindBuffer(geometry.lineVertexBuffer, gl.ARRAY_BUFFER);
73435      this.curStrokeShader.enableAttrib(
73436        this.curStrokeShader.attributes.aPosition.location,
73437        3,
73438        gl.FLOAT,
73439        false,
73440        0,
73441        0
73442      );
73443    }
73444
73445    // bind the stroke shader's 'aDirection' buffer
73446    if (geometry.lineNormalBuffer) {
73447      this._bindBuffer(geometry.lineNormalBuffer, gl.ARRAY_BUFFER);
73448      this.curStrokeShader.enableAttrib(
73449        this.curStrokeShader.attributes.aDirection.location,
73450        4,
73451        gl.FLOAT,
73452        false,
73453        0,
73454        0
73455      );
73456    }
73457
73458    this._applyColorBlend(this.curStrokeColor);
73459    this._drawArrays(gl.TRIANGLES, gId);
73460    this.curStrokeShader.unbindShader();
73461  }
73462
73463  if (this._doFill !== false) {
73464    this.curFillShader.bindShader();
73465
73466    // bind the fill shader's 'aPosition' buffer
73467    if (geometry.vertexBuffer) {
73468      //vertex position buffer
73469      this._bindBuffer(geometry.vertexBuffer, gl.ARRAY_BUFFER);
73470      this.curFillShader.enableAttrib(
73471        this.curFillShader.attributes.aPosition.location,
73472        3,
73473        gl.FLOAT,
73474        false,
73475        0,
73476        0
73477      );
73478    }
73479
73480    if (geometry.indexBuffer) {
73481      //vertex index buffer
73482      this._bindBuffer(geometry.indexBuffer, gl.ELEMENT_ARRAY_BUFFER);
73483    }
73484
73485    // bind the fill shader's 'aNormal' buffer
73486    if (geometry.normalBuffer) {
73487      this._bindBuffer(geometry.normalBuffer, gl.ARRAY_BUFFER);
73488      this.curFillShader.enableAttrib(
73489        this.curFillShader.attributes.aNormal.location,
73490        3,
73491        gl.FLOAT,
73492        false,
73493        0,
73494        0
73495      );
73496    }
73497
73498    // bind the fill shader's 'aTexCoord' buffer
73499    if (geometry.uvBuffer) {
73500      // uv buffer
73501      this._bindBuffer(geometry.uvBuffer, gl.ARRAY_BUFFER);
73502      this.curFillShader.enableAttrib(
73503        this.curFillShader.attributes.aTexCoord.location,
73504        2,
73505        gl.FLOAT,
73506        false,
73507        0,
73508        0
73509      );
73510    }
73511
73512    this._applyColorBlend(this.curFillColor);
73513    this._drawElements(gl.TRIANGLES, gId);
73514    this.curFillShader.unbindShader();
73515  }
73516  return this;
73517};
73518
73519/**
73520 * Calls drawBuffers() with a scaled model/view matrix.
73521 *
73522 * This is used by various 3d primitive methods (in primitives.js, eg. plane,
73523 * box, torus, etc...) to allow caching of un-scaled geometries. Those
73524 * geometries are generally created with unit-length dimensions, cached as
73525 * such, and then scaled appropriately in this method prior to rendering.
73526 *
73527 * @private
73528 * @method drawBuffersScaled
73529 * @param {String} gId     ID in our geom hash
73530 * @param {Number} scaleX  the amount to scale in the X direction
73531 * @param {Number} scaleY  the amount to scale in the Y direction
73532 * @param {Number} scaleZ  the amount to scale in the Z direction
73533 */
73534p5.RendererGL.prototype.drawBuffersScaled = function(
73535  gId,
73536  scaleX,
73537  scaleY,
73538  scaleZ
73539) {
73540  var uMVMatrix = this.uMVMatrix.copy();
73541  try {
73542    this.uMVMatrix.scale(scaleX, scaleY, scaleZ);
73543    this.drawBuffers(gId);
73544  } finally {
73545    this.uMVMatrix = uMVMatrix;
73546  }
73547};
73548
73549p5.RendererGL.prototype._drawArrays = function(drawMode, gId) {
73550  this.GL.drawArrays(drawMode, 0, this.gHash[gId].lineVertexCount);
73551  return this;
73552};
73553
73554p5.RendererGL.prototype._drawElements = function(drawMode, gId) {
73555  this.GL.drawElements(
73556    drawMode,
73557    this.gHash[gId].numberOfItems,
73558    this.GL.UNSIGNED_SHORT,
73559    0
73560  );
73561};
73562
73563module.exports = p5.RendererGL;
73564
73565},{"../core/core":22}],72:[function(_dereq_,module,exports){
73566'use strict';
73567
73568var p5 = _dereq_('../core/core');
73569var constants = _dereq_('../core/constants');
73570_dereq_('./p5.Shader');
73571_dereq_('../core/p5.Renderer');
73572_dereq_('./p5.Matrix');
73573
73574
73575var defaultShaders = {
73576  immediateVert: "attribute vec3 aPosition;\nattribute vec4 aVertexColor;\n\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\nuniform float uResolution;\nuniform float uPointSize;\n\nvarying vec4 vColor;
73576\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",
73577  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);\n  gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;\n  vColor = aVertexColor;\n}\n",
73578  vertexColorFrag: "precision mediump float;\nvarying vec4 vColor;\nvoid main(void) {\n  gl_FragColor = vColor;\n}",
73579  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",
73580  normalFrag: "precision mediump float;\nvarying vec3 vVertexNormal;\nvoid main(void) {\n  gl_FragColor = vec4(vVertexNormal, 1.0);\n}",
73581  basicFrag: "precision mediump float;\nvarying vec3 vVertexNormal;\nuniform vec4 uMaterialColor;\nvoid main(void) {\n  gl_FragColor = uMaterialColor;\n}",
73582  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
73582);\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",
73583  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}",
73584  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
73584);\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",
73585  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}",
73586  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;\nvec3 scale = vec3(1.0);\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
73586omponents 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",
73587  lineFrag: "precision mediump float;\nprecision mediump int;\n\nuniform vec4 uMaterialColor;\n\nvoid main() {\n  gl_FragColor = uMaterialColor;\n}"
73588};
73589
73590/**
73591 * 3D graphics class
73592 * @private
73593 * @class p5.RendererGL
73594 * @constructor
73595 * @extends p5.Renderer
73596 * @todo extend class to include public method for offscreen
73597 * rendering (FBO).
73598 *
73599 */
73600p5.RendererGL = function(elt, pInst, isMainCanvas, attr) {
73601  p5.Renderer.call(this, elt, pInst, isMainCanvas);
73602  this.attributes = {};
73603  attr = attr || {};
73604  this.attributes.alpha = attr.alpha === undefined ? true : attr.alpha;
73605  this.attributes.depth = attr.depth === undefined ? true : attr.depth;
73606  this.attributes.stencil = attr.stencil === undefined ? true : attr.stencil;
73607  this.attributes.antialias =
73608    attr.antialias === undefined ? false : attr.antialias;
73609  this.attributes.premultipliedAlpha =
73610    attr.premultipliedAlpha === undefined ? false : attr.premultipliedAlpha;
73611  this.attributes.preserveDrawingBuffer =
73612    attr.preserveDrawingBuffer === undefined
73613      ? true
73614      : attr.preserveDrawingBuffer;
73615  this.attributes.perPixelLighting =
73616    attr.perPixelLighting === undefined ? false : attr.perPixelLighting;
73617  this._initContext();
73618  this.isP3D = true; //lets us know we're in 3d mode
73619  this.GL = this.drawingContext;
73620
73621  // lights
73622
73623  this.ambientLightColors = [];
73624  this.directionalLightDirections = [];
73625  this.directionalLightColors = [];
73626
73627  this.pointLightPositions = [];
73628  this.pointLightColors = [];
73629
73630  /**
73631   * model view, projection, & normal
73632   * matrices
73633   */
73634  this.uMVMatrix = new p5.Matrix();
73635  this.uPMatrix = new p5.Matrix();
73636  this.uNMatrix = new p5.Matrix('mat3');
73637
73638  // Camera
73639  this._curCamera = null;
73640  // default camera settings, then use those to populate camera fields.
73641  this._computeCameraDefaultSettings();
73642  this.cameraFOV = this.defaultCameraFOV;
73643  this.cameraAspect = this.defaultAspect;
73644  this.cameraX = this.defaultCameraX;
73645  this.cameraY = this.defaultCameraY;
73646  this.cameraZ = this.defaultCameraZ;
73647  this.cameraNear = this.defaultCameraNear;
73648  this.cameraFar = this.defaultCameraFar;
73649  this.cameraMatrix = new p5.Matrix();
73650  this.camera(); // set default camera matrices
73651
73652  //Geometry & Material hashes
73653  this.gHash = {};
73654
73655  this._defaultLightShader = undefined;
73656  this._defaultImmediateModeShader = undefined;
73657  this._defaultNormalShader = undefined;
73658  this._defaultColorShader = undefined;
73659
73660  this.curFillShader = undefined;
73661  this.curStrokeShader = undefined;
73662
73663  this._useColorShader();
73664  this.setStrokeShader(this._getLineShader());
73665
73666  //Imediate Mode
73667  //default drawing is done in Retained Mode
73668  this.isImmediateDrawing = false;
73669  this.immediateMode = {};
73670
73671  // note: must call fill() and stroke () AFTER
73672  // default shader has been set.
73673  this.fill(255, 255, 255, 255);
73674  //this.stroke(0, 0, 0, 255);
73675  this.pointSize = 5.0; //default point size
73676  this.strokeWeight(2);
73677  this.stroke(0, 0, 0);
73678  // array of textures created in this gl context via this.getTexture(src)
73679  this.textures = [];
73680  return this;
73681};
73682
73683p5.RendererGL.prototype = Object.create(p5.Renderer.prototype);
73684
73685//////////////////////////////////////////////
73686// Setting
73687//////////////////////////////////////////////
73688
73689p5.RendererGL.prototype._initContext = function() {
73690  try {
73691    this.drawingContext =
73692      this.canvas.getContext('webgl', this.attributes) ||
73693      this.canvas.getContext('experimental-webgl', this.attributes);
73694    if (this.drawingContext === null) {
73695      throw new Error('Error creating webgl context');
73696    } else {
73697      console.log('p5.RendererGL: enabled webgl context');
73698      var gl = this.drawingContext;
73699      gl.enable(gl.DEPTH_TEST);
73700      gl.depthFunc(gl.LEQUAL);
73701      gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
73702      this._viewport = this.drawingContext.getParameter(
73703        this.drawingContext.VIEWPORT
73704      );
73705    }
73706  } catch (er) {
73707    throw new Error(er);
73708  }
73709};
73710
73711//This is helper function to reset the context anytime the attributes
73712//are changed with setAttributes()
73713
73714p5.RendererGL.prototype._resetContext = function(attr, options, callback) {
73715  var w = this.width;
73716  var h = this.height;
73717  var defaultId = this.canvas.id;
73718  var c = this.canvas;
73719  if (c) {
73720    c.parentNode.removeChild(c);
73721  }
73722  c = document.createElement('canvas');
73723  c.id = defaultId;
73724  if (this._pInst._userNode) {
73725    this._pInst._userNode.appendChild(c);
73726  } else {
73727    document.body.appendChild(c);
73728  }
73729  this._pInst.canvas = c;
73730
73731  var renderer = new p5.RendererGL(this._pInst.canvas, this._pInst, true, attr);
73732  this._pInst._setProperty('_renderer', renderer);
73733  renderer.resize(w, h);
73734  renderer._applyDefaults();
73735  this._pInst._elements.push(renderer);
73736
73737  if (typeof callback === 'function') {
73738    //setTimeout with 0 forces the task to the back of the queue, this ensures that
73739    //we finish switching out the renderer
73740    setTimeout(function() {
73741      callback.apply(window._renderer, options);
73742    }, 0);
73743  }
73744};
73745/**
73746 * @module Rendering
73747 * @submodule Rendering
73748 * @for p5
73749 */
73750/**
73751 * Set attributes for the WebGL Drawing context.
73752 * This is a way of adjusting ways that the WebGL
73753 * renderer works to fine-tune the display and performance.
73754 * This should be put in setup().
73755 * The available attributes are:
73756 * <br>
73757 * alpha - indicates if the canvas contains an alpha buffer
73758 * default is true
73759 * <br><br>
73760 * depth - indicates whether the drawing buffer has a depth buffer
73761 * of at least 16 bits - default is true
73762 * <br><br>
73763 * stencil - indicates whether the drawing buffer has a stencil buffer
73764 * of at least 8 bits
73765 * <br><br>
73766 * antialias - indicates whether or not to perform anti-aliasing
73767 * default is false
73768 * <br><br>
73769 * premultipliedAlpha - indicates that the page compositor will assume
73770 * the drawing buffer contains colors with pre-multiplied alpha
73771 * default is false
73772 * <br><br>
73773 * preserveDrawingBuffer - if true the buffers will not be cleared and
73774 * and will preserve their values until cleared or overwritten by author
73775 * (note that p5 clears automatically on draw loop)
73776 * default is true
73777 * <br><br>
73778 * perPixelLighting - if true, per-pixel lighting will be used in the
73779 * lighting shader.
73780 * default is false
73781 * <br><br>
73782 * @method setAttributes
73783 * @for p5
73784 * @param  {String}  key Name of attribute
73785 * @param  {Boolean}        value New value of named attribute
73786 * @example
73787 * <div>
73788 * <code>
73789 * function setup() {
73790 *   createCanvas(100, 100, WEBGL);
73791 * }
73792 *
73793 * function draw() {
73794 *   background(255);
73795 *   push();
73796 *   rotateZ(frameCount * 0.02);
73797 *   rotateX(frameCount * 0.02);
73798 *   rotateY(frameCount * 0.02);
73799 *   fill(0, 0, 0);
73800 *   box(50);
73801 *   pop();
73802 * }
73803 * </code>
73804 * </div>
73805 * <br>
73806 * Now with the antialias attribute set to true.
73807 * <br>
73808 * <div>
73809 * <code>
73810 * function setup() {
73811 *   createCanvas(100, 100, WEBGL);
73812 *   setAttributes('antialias', true);
73813 * }
73814 *
73815 * function draw() {
73816 *   background(255);
73817 *   push();
73818 *   rotateZ(frameCount * 0.02);
73819 *   rotateX(frameCount * 0.02);
73820 *   rotateY(frameCount * 0.02);
73821 *   fill(0, 0, 0);
73822 *   box(50);
73823 *   pop();
73824 * }
73825 * </code>
73826 * </div>
73827 *
73828 * <div>
73829 * <code>
73830 * // press the mouse button to enable perPixelLighting
73831 * function setup() {
73832 *   createCanvas(100, 100, WEBGL);
73833 *   noStroke();
73834 *   fill(255);
73835 * }
73836 *
73837 * var lights = [
73838 *   { c: '#f00', t: 1.12, p: 1.91, r: 0.2 },
73839 *   { c: '#0f0', t: 1.21, p: 1.31, r: 0.2 },
73840 *   { c: '#00f', t: 1.37, p: 1.57, r: 0.2 },
73841 *   { c: '#ff0', t: 1.12, p: 1.91, r: 0.7 },
73842 *   { c: '#0ff', t: 1.21, p: 1.31, r: 0.7 },
73843 *   { c: '#f0f', t: 1.37, p: 1.57, r: 0.7 }
73844 * ];
73845 *
73846 * function draw() {
73847 *   var t = millis() / 1000 + 1000;
73848 *   background(0);
73849 *   directionalLight(color('#222'), 1, 1, 1);
73850 *
73851 *   for (var i = 0; i < lights.length; i++) {
73852 *     var light = lights[i];
73853 *     pointLight(
73854 *       color(light.c),
73855 *       p5.Vector.fromAngles(t * light.t, t * light.p, width * light.r)
73856 *     );
73857 *   }
73858 *
73859 *   specularMaterial(255);
73860 *   sphere(width * 0.1);
73861 *
73862 *   rotateX(t * 0.77);
73863 *   rotateY(t * 0.83);
73864 *   rotateZ(t * 0.91);
73865 *   torus(width * 0.3, width * 0.07, 30, 10);
73866 * }
73867 *
73868 * function mousePressed() {
73869 *   setAttributes('perPixelLighting', true);
73870 *   noStroke();
73871 *   fill(255);
73872 * }
73873 * function mouseReleased() {
73874 *   setAttributes('perPixelLighting', false);
73875 *   noStroke();
73876 *   fill(255);
73877 * }
73878 * </code>
73879 * </div>
73880 *
73881 * @alt a rotating cube with smoother edges
73882 */
73883/**
73884 * @method setAttributes
73885 * @for p5
73886 * @param  {Object}  obj object with key-value pairs
73887 */
73888
73889p5.prototype.setAttributes = function(key, value) {
73890  this._assert3d('setAttributes');
73891  //@todo_FES
73892  var attr;
73893  if (typeof value !== 'undefined') {
73894    attr = {};
73895    attr[key] = value;
73896  } else if (key instanceof Object) {
73897    attr = key;
73898  }
73899  this.push();
73900  this._renderer._resetContext(attr);
73901  this.pop();
73902};
73903
73904/**
73905 * @class p5.RendererGL
73906 */
73907
73908p5.RendererGL.prototype._computeCameraDefaultSettings = function() {
73909  this.defaultCameraFOV = 60 / 180 * Math.PI;
73910  this.defaultCameraAspect = this.width / this.height;
73911  this.defaultCameraX = 0;
73912  this.defaultCameraY = 0;
73913  this.defaultCameraZ =
73914    this.height / 2.0 / Math.tan(this.defaultCameraFOV / 2.0);
73915  this.defaultCameraNear = this.defaultCameraZ * 0.1;
73916  this.defaultCameraFar = this.defaultCameraZ * 10;
73917};
73918
73919//detect if user didn't set the camera
73920//then call this function below
73921p5.RendererGL.prototype._setDefaultCamera = function() {
73922  if (this._curCamera === null) {
73923    this._computeCameraDefaultSettings();
73924    this.cameraFOV = this.defaultCameraFOV;
73925    this.cameraAspect = this.defaultAspect;
73926    this.cameraX = this.defaultCameraX;
73927    this.cameraY = this.defaultCameraY;
73928    this.cameraZ = this.defaultCameraZ;
73929    this.cameraNear = this.defaultCameraNear;
73930    this.cameraFar = this.defaultCameraFar;
73931
73932    this.perspective();
73933    this.camera();
73934    this._curCamera = 'default';
73935  }
73936};
73937
73938p5.RendererGL.prototype._update = function() {
73939  // reset model view and apply initial camera transform
73940  // (containing only look at info; no projection).
73941  this.uMVMatrix.set(
73942    this.cameraMatrix.mat4[0],
73943    this.cameraMatrix.mat4[1],
73944    this.cameraMatrix.mat4[2],
73945    this.cameraMatrix.mat4[3],
73946    this.cameraMatrix.mat4[4],
73947    this.cameraMatrix.mat4[5],
73948    this.cameraMatrix.mat4[6],
73949    this.cameraMatrix.mat4[7],
73950    this.cameraMatrix.mat4[8],
73951    this.cameraMatrix.mat4[9],
73952    this.cameraMatrix.mat4[10],
73953    this.cameraMatrix.mat4[11],
73954    this.cameraMatrix.mat4[12],
73955    this.cameraMatrix.mat4[13],
73956    this.cameraMatrix.mat4[14],
73957    this.cameraMatrix.mat4[15]
73958  );
73959
73960  // reset light data for new frame.
73961
73962  this.ambientLightColors.length = 0;
73963  this.directionalLightDirections.length = 0;
73964  this.directionalLightColors.length = 0;
73965
73966  this.pointLightPositions.length = 0;
73967  this.pointLightColors.length = 0;
73968};
73969
73970/**
73971 * [background description]
73972 */
73973p5.RendererGL.prototype.background = function() {
73974  var _col = this._pInst.color.apply(this._pInst, arguments);
73975  var _r = _col.levels[0] / 255;
73976  var _g = _col.levels[1] / 255;
73977  var _b = _col.levels[2] / 255;
73978  var _a = _col.levels[3] / 255;
73979  this.GL.clearColor(_r, _g, _b, _a);
73980  this.GL.depthMask(true);
73981  this.GL.clear(this.GL.COLOR_BUFFER_BIT | this.GL.DEPTH_BUFFER_BIT);
73982};
73983
73984//@TODO implement this
73985// p5.RendererGL.prototype.clear = function() {
73986//@TODO
73987// };
73988
73989//////////////////////////////////////////////
73990// COLOR
73991//////////////////////////////////////////////
73992/**
73993 * Basic fill material for geometry with a given color
73994 * @method  fill
73995 * @class p5.RendererGL
73996 * @param  {Number|Number[]|String|p5.Color} v1  gray value,
73997 * red or hue value (depending on the current color mode),
73998 * or color Array, or CSS color string
73999 * @param  {Number}            [v2] green or saturation value
74000 * @param  {Number}            [v3] blue or brightness value
74001 * @param  {Number}            [a]  opacity
74002 * @chainable
74003 * @example
74004 * <div>
74005 * <code>
74006 * function setup() {
74007 *   createCanvas(200, 200, WEBGL);
74008 * }
74009 *
74010 * function draw() {
74011 *   background(0);
74012 *   noStroke();
74013 *   fill(100, 100, 240);
74014 *   rotateX(frameCount * 0.01);
74015 *   rotateY(frameCount * 0.01);
74016 *   box(75, 75, 75);
74017 * }
74018 * </code>
74019 * </div>
74020 *
74021 * @alt
74022 * black canvas with purple cube spinning
74023 *
74024 */
74025p5.RendererGL.prototype.fill = function(v1, v2, v3, a) {
74026  //see material.js for more info on color blending in webgl
74027  var color = p5.prototype.color.apply(this._pInst, arguments);
74028  this.curFillColor = color._array;
74029
74030  if (this.isImmediateDrawing) {
74031    this.setFillShader(this._getImmediateModeShader());
74032  } else {
74033    this.setFillShader(this._getColorShader());
74034  }
74035  this.drawMode = constants.FILL;
74036  this.curFillShader.setUniform('uMaterialColor', this.curFillColor);
74037};
74038
74039/**
74040 * Basic stroke material for geometry with a given color
74041 * @method  stroke
74042 * @param  {Number|Number[]|String|p5.Color} v1  gray value,
74043 * red or hue value (depending on the current color mode),
74044 * or color Array, or CSS color string
74045 * @param  {Number}            [v2] green or saturation value
74046 * @param  {Number}            [v3] blue or brightness value
74047 * @param  {Number}            [a]  opacity
74048 * @example
74049 * <div>
74050 * <code>
74051 * function setup() {
74052 *   createCanvas(200, 200, WEBGL);
74053 * }
74054 *
74055 * function draw() {
74056 *   background(0);
74057 *   stroke(240, 150, 150);
74058 *   fill(100, 100, 240);
74059 *   rotateX(frameCount * 0.01);
74060 *   rotateY(frameCount * 0.01);
74061 *   box(75, 75, 75);
74062 * }
74063 * </code>
74064 * </div>
74065 *
74066 * @alt
74067 * black canvas with purple cube with pink outline spinning
74068 *
74069 */
74070p5.RendererGL.prototype.stroke = function(r, g, b, a) {
74071  //@todo allow transparency in stroking currently doesn't have
74072  //any impact and causes problems with specularMaterial
74073  arguments[3] = 255;
74074  var color = p5.prototype.color.apply(this._pInst, arguments);
74075  this.curStrokeColor = color._array;
74076  this.curStrokeShader.setUniform('uMaterialColor', this.curStrokeColor);
74077};
74078
74079/**
74080 * Change weight of stroke
74081 * @method  strokeWeight
74082 * @param  {Number} stroke weight to be used for drawing
74083 * @example
74084 * <div>
74085 * <code>
74086 * function setup() {
74087 *   createCanvas(200, 400, WEBGL);
74088 *   setAttributes('antialias', true);
74089 * }
74090 *
74091 * function draw() {
74092 *   background(0);
74093 *   noStroke();
74094 *   translate(0, -100, 0);
74095 *   stroke(240, 150, 150);
74096 *   fill(100, 100, 240);
74097 *   push();
74098 *   strokeWeight(8);
74099 *   rotateX(frameCount * 0.01);
74100 *   rotateY(frameCount * 0.01);
74101 *   sphere(75);
74102 *   pop();
74103 *   push();
74104 *   translate(0, 200, 0);
74105 *   strokeWeight(1);
74106 *   rotateX(frameCount * 0.01);
74107 *   rotateY(frameCount * 0.01);
74108 *   sphere(75);
74109 *   pop();
74110 * }
74111 * </code>
74112 * </div>
74113 *
74114 * @alt
74115 * black canvas with two purple rotating spheres with pink
74116 * outlines the sphere on top has much heavier outlines,
74117 *
74118 */
74119p5.RendererGL.prototype.strokeWeight = function(w) {
74120  if (this.curStrokeWeight !== w) {
74121    this.pointSize = w;
74122    this.curStrokeWeight = w;
74123    this.curStrokeShader.setUniform('uStrokeWeight', w);
74124  }
74125};
74126
74127/**
74128 * Returns an array of [R,G,B,A] values for any pixel or grabs a section of
74129 * an image. If no parameters are specified, the entire image is returned.
74130 * Use the x and y parameters to get the value of one pixel. Get a section of
74131 * the display window by specifying additional w and h parameters. When
74132 * getting an image, the x and y parameters define the coordinates for the
74133 * upper-left corner of the image, regardless of the current imageMode().
74134 * <br><br>
74135 * If the pixel requested is outside of the image window, [0,0,0,255] is
74136 * returned.
74137 * <br><br>
74138 * Getting the color of a single pixel with get(x, y) is easy, but not as fast
74139 * as grabbing the data directly from pixels[]. The equivalent statement to
74140 * get(x, y) is using pixels[] with pixel density d
74141 *
74142 * @private
74143 * @method get
74144 * @param  {Number}               [x] x-coordinate of the pixel
74145 * @param  {Number}               [y] y-coordinate of the pixel
74146 * @param  {Number}               [w] width
74147 * @param  {Number}               [h] height
74148 * @return {Number[]|Color|p5.Image}  color of pixel at x,y in array format
74149 *                                    [R, G, B, A] or p5.Image
74150 */
74151p5.RendererGL.prototype.get = function(x, y, w, h) {
74152  return p5.Renderer2D.prototype.get.apply(this, [x, y, w, h]);
74153};
74154
74155/**
74156 * Loads the pixels data for this canvas into the pixels[] attribute.
74157 * Note that updatePixels() and set() do not work.
74158 * Any pixel manipulation must be done directly to the pixels[] array.
74159 *
74160 * @private
74161 * @method loadPixels
74162 *
74163 */
74164
74165p5.RendererGL.prototype.loadPixels = function() {
74166  //@todo_FES
74167  if (this.attributes.preserveDrawingBuffer !== true) {
74168    console.log(
74169      'loadPixels only works in WebGL when preserveDrawingBuffer ' + 'is true.'
74170    );
74171    return;
74172  }
74173  var pd = this._pInst._pixelDensity;
74174  var x = 0;
74175  var y = 0;
74176  var w = this.width;
74177  var h = this.height;
74178  w *= pd;
74179  h *= pd;
74180  //if there isn't a renderer-level temporary pixels buffer
74181  //make a new one
74182  if (typeof this.pixels === 'undefined') {
74183    this.pixels = new Uint8Array(
74184      this.GL.drawingBufferWidth * this.GL.drawingBufferHeight * 4
74185    );
74186  }
74187  this.GL.readPixels(
74188    x,
74189    y,
74190    w,
74191    h,
74192    this.GL.RGBA,
74193    this.GL.UNSIGNED_BYTE,
74194    this.pixels
74195  );
74196  this._pInst._setProperty('pixels', this.pixels);
74197};
74198
74199//////////////////////////////////////////////
74200// HASH | for geometry
74201//////////////////////////////////////////////
74202
74203p5.RendererGL.prototype.geometryInHash = function(gId) {
74204  return this.gHash[gId] !== undefined;
74205};
74206
74207/**
74208 * [resize description]
74209 * @private
74210 * @param  {Number} w [description]
74211 * @param  {Number} h [description]
74212 */
74213p5.RendererGL.prototype.resize = function(w, h) {
74214  p5.Renderer.prototype.resize.call(this, w, h);
74215  this.GL.viewport(
74216    0,
74217    0,
74218    this.GL.drawingBufferWidth,
74219    this.GL.drawingBufferHeight
74220  );
74221  this._viewport = this.GL.getParameter(this.GL.VIEWPORT);
74222  // If we're using the default camera, update the aspect ratio
74223  if (this._curCamera === null || this._curCamera === 'default') {
74224    this._curCamera = null;
74225    // camera defaults are dependent on the width & height of the screen,
74226    // so we'll want to update them if the size of the screen changes.
74227    this._setDefaultCamera();
74228  }
74229  //resize pixels buffer
74230  if (typeof this.pixels !== 'undefined') {
74231    this.pixels = new Uint8Array(
74232      this.GL.drawingBufferWidth * this.GL.drawingBufferHeight * 4
74233    );
74234  }
74235};
74236
74237/**
74238 * clears color and depth buffers
74239 * with r,g,b,a
74240 * @private
74241 * @param {Number} r normalized red val.
74242 * @param {Number} g normalized green val.
74243 * @param {Number} b normalized blue val.
74244 * @param {Number} a normalized alpha val.
74245 */
74246p5.RendererGL.prototype.clear = function() {
74247  var _r = arguments[0] || 0;
74248  var _g = arguments[1] || 0;
74249  var _b = arguments[2] || 0;
74250  var _a = arguments[3] || 0;
74251  this.GL.clearColor(_r, _g, _b, _a);
74252  this.GL.clear(this.GL.COLOR_BUFFER_BIT | this.GL.DEPTH_BUFFER_BIT);
74253};
74254
74255/**
74256 * [translate description]
74257 * @private
74258 * @param  {Number} x [description]
74259 * @param  {Number} y [description]
74260 * @param  {Number} z [description]
74261 * @chainable
74262 * @todo implement handle for components or vector as args
74263 */
74264p5.RendererGL.prototype.translate = function(x, y, z) {
74265  if (x instanceof p5.Vector) {
74266    z = x.z;
74267    y = x.y;
74268    x = x.x;
74269  }
74270  this.uMVMatrix.translate([x, y, z]);
74271  return this;
74272};
74273
74274/**
74275 * Scales the Model View Matrix by a vector
74276 * @private
74277 * @param  {Number | p5.Vector | Array} x [description]
74278 * @param  {Number} [y] y-axis scalar
74279 * @param  {Number} [z] z-axis scalar
74280 * @chainable
74281 */
74282p5.RendererGL.prototype.scale = function(x, y, z) {
74283  this.uMVMatrix.scale(x, y, z);
74284  return this;
74285};
74286
74287p5.RendererGL.prototype.rotate = function(rad, axis) {
74288  if (typeof axis === 'undefined') {
74289    return this.rotateZ(rad);
74290  }
74291  p5.Matrix.prototype.rotate.apply(this.uMVMatrix, arguments);
74292  return this;
74293};
74294
74295p5.RendererGL.prototype.rotateX = function(rad) {
74296  this.rotate(rad, 1, 0, 0);
74297  return this;
74298};
74299
74300p5.RendererGL.prototype.rotateY = function(rad) {
74301  this.rotate(rad, 0, 1, 0);
74302  return this;
74303};
74304
74305p5.RendererGL.prototype.rotateZ = function(rad) {
74306  this.rotate(rad, 0, 0, 1);
74307  return this;
74308};
74309
74310p5.RendererGL.prototype.push = function() {
74311  // get the base renderer style
74312  var style = p5.Renderer.prototype.push.apply(this);
74313
74314  // add webgl-specific style properties
74315  var properties = style.properties;
74316
74317  properties.uMVMatrix = this.uMVMatrix.copy();
74318  properties.cameraMatrix = this.cameraMatrix.copy();
74319
74320  return style;
74321};
74322
74323p5.RendererGL.prototype.resetMatrix = function() {
74324  this.uMVMatrix = p5.Matrix.identity(this._pInst);
74325  return this;
74326};
74327
74328// Text/Typography
74329// @TODO:
74330p5.RendererGL.prototype._applyTextProperties = function() {
74331  //@TODO finish implementation
74332  console.error('text commands not yet implemented in webgl');
74333};
74334
74335//////////////////////////////////////////////
74336// SHADER
74337//////////////////////////////////////////////
74338
74339/*
74340 * Initializes and uses the specified shader, then returns
74341 * that shader. Note: initialization and resetting the program
74342 * is only used if needed (say, if a new value is provided)
74343 * so it is safe to call this method with the same shader multiple
74344 * times without a signficant performance hit).
74345 *
74346 * @method setFillShader
74347 * @param {p5.Shader} [s] a p5.Shader object
74348 * @return {p5.Shader} the current, updated fill shader
74349 */
74350p5.RendererGL.prototype.setFillShader = function(s) {
74351  if (this.curFillShader !== s) {
74352    // only do setup etc. if shader is actually new.
74353    this.curFillShader = s;
74354
74355    // safe to do this multiple times;
74356    // init() will bail early if has already been run.
74357    this.curFillShader.init();
74358    //this.curFillShader.useProgram();
74359  }
74360  // always return this.curFillShader, even if no change was made.
74361  return this.curFillShader;
74362};
74363
74364/*
74365 * @method setStrokeShader
74366 * @param {p5.Shader} [s] a p5.Shader object
74367 * @return {p5.Shader} the current, updated stroke shader
74368 */
74369p5.RendererGL.prototype.setStrokeShader = function(s) {
74370  if (this.curStrokeShader !== s) {
74371    // only do setup etc. if shader is actually new.
74372    this.curStrokeShader = s;
74373    // safe to do this multiple times;
74374    // init() will bail early if has already been run.
74375    this.curStrokeShader.init();
74376    //this.curStrokeShader.useProgram();
74377  }
74378  // always return this.curLineShader, even if no change was made.
74379  return this.curStrokeShader;
74380};
74381
74382/*
74383 * shaders are created and cached on a per-renderer basis,
74384 * on the grounds that each renderer will have its own gl context
74385 * and the shader must be valid in that context.
74386 *
74387 *
74388 */
74389
74390p5.RendererGL.prototype._useLightShader = function() {
74391  if (!this.curFillShader || !this.curFillShader.isLightShader()) {
74392    this.setFillShader(this._getLightShader());
74393  }
74394  return this.curFillShader;
74395};
74396
74397p5.RendererGL.prototype._useColorShader = function() {
74398  // looking at the code within the glsl files, I'm not really
74399  // sure why these are two different shaders. but, they are,
74400  // and if we're drawing in retain mode but the shader is the
74401  // immediate mode one, we need to switch.
74402
74403  // TODO: what if curFillShader is _any_ other shader?
74404  if (
74405    !this.curFillShader ||
74406    this.curFillShader === this._defaultImmediateModeShader
74407  ) {
74408    // there are different immediate mode and retain mode color shaders.
74409    // if we're using the immediate mode one, we need to switch to
74410    // one that works for retain mode.
74411    this.setFillShader(this._getColorShader());
74412  }
74413  return this.curFillShader;
74414};
74415
74416p5.RendererGL.prototype._useImmediateModeShader = function() {
74417  // TODO: what if curFillShader is _any_ other shader?
74418  if (!this.curFillShader || this.curFillShader === this._defaultColorShader) {
74419    // this is the fill/stroke shader for retain mode.
74420    // must switch to immediate mode shader before drawing!
74421    this.setFillShader(this._getImmediateModeShader());
74422    // note that if we're using the texture shader...
74423    // this shouldn't change. :)
74424  }
74425  return this.curFillShader;
74426};
74427
74428p5.RendererGL.prototype._getLightShader = function() {
74429  if (!this._defaultLightShader) {
74430    if (this.attributes.perPixelLighting) {
74431      this._defaultLightShader = new p5.Shader(
74432        this,
74433        defaultShaders.phongVert,
74434        defaultShaders.phongFrag
74435      );
74436    } else {
74437      this._defaultLightShader = new p5.Shader(
74438        this,
74439        defaultShaders.lightVert,
74440        defaultShaders.lightTextureFrag
74441      );
74442    }
74443  }
74444  //this.drawMode = constants.FILL;
74445  return this._defaultLightShader;
74446};
74447
74448p5.RendererGL.prototype._getImmediateModeShader = function() {
74449  if (!this._defaultImmediateModeShader) {
74450    this._defaultImmediateModeShader = new p5.Shader(
74451      this,
74452      defaultShaders.immediateVert,
74453      defaultShaders.vertexColorFrag
74454    );
74455  }
74456  //this.drawMode = constants.FILL;
74457  return this._defaultImmediateModeShader;
74458};
74459
74460p5.RendererGL.prototype._getNormalShader = function() {
74461  if (!this._defaultNormalShader) {
74462    this._defaultNormalShader = new p5.Shader(
74463      this,
74464      defaultShaders.normalVert,
74465      defaultShaders.normalFrag
74466    );
74467  }
74468  //this.drawMode = constants.FILL;
74469  return this._defaultNormalShader;
74470};
74471
74472p5.RendererGL.prototype._getColorShader = function() {
74473  if (!this._defaultColorShader) {
74474    this._defaultColorShader = new p5.Shader(
74475      this,
74476      defaultShaders.normalVert,
74477      defaultShaders.basicFrag
74478    );
74479  }
74480  //this.drawMode = constants.FILL;
74481  return this._defaultColorShader;
74482};
74483
74484p5.RendererGL.prototype._getLineShader = function() {
74485  if (!this._defaultLineShader) {
74486    this._defaultLineShader = new p5.Shader(
74487      this,
74488      defaultShaders.lineVert,
74489      defaultShaders.lineFrag
74490    );
74491  }
74492  //this.drawMode = constants.STROKE;
74493  return this._defaultLineShader;
74494};
74495
74496p5.RendererGL.prototype._getEmptyTexture = function() {
74497  if (!this._emptyTexture) {
74498    // a plain white texture RGBA, full alpha, single pixel.
74499    var im = new p5.Image(1, 1);
74500    im.set(0, 0, 255);
74501    this._emptyTexture = new p5.Texture(this, im);
74502  }
74503  return this._emptyTexture;
74504};
74505
74506p5.RendererGL.prototype.getTexture = function(img) {
74507  var checkSource = function(element) {
74508    return element.src === img;
74509  };
74510  //this.drawMode = constants.TEXTURE;
74511  var tex = this.textures.find(checkSource);
74512  if (!tex) {
74513    tex = new p5.Texture(this, img);
74514    this.textures.push(tex);
74515  }
74516
74517  return tex;
74518};
74519
74520//Binds a buffer to the drawing context
74521//when passed more than two arguments it also updates or initializes
74522//the data associated with the buffer
74523p5.RendererGL.prototype._bindBuffer = function(
74524  buffer,
74525  target,
74526  values,
74527  type,
74528  usage
74529) {
74530  this.GL.bindBuffer(target, buffer);
74531  if (values !== undefined) {
74532    var data = new type(values);
74533    this.GL.bufferData(target, data, usage);
74534  }
74535};
74536
74537//////////////////////////
74538//// SMOOTHING
74539/////////////////////////
74540// @TODO:
74541p5.RendererGL.prototype.smooth = function() {
74542  //@TODO finish implementation
74543  console.log('smoothing not yet implemented in webgl');
74544};
74545
74546p5.RendererGL.prototype.noSmooth = function() {
74547  //@TODO finish implementation
74548  console.log('smoothing not yet implemented in webgl');
74549};
74550
74551///////////////////////////////
74552//// UTILITY FUNCTIONS
74553//////////////////////////////
74554/**
74555 * turn a two dimensional array into one dimensional array
74556 * @private
74557 * @param  {Array} arr 2-dimensional array
74558 * @return {Array}     1-dimensional array
74559 * [[1, 2, 3],[4, 5, 6]] -> [1, 2, 3, 4, 5, 6]
74560 */
74561p5.RendererGL.prototype._flatten = function(arr) {
74562  //when empty, return empty
74563  if (arr.length === 0) {
74564    return [];
74565  } else if (arr.length > 20000) {
74566    //big models , load slower to avoid stack overflow
74567    //faster non-recursive flatten via axelduch
74568    //stackoverflow.com/questions/27266550/how-to-flatten-nested-array-in-javascript
74569    var toString = Object.prototype.toString;
74570    var arrayTypeStr = '[object Array]';
74571    var result = [];
74572    var nodes = arr.slice();
74573    var node;
74574    node = nodes.pop();
74575    do {
74576      if (toString.call(node) === arrayTypeStr) {
74577        nodes.push.apply(nodes, node);
74578      } else {
74579        result.push(node);
74580      }
74581    } while (nodes.length && (node = nodes.pop()) !== undefined);
74582    result.reverse(); // we reverse result to restore the original order
74583    return result;
74584  } else {
74585    //otherwise if model within limits for browser
74586    //use faster recursive loading
74587    return [].concat.apply([], arr);
74588  }
74589};
74590
74591/**
74592 * turn a p5.Vector Array into a one dimensional number array
74593 * @private
74594 * @param  {p5.Vector[]} arr  an array of p5.Vector
74595 * @return {Number[]}     a one dimensional array of numbers
74596 * [p5.Vector(1, 2, 3), p5.Vector(4, 5, 6)] ->
74597 * [1, 2, 3, 4, 5, 6]
74598 */
74599p5.RendererGL.prototype._vToNArray = function(arr) {
74600  return this._flatten(
74601    arr.map(function(item) {
74602      return [item.x, item.y, item.z];
74603    })
74604  );
74605};
74606
74607/**
74608 * ensures that p5 is using a 3d renderer. throws an error if not.
74609 */
74610p5.prototype._assert3d = function(name) {
74611  if (!this._renderer.isP3D)
74612    throw new Error(
74613      name +
74614        "() is only supported in WEBGL mode. If you'd like to use 3D graphics" +
74615        ' and WebGL, see  https://p5js.org/examples/form-3d-primitives.html' +
74616        ' for more information.'
74617    );
74618};
74619
74620module.exports = p5.RendererGL;
74621
74622},{"../core/constants":21,"../core/core":22,"../core/p5.Renderer":29,"./p5.Matrix":69,"./p5.Shader":73}],73:[function(_dereq_,module,exports){
74623/**
74624 * This module defines the p5.Shader class
74625 * @module Lights, Camera
74626 * @submodule Shaders
74627 * @for p5
74628 * @requires core
74629 */
74630
74631'use strict';
74632
74633var p5 = _dereq_('../core/core');
74634
74635/**
74636 * Shader class for WEBGL Mode
74637 * @class p5.Shader
74638 * @param {p5.RendererGL} renderer an instance of p5.RendererGL that
74639 * will provide the GL context for this new p5.Shader
74640 * @param {String} vertSrc source code for the vertex shader (as a string)
74641 * @param {String} fragSrc source code for the fragment shader (as a string)
74642 */
74643p5.Shader = function(renderer, vertSrc, fragSrc) {
74644  // TODO: adapt this to not take ids, but rather,
74645  // to take the source for a vertex and fragment shader
74646  // to enable custom shaders at some later date
74647  this._renderer = renderer;
74648  this._vertSrc = vertSrc;
74649  this._fragSrc = fragSrc;
74650  this._vertShader = -1;
74651  this._fragShader = -1;
74652  this._glProgram = 0;
74653  this._loadedAttributes = false;
74654  this.attributes = {};
74655  this._loadedUniforms = false;
74656  this.uniforms = {};
74657  this._bound = false;
74658  this.samplers = [];
74659
74660  return this;
74661};
74662
74663/**
74664 * Creates, compiles, and links the shader based on its
74665 * sources for the vertex and fragment shaders (provided
74666 * to the constructor). Populates known attributes and
74667 * uniforms from the shader.
74668 * @method init
74669 * @chainable
74670 * @private
74671 */
74672p5.Shader.prototype.init = function() {
74673  if (this._glProgram === 0 /* or context is stale? */) {
74674    var gl = this._renderer.GL;
74675
74676    // @todo: once custom shading is allowed,
74677    // friendly error messages should be used here to share
74678    // compiler and linker errors.
74679
74680    //set up the shader by
74681    // 1. creating and getting a gl id for the shader program,
74682    // 2. compliling its vertex & fragment sources,
74683    // 3. linking the vertex and fragment shaders
74684    this._vertShader = gl.createShader(gl.VERTEX_SHADER);
74685    //load in our default vertex shader
74686    gl.shaderSource(this._vertShader, this._vertSrc);
74687    gl.compileShader(this._vertShader);
74688    // if our vertex shader failed compilation?
74689    if (!gl.getShaderParameter(this._vertShader, gl.COMPILE_STATUS)) {
74690      console.error(
74691        'Yikes! An error occurred compiling the vertex shader:' +
74692          gl.getShaderInfoLog(this._vertShader)
74693      );
74694      return null;
74695    }
74696
74697    this._fragShader = gl.createShader(gl.FRAGMENT_SHADER);
74698    //load in our material frag shader
74699    gl.shaderSource(this._fragShader, this._fragSrc);
74700    gl.compileShader(this._fragShader);
74701    // if our frag shader failed compilation?
74702    if (!gl.getShaderParameter(this._fragShader, gl.COMPILE_STATUS)) {
74703      console.error(
74704        'Darn! An error occurred compiling the fragment shader:' +
74705          gl.getShaderInfoLog(this._fragShader)
74706      );
74707      return null;
74708    }
74709
74710    this._glProgram = gl.createProgram();
74711    gl.attachShader(this._glProgram, this._vertShader);
74712    gl.attachShader(this._glProgram, this._fragShader);
74713    gl.linkProgram(this._glProgram);
74714    if (!gl.getProgramParameter(this._glProgram, gl.LINK_STATUS)) {
74715      console.error(
74716        'Snap! Error linking shader program: ' +
74717          gl.getProgramInfoLog(this._glProgram)
74718      );
74719    }
74720
74721    this._loadAttributes();
74722    this._loadUniforms();
74723  }
74724  return this;
74725};
74726
74727/**
74728 * Queries the active attributes for this shader and loads
74729 * their names and locations into the attributes array.
74730 * @method _loadAttributes
74731 * @private
74732 */
74733p5.Shader.prototype._loadAttributes = function() {
74734  if (this._loadedAttributes) {
74735    return;
74736  }
74737
74738  this.attributes = {};
74739
74740  var gl = this._renderer.GL;
74741
74742  var numAttributes = gl.getProgramParameter(
74743    this._glProgram,
74744    gl.ACTIVE_ATTRIBUTES
74745  );
74746  for (var i = 0; i < numAttributes; ++i) {
74747    var attributeInfo = gl.getActiveAttrib(this._glProgram, i);
74748    var name = attributeInfo.name;
74749    var location = gl.getAttribLocation(this._glProgram, name);
74750    var attribute = {};
74751    attribute.name = name;
74752    attribute.location = location;
74753    attribute.type = attributeInfo.type;
74754    attribute.size = attributeInfo.size;
74755    this.attributes[name] = attribute;
74756  }
74757
74758  this._loadedAttributes = true;
74759};
74760
74761/**
74762 * Queries the active uniforms for this shader and loads
74763 * their names and locations into the uniforms array.
74764 * @method _loadUniforms
74765 * @private
74766 */
74767p5.Shader.prototype._loadUniforms = function() {
74768  if (this._loadedUniforms) {
74769    return;
74770  }
74771
74772  var gl = this._renderer.GL;
74773
74774  // Inspect shader and cache uniform info
74775  var numUniforms = gl.getProgramParameter(this._glProgram, gl.ACTIVE_UNIFORMS);
74776
74777  var samplerIndex = 0;
74778  for (var i = 0; i < numUniforms; ++i) {
74779    var uniformInfo = gl.getActiveUniform(this._glProgram, i);
74780    var uniform = {};
74781    uniform.location = gl.getUniformLocation(this._glProgram, uniformInfo.name);
74782    uniform.size = uniformInfo.size;
74783    var uniformName = uniformInfo.name;
74784    //uniforms thats are arrays have their name returned as
74785    //someUniform[0] which is a bit silly so we trim it
74786    //off here. The size property tells us that its an array
74787    //so we dont lose any information by doing this
74788    if (uniformInfo.size > 1) {
74789      uniformName = uniformName.substring(0, uniformName.indexOf('[0]'));
74790    }
74791    uniform.name = uniformName;
74792    uniform.type = uniformInfo.type;
74793    if (uniform.type === gl.SAMPLER_2D) {
74794      uniform.samplerIndex = samplerIndex;
74795      samplerIndex++;
74796      this.samplers.push(uniform);
74797    }
74798    this.uniforms[uniformName] = uniform;
74799  }
74800  this._loadedUniforms = true;
74801};
74802
74803p5.Shader.prototype.compile = function() {
74804  // TODO
74805};
74806
74807/**
74808 * initializes (if needed) and binds the shader program.
74809 * @method bindShader
74810 * @private
74811 */
74812p5.Shader.prototype.bindShader = function() {
74813  this.init();
74814  if (!this._bound) {
74815    this.useProgram();
74816    this._bound = true;
74817    this.bindTextures();
74818
74819    this._loadAttributes();
74820    this._loadUniforms();
74821
74822    this._renderer._setDefaultCamera();
74823    this._setMatrixUniforms();
74824    if (this === this._renderer.curStrokeShader) {
74825      this._setViewportUniform();
74826    }
74827  }
74828};
74829
74830/**
74831 * @method unbindShader
74832 * @chainable
74833 * @private
74834 */
74835p5.Shader.prototype.unbindShader = function() {
74836  if (this._bound) {
74837    this.unbindTextures();
74838    //this._renderer.GL.useProgram(0); ??
74839    this._bound = false;
74840  }
74841  return this;
74842};
74843
74844p5.Shader.prototype.bindTextures = function() {
74845  var gl = this._renderer.GL;
74846  for (var i = 0; i < this.samplers.length; i++) {
74847    var uniform = this.samplers[i];
74848    var tex = uniform.texture;
74849    if (tex === undefined) {
74850      // user hasn't yet supplied a texture for this slot.
74851      // (or there may not be one--maybe just lighting),
74852      // so we supply a default texture instead.
74853      tex = this._renderer._getEmptyTexture();
74854    }
74855    gl.activeTexture(gl.TEXTURE0 + uniform.samplerIndex);
74856    tex.bindTexture();
74857    tex.update();
74858    gl.uniform1i(uniform.location, uniform.samplerIndex);
74859  }
74860};
74861
74862p5.Shader.prototype.unbindTextures = function() {
74863  // TODO: migrate stuff from material.js here
74864  // - OR - have material.js define this function
74865};
74866
74867p5.Shader.prototype._setMatrixUniforms = function() {
74868  this.setUniform('uProjectionMatrix', this._renderer.uPMatrix.mat4);
74869  this.setUniform('uModelViewMatrix', this._renderer.uMVMatrix.mat4);
74870  this.setUniform('uViewMatrix', this._renderer.cameraMatrix.mat4);
74871  if (this === this._renderer.curFillShader) {
74872    this._renderer.uNMatrix.inverseTranspose(this._renderer.uMVMatrix);
74873    this.setUniform('uNormalMatrix', this._renderer.uNMatrix.mat3);
74874  }
74875};
74876
74877p5.Shader.prototype._setViewportUniform = function() {
74878  this.setUniform('uViewport', this._renderer._viewport);
74879};
74880
74881/**
74882 * @method useProgram
74883 * @chainable
74884 * @private
74885 */
74886p5.Shader.prototype.useProgram = function() {
74887  var gl = this._renderer.GL;
74888  gl.useProgram(this._glProgram);
74889  return this;
74890};
74891
74892/**
74893 * Wrapper around gl.uniform functions.
74894 * As we store uniform info in the shader we can use that
74895 * to do type checking on the supplied data and call
74896 * the appropriate function.
74897 * @method setUniform
74898 * @chainable
74899 * @param {String} uniformName the name of the uniform in the
74900 * shader program
74901 * @param {Object|Number|Boolean|Number[]} data the data to be associated
74902 * with that uniform; type varies (could be a single numerical value, array,
74903 * matrix, or texture / sampler reference)
74904 */
74905p5.Shader.prototype.setUniform = function(uniformName, data) {
74906  //@todo update all current gl.uniformXX calls
74907
74908  var uniform = this.uniforms[uniformName];
74909  if (!uniform) {
74910    //@todo warning?
74911    return;
74912  }
74913  var location = uniform.location;
74914
74915  var gl = this._renderer.GL;
74916  // todo: is this safe to do here?
74917  // todo: store the values another way?
74918  this.useProgram();
74919
74920  // TODO BIND?
74921
74922  switch (uniform.type) {
74923    case gl.BOOL:
74924      if (data === true) {
74925        gl.uniform1i(location, 1);
74926      } else {
74927        gl.uniform1i(location, 0);
74928      }
74929      break;
74930    case gl.INT:
74931      if (uniform.size > 1) {
74932        data.length && gl.uniform1iv(location, data);
74933      } else {
74934        gl.uniform1i(location, data);
74935      }
74936      break;
74937    case gl.FLOAT:
74938      if (uniform.size > 1) {
74939        data.length && gl.uniform1fv(location, data);
74940      } else {
74941        gl.uniform1f(location, data);
74942      }
74943      break;
74944    case gl.FLOAT_MAT3:
74945      gl.uniformMatrix3fv(location, false, data);
74946      break;
74947    case gl.FLOAT_MAT4:
74948      gl.uniformMatrix4fv(location, false, data);
74949      break;
74950    case gl.FLOAT_VEC2:
74951      if (uniform.size > 1) {
74952        data.length && gl.uniform2fv(location, data);
74953      } else {
74954        gl.uniform2f(location, data[0], data[1]);
74955      }
74956      break;
74957    case gl.FLOAT_VEC3:
74958      if (uniform.size > 1) {
74959        data.length && gl.uniform3fv(location, data);
74960      } else {
74961        gl.uniform3f(location, data[0], data[1], data[2]);
74962      }
74963      break;
74964    case gl.FLOAT_VEC4:
74965      if (uniform.size > 1) {
74966        data.length && gl.uniform4fv(location, data);
74967      } else {
74968        gl.uniform4f(location, data[0], data[1], data[2], data[3]);
74969      }
74970      break;
74971    case gl.SAMPLER_2D:
74972      gl.activeTexture(gl.TEXTURE0 + uniform.samplerIndex);
74973      uniform.texture = this._renderer.getTexture(data);
74974      gl.uniform1i(uniform.location, uniform.samplerIndex);
74975      break;
74976    //@todo complete all types
74977  }
74978  return this;
74979};
74980
74981/* NONE OF THIS IS FAST OR EFFICIENT BUT BEAR WITH ME
74982 *
74983 * these shader "type" query methods are used by various
74984 * facilities of the renderer to determine if changing
74985 * the shader type for the required action (for example,
74986 * do we need to load the default lighting shader if the
74987 * current shader cannot handle lighting?)
74988 *
74989 **/
74990
74991p5.Shader.prototype.isLightShader = function() {
74992  return (
74993    this.uniforms.uUseLighting !== undefined ||
74994    this.uniforms.uAmbientLightCount !== undefined ||
74995    this.uniforms.uDirectionalLightCount !== undefined ||
74996    this.uniforms.uPointLightCount !== undefined ||
74997    this.uniforms.uAmbientColor !== undefined ||
74998    this.uniforms.uDirectionalColor !== undefined ||
74999    this.uniforms.uPointLightLocation !== undefined ||
75000    this.uniforms.uPointLightColor !== undefined ||
75001    this.uniforms.uLightingDirection !== undefined ||
75002    this.uniforms.uSpecular !== undefined
75003  );
75004};
75005
75006p5.Shader.prototype.isTextureShader = function() {
75007  return this.samplerIndex > 0;
75008};
75009
75010p5.Shader.prototype.isColorShader = function() {
75011  return (
75012    this.attributes.aVertexColor !== undefined ||
75013    this.uniforms.uMaterialColor !== undefined
75014  );
75015};
75016
75017p5.Shader.prototype.isTexLightShader = function() {
75018  return this.isLightShader() && this.isTextureShader();
75019};
75020
75021p5.Shader.prototype.isStrokeShader = function() {
75022  return this.uniforms.uStrokeWeight !== undefined;
75023};
75024
75025/**
75026 * @method enableAttrib
75027 * @chainable
75028 * @private
75029 */
75030p5.Shader.prototype.enableAttrib = function(
75031  loc,
75032  size,
75033  type,
75034  normalized,
75035  stride,
75036  offset
75037) {
75038  var gl = this._renderer.GL;
75039  if (loc !== -1) {
75040    gl.enableVertexAttribArray(loc);
75041    gl.vertexAttribPointer(loc, size, type, normalized, stride, offset);
75042  }
75043  return this;
75044};
75045
75046module.exports = p5.Shader;
75047
75048},{"../core/core":22}],74:[function(_dereq_,module,exports){
75049/**
75050 * This module defines the p5.Texture class
75051 * @module Lights, Camera
75052 * @submodule Material
75053 * @for p5
75054 * @requires core
75055 */
75056
75057'use strict';
75058
75059var p5 = _dereq_('../core/core');
75060
75061/**
75062 * Texture class for WEBGL Mode
75063 * @private
75064 * @class p5.Texture
75065 * @param {p5.RendererGL} renderer an instance of p5.RendererGL that
75066 * will provide the GL context for this new p5.Texture
75067 * @param {p5.Image|p5.Graphics|p5.Element|p5.MediaElement} [obj] the
75068 * object containing the image data to store in the texture.
75069 */
75070p5.Texture = function(renderer, obj) {
75071  this._renderer = renderer;
75072
75073  var gl = this._renderer.GL;
75074
75075  this.src = obj;
75076  this.glTex = undefined;
75077  this.glTarget = gl.TEXTURE_2D;
75078  this.glFormat = gl.RGBA;
75079  this.mipmaps = false;
75080  this.glMinFilter = gl.LINEAR;
75081  this.glMagFilter = gl.LINEAR;
75082  this.glWrapS = gl.CLAMP_TO_EDGE;
75083  this.glWrapT = gl.CLAMP_TO_EDGE;
75084
75085  // used to determine if this texture might need constant updating
75086  // because it is a video or gif.
75087  this.isSrcMediaElement =
75088    typeof p5.MediaElement !== 'undefined' && obj instanceof p5.MediaElement;
75089  this._videoPrevUpdateTime = 0;
75090  this.isSrcHTMLElement =
75091    typeof p5.Element !== 'undefined' &&
75092    obj instanceof p5.Element &&
75093    !(obj instanceof p5.Graphics);
75094  this.isSrcP5Image = obj instanceof p5.Image;
75095  this.isSrcP5Graphics = obj instanceof p5.Graphics;
75096
75097  var textureData = this._getTextureDataFromSource();
75098  this.width = textureData.width;
75099  this.height = textureData.height;
75100
75101  this.init(textureData);
75102  return this;
75103};
75104
75105p5.Texture.prototype._getTextureDataFromSource = function() {
75106  var textureData;
75107  if (this.isSrcP5Image) {
75108    // param is a p5.Image
75109    textureData = this.src.canvas;
75110  } else if (
75111    this.isSrcMediaElement ||
75112    this.isSrcP5Graphics ||
75113    this.isSrcHTMLElement
75114  ) {
75115    // if param is a video HTML element
75116    textureData = this.src.elt;
75117  }
75118  return textureData;
75119};
75120
75121/**
75122 * Initializes common texture parameters, creates a gl texture,
75123 * tries to upload the texture for the first time if data is
75124 * already available.
75125 * @private
75126 * @method init
75127 */
75128p5.Texture.prototype.init = function(data) {
75129  var gl = this._renderer.GL;
75130  this.glTex = gl.createTexture();
75131  this.bindTexture();
75132
75133  //gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
75134  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, this.glMagFilter);
75135  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, this.glMinFilter);
75136  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, this.glWrapS);
75137  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, this.glWrapT);
75138
75139  if (
75140    this.width === 0 ||
75141    this.height === 0 ||
75142    (this.isSrcMediaElement && !this.src.loadedmetadata)
75143  ) {
75144    // assign a 1x1 empty texture initially, because data is not yet ready,
75145    // so that no errors occur in gl console!
75146    var tmpdata = new Uint8Array([1, 1, 1, 1]);
75147    gl.texImage2D(
75148      this.glTarget,
75149      0,
75150      gl.RGBA,
75151      1,
75152      1,
75153      0,
75154      this.glFormat,
75155      gl.UNSIGNED_BYTE,
75156      tmpdata
75157    );
75158  } else {
75159    // data is ready: just push the texture!
75160    gl.texImage2D(
75161      this.glTarget,
75162      0,
75163      this.glFormat,
75164      this.glFormat,
75165      gl.UNSIGNED_BYTE,
75166      data
75167    );
75168  }
75169};
75170
75171/**
75172 * Checks if the source data for this texture has changed (if it's
75173 * easy to do so) and reuploads the texture if necessary. If it's not
75174 * possible or to expensive to do a calculation to determine wheter or
75175 * not the data has occurred, this method simply re-uploads the texture.
75176 * @method update
75177 */
75178p5.Texture.prototype.update = function() {
75179  var data = this.src;
75180  if (data.width === 0 || data.height === 0) {
75181    return; // nothing to do!
75182  }
75183
75184  var textureData = this._getTextureDataFromSource();
75185
75186  var gl = this._renderer.GL;
75187  // pull texture from data, make sure width & height are appropriate
75188  if (textureData.width !== this.width || textureData.height !== this.height) {
75189    // make sure that if the width and height of this.src have changed
75190    // for some reason, we update our metadata and upload the texture again
75191    this.width = textureData.width;
75192    this.height = textureData.height;
75193
75194    this.bindTexture();
75195    gl.texImage2D(
75196      this.glTarget,
75197      0,
75198      this.glFormat,
75199      this.glFormat,
75200      gl.UNSIGNED_BYTE,
75201      textureData
75202    );
75203
75204    if (this.isSrcP5Image) {
75205      data.setModified(false);
75206    } else if (this.isSrcMediaElement || this.isSrcHTMLElement) {
75207      // on the first frame the metadata comes in, the size will be changed
75208      // from 0 to actual size, but pixels may not be available.
75209      // flag for update in a future frame.
75210      // if we don't do this, a paused video, for example, may not
75211      // send the first frame to texture memory.
75212      data.setModified(true);
75213    }
75214  } else if (this.isSrcP5Image) {
75215    // for an image, we only update if the modified field has been set,
75216    // for example, by a call to p5.Image.set
75217    if (data.isModified()) {
75218      this.bindTexture();
75219      gl.texImage2D(
75220        this.glTarget,
75221        0,
75222        this.glFormat,
75223        this.glFormat,
75224        gl.UNSIGNED_BYTE,
75225        textureData
75226      );
75227      data.setModified(false);
75228    }
75229  } else if (this.isSrcMediaElement) {
75230    var shouldUpdate = false;
75231
75232    // for a media element (video), we'll check if the current time in
75233    // the video frame matches the last time. if it doesn't match, the
75234    // video has advanced or otherwise been taken to a new frame,
75235    // and we need to upload it.
75236    if (data.isModified()) {
75237      // p5.MediaElement may have also had set/updatePixels, etc. called
75238      // on it and should be updated, or may have been set for the first
75239      // time!
75240      shouldUpdate = true;
75241      data.setModified(false);
75242    } else if (data.loadedmetadata) {
75243      // if the meta data has been loaded, we can ask the video
75244      // what it's current position (in time) is.
75245      if (this._videoPrevUpdateTime !== data.time()) {
75246        // update the texture in gpu mem only if the current
75247        // video timestamp does not match the timestamp of the last
75248        // time we uploaded this texture (and update the time we
75249        // last uploaded, too)
75250        this._videoPrevUpdateTime = data.time();
75251        shouldUpdate = true;
75252      }
75253    }
75254
75255    if (shouldUpdate) {
75256      this.bindTexture();
75257      gl.texImage2D(
75258        this.glTarget,
75259        0,
75260        this.glFormat,
75261        this.glFormat,
75262        gl.UNSIGNED_BYTE,
75263        textureData
75264      );
75265    }
75266  } else {
75267    /* data instanceof p5.Graphics, probably */ // there is not enough information to tell if the texture can be
75268    // conditionally updated; so to be safe, we just go ahead and upload it.
75269    gl.texImage2D(
75270      this.glTarget,
75271      0,
75272      this.glFormat,
75273      this.glFormat,
75274      gl.UNSIGNED_BYTE,
75275      textureData
75276    );
75277  }
75278};
75279
75280/**
75281 * Binds the texture to the appropriate GL target.
75282 * @method bindTexture
75283 */
75284p5.Texture.prototype.bindTexture = function() {
75285  // bind texture using gl context + glTarget and
75286  // generated gl texture object
75287  var gl = this._renderer.GL;
75288  gl.bindTexture(this.glTarget, this.glTex);
75289
75290  return this;
75291};
75292
75293/**
75294 * Unbinds the texture from the appropriate GL target.
75295 * @method unbindTexture
75296 */
75297p5.Texture.prototype.unbindTexture = function() {
75298  // unbind per above, disable texturing on glTarget
75299  var gl = this._renderer.GL;
75300  gl.bindTexture(this.glTarget, null);
75301};
75302
75303module.exports = p5.Texture;
75304
75305},{"../core/core":22}],75:[function(_dereq_,module,exports){
75306/**
75307 * @module Shape
75308 * @submodule 3D Primitives
75309 * @for p5
75310 * @requires core
75311 * @requires p5.Geometry
75312 */
75313
75314'use strict';
75315
75316var p5 = _dereq_('../core/core');
75317_dereq_('./p5.Geometry');
75318
75319/**
75320 * Draw a plane with given a width and height
75321 * @method plane
75322 * @param  {Number} [width]    width of the plane
75323 * @param  {Number} [height]   height of the plane
75324 * @param  {Integer} [detailX]  Optional number of triangle
75325 *                             subdivisions in x-dimension
75326 * @param {Integer} [detailY]   Optional number of triangle
75327 *                             subdivisions in y-dimension
75328 * @chainable
75329 * @example
75330 * <div>
75331 * <code>
75332 * //draw a plane with width 50 and height 50
75333 * function setup() {
75334 *   createCanvas(100, 100, WEBGL);
75335 * }
75336 *
75337 * function draw() {
75338 *   background(200);
75339 *   plane(50, 50);
75340 * }
75341 * </code>
75342 * </div>
75343 *
75344 * @alt
75345 * Nothing displayed on canvas
75346 * Rotating interior view of a box with sides that change color.
75347 * 3d red and green gradient.
75348 * Rotating interior view of a cylinder with sides that change color.
75349 * Rotating view of a cylinder with sides that change color.
75350 * 3d red and green gradient.
75351 * rotating view of a multi-colored cylinder with concave sides.
75352 */
75353p5.prototype.plane = function(width, height, detailX, detailY) {
75354  this._assert3d('plane');
75355  p5._validateParameters('plane', arguments);
75356  if (typeof width === 'undefined') {
75357    width = 50;
75358  }
75359  if (typeof height === 'undefined') {
75360    height = width;
75361  }
75362
75363  if (typeof detailX === 'undefined') {
75364    detailX = 1;
75365  }
75366  if (typeof detailY === 'undefined') {
75367    detailY = 1;
75368  }
75369
75370  var gId = 'plane|' + detailX + '|' + detailY;
75371
75372  if (!this._renderer.geometryInHash(gId)) {
75373    var _plane = function() {
75374      var u, v, p;
75375      for (var i = 0; i <= this.detailY; i++) {
75376        v = i / this.detailY;
75377        for (var j = 0; j <= this.detailX; j++) {
75378          u = j / this.detailX;
75379          p = new p5.Vector(u - 0.5, v - 0.5, 0);
75380          this.vertices.push(p);
75381          this.uvs.push(u, v);
75382        }
75383      }
75384    };
75385    var planeGeom = new p5.Geometry(detailX, detailY, _plane);
75386    planeGeom.computeFaces().computeNormals();
75387    if (detailX <= 1 && detailY <= 1) {
75388      planeGeom._makeTriangleEdges()._edgesToVertices();
75389    } else {
75390      console.log(
75391        'Cannot draw stroke on plane objects with more' +
75392          ' than 1 detailX or 1 detailY'
75393      );
75394    }
75395    this._renderer.createBuffers(gId, planeGeom);
75396  }
75397
75398  this._renderer.drawBuffersScaled(gId, width, height, 0);
75399};
75400
75401/**
75402 * Draw a box with given width, height and depth
75403 * @method  box
75404 * @param  {Number} [width]     width of the box
75405 * @param  {Number} [Height]    height of the box
75406 * @param  {Number} [depth]     depth of the box
75407 * @param {Integer} [detailX]  Optional number of triangle
75408 *                            subdivisions in x-dimension
75409 * @param {Integer} [detailY]  Optional number of triangle
75410 *                            subdivisions in y-dimension
75411 * @chainable
75412 * @example
75413 * <div>
75414 * <code>
75415 * //draw a spinning box with width, height and depth 200
75416 * function setup() {
75417 *   createCanvas(100, 100, WEBGL);
75418 * }
75419 *
75420 * function draw() {
75421 *   background(200);
75422 *   rotateX(frameCount * 0.01);
75423 *   rotateY(frameCount * 0.01);
75424 *   box(50);
75425 * }
75426 * </code>
75427 * </div>
75428 */
75429p5.prototype.box = function(width, height, depth, detailX, detailY) {
75430  this._assert3d('box');
75431  p5._validateParameters('box', arguments);
75432  if (typeof width === 'undefined') {
75433    width = 50;
75434  }
75435  if (typeof height === 'undefined') {
75436    height = width;
75437  }
75438  if (typeof depth === 'undefined') {
75439    depth = height;
75440  }
75441
75442  var perPixelLighting =
75443    this._renderer.attributes && this._renderer.attributes.perPixelLighting;
75444  if (typeof detailX === 'undefined') {
75445    detailX = perPixelLighting ? 1 : 4;
75446  }
75447  if (typeof detailY === 'undefined') {
75448    detailY = perPixelLighting ? 1 : 4;
75449  }
75450
75451  var gId = 'box|' + detailX + '|' + detailY;
75452  if (!this._renderer.geometryInHash(gId)) {
75453    var _box = function() {
75454      var cubeIndices = [
75455        [0, 4, 2, 6], // -1, 0, 0],// -x
75456        [1, 3, 5, 7], // +1, 0, 0],// +x
75457        [0, 1, 4, 5], // 0, -1, 0],// -y
75458        [2, 6, 3, 7], // 0, +1, 0],// +y
75459        [0, 2, 1, 3], // 0, 0, -1],// -z
75460        [4, 5, 6, 7] // 0, 0, +1] // +z
75461      ];
75462      //using strokeIndices instead of faces for strokes
75463      //to avoid diagonal stroke lines across face of box
75464      this.strokeIndices = [
75465        [0, 1],
75466        [1, 3],
75467        [3, 2],
75468        [6, 7],
75469        [8, 9],
75470        [9, 11],
75471        [14, 15],
75472        [16, 17],
75473        [17, 19],
75474        [18, 19],
75475        [20, 21],
75476        [22, 23]
75477      ];
75478      for (var i = 0; i < cubeIndices.length; i++) {
75479        var cubeIndex = cubeIndices[i];
75480        var v = i * 4;
75481        for (var j = 0; j < 4; j++) {
75482          var d = cubeIndex[j];
75483          //inspired by lightgl:
75484          //https://github.com/evanw/lightgl.js
75485          //octants:https://en.wikipedia.org/wiki/Octant_(solid_geometry)
75486          var octant = new p5.Vector(
75487            ((d & 1) * 2 - 1) / 2,
75488            ((d & 2) - 1) / 2,
75489            ((d & 4) / 2 - 1) / 2
75490          );
75491          this.vertices.push(octant);
75492          this.uvs.push(j & 1, (j & 2) / 2);
75493        }
75494        this.faces.push([v, v + 1, v + 2]);
75495        this.faces.push([v + 2, v + 1, v + 3]);
75496      }
75497    };
75498    var boxGeom = new p5.Geometry(detailX, detailY, _box);
75499    boxGeom.computeNormals();
75500    if (detailX <= 4 && detailY <= 4) {
75501      boxGeom._makeTriangleEdges()._edgesToVertices();
75502    } else {
75503      console.log(
75504        'Cannot draw stroke on box objects with more' +
75505          ' than 4 detailX or 4 detailY'
75506      );
75507    }
75508    //initialize our geometry buffer with
75509    //the key val pair:
75510    //geometry Id, Geom object
75511    this._renderer.createBuffers(gId, boxGeom);
75512  }
75513  this._renderer.drawBuffersScaled(gId, width, height, depth);
75514
75515  return this;
75516};
75517
75518/**
75519 * Draw a sphere with given radius
75520 * @method sphere
75521 * @param  {Number} [radius]          radius of circle
75522 * @param  {Integer} [detailX]        number of segments,
75523 *                                    the more segments the smoother geometry
75524 *                                    default is 24
75525 * @param  {Integer} [detailY]        number of segments,
75526 *                                    the more segments the smoother geometry
75527 *                                    default is 16
75528 * @chainable
75529 * @example
75530 * <div>
75531 * <code>
75532 * // draw a sphere with radius 200
75533 * function setup() {
75534 *   createCanvas(100, 100, WEBGL);
75535 * }
75536 *
75537 * function draw() {
75538 *   background(200);
75539 *   sphere(40);
75540 * }
75541 * </code>
75542 * </div>
75543 */
75544p5.prototype.sphere = function(radius, detailX, detailY) {
75545  this._assert3d('sphere');
75546  p5._validateParameters('sphere', arguments);
75547  if (typeof radius === 'undefined') {
75548    radius = 50;
75549  }
75550  if (typeof detailX === 'undefined') {
75551    detailX = 24;
75552  }
75553  if (typeof detailY === 'undefined') {
75554    detailY = 16;
75555  }
75556
75557  this.ellipsoid(radius, radius, radius, detailX, detailY);
75558
75559  return this;
75560};
75561
75562/**
75563 * @private
75564 * Helper function for creating both cones and cyllinders
75565 * Will only generate well-defined geometry when bottomRadius, height > 0
75566 * and topRadius >= 0
75567 * If topRadius == 0, topCap should be false
75568 */
75569var _truncatedCone = function(
75570  bottomRadius,
75571  topRadius,
75572  height,
75573  detailX,
75574  detailY,
75575  bottomCap,
75576  topCap
75577) {
75578  bottomRadius = bottomRadius <= 0 ? 1 : bottomRadius;
75579  topRadius = topRadius < 0 ? 0 : topRadius;
75580  height = height <= 0 ? bottomRadius : height;
75581  detailX = detailX < 3 ? 3 : detailX;
75582  detailY = detailY < 1 ? 1 : detailY;
75583  bottomCap = bottomCap === undefined ? true : bottomCap;
75584  topCap = topCap === undefined ? topRadius !== 0 : topCap;
75585  var start = bottomCap ? -2 : 0;
75586  var end = detailY + (topCap ? 2 : 0);
75587  var vertsOnLayer = {};
75588  //ensure constant slant for interior vertex normals
75589  var slant = Math.atan2(bottomRadius - topRadius, height);
75590  var yy, ii, jj, nextii, nextjj;
75591  for (yy = start; yy <= end; ++yy) {
75592    var v = yy / detailY;
75593    var y = height * v;
75594    var ringRadius;
75595    if (yy < 0) {
75596      //for the bottomCap edge
75597      y = 0;
75598      v = 0;
75599      ringRadius = bottomRadius;
75600    } else if (yy > detailY) {
75601      //for the topCap edge
75602      y = height;
75603      v = 1;
75604      ringRadius = topRadius;
75605    } else {
75606      //for the middle
75607      ringRadius = bottomRadius + (topRadius - bottomRadius) * v;
75608    }
75609    if (yy === -2 || yy === detailY + 2) {
75610      //center of bottom or top caps
75611      ringRadius = 0;
75612    }
75613
75614    y -= height / 2; //shift coordiate origin to the center of object
75615    vertsOnLayer[yy] = ringRadius === 0 ? 1 : detailX;
75616    for (ii = 0; ii < vertsOnLayer[yy]; ++ii) {
75617      var u = ii / detailX;
75618      //VERTICES
75619      this.vertices.push(
75620        new p5.Vector(
75621          Math.sin(u * 2 * Math.PI) * ringRadius,
75622          y,
75623          Math.cos(u * 2 * Math.PI) * ringRadius
75624        )
75625      );
75626      //VERTEX NORMALS
75627      this.vertexNormals.push(
75628        new p5.Vector(
75629          yy < 0 || yy > detailY
75630            ? 0
75631            : Math.sin(u * 2 * Math.PI) * Math.cos(slant),
75632          yy < 0 ? -1 : yy > detailY ? 1 : Math.sin(slant),
75633          yy < 0 || yy > detailY
75634            ? 0
75635            : Math.cos(u * 2 * Math.PI) * Math.cos(slant)
75636        )
75637      );
75638      //UVs
75639      this.uvs.push(u, v);
75640    }
75641  }
75642
75643  var startIndex = 0;
75644  if (bottomCap) {
75645    for (jj = 0; jj < vertsOnLayer[-1]; ++jj) {
75646      nextjj = (jj + 1) % vertsOnLayer[-1];
75647      this.faces.push([
75648        startIndex,
75649        startIndex + 1 + nextjj,
75650        startIndex + 1 + jj
75651      ]);
75652    }
75653    startIndex += vertsOnLayer[-2] + vertsOnLayer[-1];
75654  }
75655  for (yy = 0; yy < detailY; ++yy) {
75656    for (ii = 0; ii < vertsOnLayer[yy]; ++ii) {
75657      if (vertsOnLayer[yy + 1] === 1) {
75658        //top layer
75659        nextii = (ii + 1) % vertsOnLayer[yy];
75660        this.faces.push([
75661          startIndex + ii,
75662          startIndex + nextii,
75663          startIndex + vertsOnLayer[yy]
75664        ]);
75665      } else {
75666        //other side faces
75667        //should have vertsOnLayer[yy] === vertsOnLayer[yy + 1]
75668        nextii = (ii + 1) % vertsOnLayer[yy];
75669        this.faces.push([
75670          startIndex + ii,
75671          startIndex + nextii,
75672          startIndex + vertsOnLayer[yy] + nextii
75673        ]);
75674        this.faces.push([
75675          startIndex + ii,
75676          startIndex + vertsOnLayer[yy] + nextii,
75677          startIndex + vertsOnLayer[yy] + ii
75678        ]);
75679      }
75680    }
75681    startIndex += vertsOnLayer[yy];
75682  }
75683  if (topCap) {
75684    startIndex += vertsOnLayer[detailY];
75685    for (ii = 0; ii < vertsOnLayer[detailY + 1]; ++ii) {
75686      nextii = (ii + 1) % vertsOnLayer[detailY + 1];
75687      this.faces.push([
75688        startIndex + ii,
75689        startIndex + nextii,
75690        startIndex + vertsOnLayer[detailY + 1]
75691      ]);
75692    }
75693  }
75694};
75695
75696/**
75697 * Draw a cylinder with given radius and height
75698 * @method cylinder
75699 * @param  {Number}  [radius]    radius of the surface
75700 * @param  {Number}  [height]    height of the cylinder
75701 * @param  {Integer} [detailX]   number of segments,
75702 *                               the more segments the smoother geometry
75703 *                               default is 24
75704 * @param  {Integer} [detailY]   number of segments in y-dimension,
75705 *                               the more segments the smoother geometry
75706 *                               default is 1
75707 * @param  {Boolean} [bottomCap] whether to draw the bottom of the cylinder
75708 * @param  {Boolean} [topCap]    whether to draw the top of the cylinder
75709 * @chainable
75710 * @example
75711 * <div>
75712 * <code>
75713 * //draw a spinning cylinder with radius 20 and height 50
75714 * function setup() {
75715 *   createCanvas(100, 100, WEBGL);
75716 * }
75717 *
75718 * function draw() {
75719 *   background(200);
75720 *   rotateX(frameCount * 0.01);
75721 *   rotateZ(frameCount * 0.01);
75722 *   cylinder(20, 50);
75723 * }
75724 * </code>
75725 * </div>
75726 */
75727p5.prototype.cylinder = function(
75728  radius,
75729  height,
75730  detailX,
75731  detailY,
75732  bottomCap,
75733  topCap
75734) {
75735  this._assert3d('cylinder');
75736  p5._validateParameters('cylinder', arguments);
75737  if (typeof radius === 'undefined') {
75738    radius = 50;
75739  }
75740  if (typeof height === 'undefined') {
75741    height = radius;
75742  }
75743  if (typeof detailX === 'undefined') {
75744    detailX = 24;
75745  }
75746  if (typeof detailY === 'undefined') {
75747    detailY = 1;
75748  }
75749  if (typeof topCap === 'undefined') {
75750    topCap = true;
75751  }
75752  if (typeof bottomCap === 'undefined') {
75753    bottomCap = true;
75754  }
75755
75756  var gId =
75757    'cylinder|' + detailX + '|' + detailY + '|' + bottomCap + '|' + topCap;
75758  if (!this._renderer.geometryInHash(gId)) {
75759    var cylinderGeom = new p5.Geometry(detailX, detailY);
75760    _truncatedCone.call(
75761      cylinderGeom,
75762      1,
75763      1,
75764      1,
75765      detailX,
75766      detailY,
75767      bottomCap,
75768      topCap
75769    );
75770    cylinderGeom.computeNormals();
75771    if (detailX <= 24 && detailY <= 16) {
75772      cylinderGeom._makeTriangleEdges()._edgesToVertices();
75773    } else {
75774      console.log(
75775        'Cannot draw stroke on cylinder objects with more' +
75776          ' than 24 detailX or 16 detailY'
75777      );
75778    }
75779    this._renderer.createBuffers(gId, cylinderGeom);
75780  }
75781
75782  this._renderer.drawBuffersScaled(gId, radius, height, radius);
75783
75784  return this;
75785};
75786
75787/**
75788 * Draw a cone with given radius and height
75789 * @method cone
75790 * @param  {Number}  [radius]  radius of the bottom surface
75791 * @param  {Number}  [height]  height of the cone
75792 * @param  {Integer} [detailX] number of segments,
75793 *                             the more segments the smoother geometry
75794 *                             default is 24
75795 * @param  {Integer} [detailY] number of segments,
75796 *                             the more segments the smoother geometry
75797 *                             default is 1
75798 * @param  {Boolean} [cap]     whether to draw the base of the cone
75799 * @chainable
75800 * @example
75801 * <div>
75802 * <code>
75803 * //draw a spinning cone with radius 40 and height 70
75804 * function setup() {
75805 *   createCanvas(100, 100, WEBGL);
75806 * }
75807 *
75808 * function draw() {
75809 *   background(200);
75810 *   rotateX(frameCount * 0.01);
75811 *   rotateZ(frameCount * 0.01);
75812 *   cone(40, 70);
75813 * }
75814 * </code>
75815 * </div>
75816 */
75817p5.prototype.cone = function(radius, height, detailX, detailY, cap) {
75818  this._assert3d('cone');
75819  p5._validateParameters('cone', arguments);
75820  if (typeof radius === 'undefined') {
75821    radius = 50;
75822  }
75823  if (typeof height === 'undefined') {
75824    height = radius;
75825  }
75826  if (typeof detailX === 'undefined') {
75827    detailX = 24;
75828  }
75829  if (typeof detailY === 'undefined') {
75830    detailY = 1;
75831  }
75832  if (typeof cap === 'undefined') {
75833    cap = true;
75834  }
75835
75836  var gId = 'cone|' + detailX + '|' + detailY + '|' + cap;
75837  if (!this._renderer.geometryInHash(gId)) {
75838    var coneGeom = new p5.Geometry(detailX, detailY);
75839    _truncatedCone.call(coneGeom, 1, 0, 1, detailX, detailY, cap, false);
75840    //for cones we need to average Normals
75841    coneGeom.computeNormals();
75842    if (detailX <= 24 && detailY <= 16) {
75843      coneGeom._makeTriangleEdges()._edgesToVertices();
75844    } else {
75845      console.log(
75846        'Cannot draw stroke on cone objects with more' +
75847          ' than 24 detailX or 16 detailY'
75848      );
75849    }
75850    this._renderer.createBuffers(gId, coneGeom);
75851  }
75852
75853  this._renderer.drawBuffersScaled(gId, radius, height, radius);
75854
75855  return this;
75856};
75857
75858/**
75859 * Draw an ellipsoid with given radius
75860 * @method ellipsoid
75861 * @param  {Number} [radiusx]         xradius of circle
75862 * @param  {Number} [radiusy]         yradius of circle
75863 * @param  {Number} [radiusz]         zradius of circle
75864 * @param  {Integer} [detailX]        number of segments,
75865 *                                    the more segments the smoother geometry
75866 *                                    default is 24. Avoid detail number above
75867 *                                    150, it may crash the browser.
75868 * @param  {Integer} [detailY]        number of segments,
75869 *                                    the more segments the smoother geometry
75870 *                                    default is 16. Avoid detail number above
75871 *                                    150, it may crash the browser.
75872 * @chainable
75873 * @example
75874 * <div>
75875 * <code>
75876 * // draw an ellipsoid with radius 20, 30 and 40.
75877 * function setup() {
75878 *   createCanvas(100, 100, WEBGL);
75879 * }
75880 *
75881 * function draw() {
75882 *   background(200);
75883 *   ellipsoid(20, 30, 40);
75884 * }
75885 * </code>
75886 * </div>
75887 */
75888p5.prototype.ellipsoid = function(radiusX, radiusY, radiusZ, detailX, detailY) {
75889  this._assert3d('ellipsoid');
75890  p5._validateParameters('ellipsoid', arguments);
75891  if (typeof radiusX === 'undefined') {
75892    radiusX = 50;
75893  }
75894  if (typeof radiusY === 'undefined') {
75895    radiusY = radiusX;
75896  }
75897  if (typeof radiusZ === 'undefined') {
75898    radiusZ = radiusX;
75899  }
75900
75901  if (typeof detailX === 'undefined') {
75902    detailX = 24;
75903  }
75904  if (typeof detailY === 'undefined') {
75905    detailY = 16;
75906  }
75907
75908  var gId = 'ellipsoid|' + detailX + '|' + detailY;
75909
75910  if (!this._renderer.geometryInHash(gId)) {
75911    var _ellipsoid = function() {
75912      for (var i = 0; i <= this.detailY; i++) {
75913        var v = i / this.detailY;
75914        var phi = Math.PI * v - Math.PI / 2;
75915        var cosPhi = Math.cos(phi);
75916        var sinPhi = Math.sin(phi);
75917
75918        for (var j = 0; j <= this.detailX; j++) {
75919          var u = j / this.detailX;
75920          var theta = 2 * Math.PI * u;
75921          var cosTheta = Math.cos(theta);
75922          var sinTheta = Math.sin(theta);
75923          var p = new p5.Vector(cosPhi * sinTheta, sinPhi, cosPhi * cosTheta);
75924          this.vertices.push(p);
75925          this.vertexNormals.push(p);
75926          this.uvs.push(u, v);
75927        }
75928      }
75929    };
75930    var ellipsoidGeom = new p5.Geometry(detailX, detailY, _ellipsoid);
75931    ellipsoidGeom.computeFaces();
75932    if (detailX <= 24 && detailY <= 24) {
75933      ellipsoidGeom._makeTriangleEdges()._edgesToVertices();
75934    } else {
75935      console.log(
75936        'Cannot draw stroke on ellipsoids with more' +
75937          ' than 24 detailX or 24 detailY'
75938      );
75939    }
75940    this._renderer.createBuffers(gId, ellipsoidGeom);
75941  }
75942
75943  this._renderer.drawBuffersScaled(gId, radiusX, radiusY, radiusZ);
75944
75945  return this;
75946};
75947
75948/**
75949 * Draw a torus with given radius and tube radius
75950 * @method torus
75951 * @param  {Number} [radius]      radius of the whole ring
75952 * @param  {Number} [tubeRadius]  radius of the tube
75953 * @param  {Integer} [detailX]    number of segments in x-dimension,
75954 *                                the more segments the smoother geometry
75955 *                                default is 24
75956 * @param  {Integer} [detailY]    number of segments in y-dimension,
75957 *                                the more segments the smoother geometry
75958 *                                default is 16
75959 * @chainable
75960 * @example
75961 * <div>
75962 * <code>
75963 * //draw a spinning torus with radius 200 and tube radius 60
75964 * function setup() {
75965 *   createCanvas(100, 100, WEBGL);
75966 * }
75967 *
75968 * function draw() {
75969 *   background(200);
75970 *   rotateX(frameCount * 0.01);
75971 *   rotateY(frameCount * 0.01);
75972 *   torus(50, 15);
75973 * }
75974 * </code>
75975 * </div>
75976 */
75977p5.prototype.torus = function(radius, tubeRadius, detailX, detailY) {
75978  this._assert3d('torus');
75979  p5._validateParameters('torus', arguments);
75980  if (typeof radius === 'undefined') {
75981    radius = 50;
75982  } else if (!radius) {
75983    return; // nothing to draw
75984  }
75985
75986  if (typeof tubeRadius === 'undefined') {
75987    tubeRadius = 10;
75988  } else if (!tubeRadius) {
75989    return; // nothing to draw
75990  }
75991
75992  if (typeof detailX === 'undefined') {
75993    detailX = 24;
75994  }
75995  if (typeof detailY === 'undefined') {
75996    detailY = 16;
75997  }
75998
75999  var tubeRatio = (tubeRadius / radius).toPrecision(4);
76000  var gId = 'torus|' + tubeRatio + '|' + detailX + '|' + detailY;
76001
76002  if (!this._renderer.geometryInHash(gId)) {
76003    var _torus = function() {
76004      for (var i = 0; i <= this.detailY; i++) {
76005        var v = i / this.detailY;
76006        var phi = 2 * Math.PI * v;
76007        var cosPhi = Math.cos(phi);
76008        var sinPhi = Math.sin(phi);
76009        var r = 1 + tubeRatio * cosPhi;
76010
76011        for (var j = 0; j <= this.detailX; j++) {
76012          var u = j / this.detailX;
76013          var theta = 2 * Math.PI * u;
76014          var cosTheta = Math.cos(theta);
76015          var sinTheta = Math.sin(theta);
76016
76017          var p = new p5.Vector(r * cosTheta, r * sinTheta, tubeRatio * sinPhi);
76018
76019          var n = new p5.Vector(cosPhi * cosTheta, cosPhi * sinTheta, sinPhi);
76020
76021          this.vertices.push(p);
76022          this.vertexNormals.push(n);
76023          this.uvs.push(u, v);
76024        }
76025      }
76026    };
76027    var torusGeom = new p5.Geometry(detailX, detailY, _torus);
76028    torusGeom.computeFaces();
76029    if (detailX <= 24 && detailY <= 16) {
76030      torusGeom._makeTriangleEdges()._edgesToVertices();
76031    } else {
76032      console.log(
76033        'Cannot draw strokes on torus object with more' +
76034          ' than 24 detailX or 16 detailY'
76035      );
76036    }
76037    this._renderer.createBuffers(gId, torusGeom);
76038  }
76039  this._renderer.drawBuffersScaled(gId, radius, radius, radius);
76040
76041  return this;
76042};
76043
76044///////////////////////
76045/// 2D primitives
76046/////////////////////////
76047
76048//@TODO
76049p5.RendererGL.prototype.point = function(x, y, z) {
76050  console.log('point not yet implemented in webgl');
76051  return this;
76052};
76053
76054p5.RendererGL.prototype.triangle = function(args) {
76055  var x1 = args[0],
76056    y1 = args[1];
76057  var x2 = args[2],
76058    y2 = args[3];
76059  var x3 = args[4],
76060    y3 = args[5];
76061
76062  var gId = 'tri';
76063  if (!this.geometryInHash(gId)) {
76064    var _triangle = function() {
76065      var vertices = [];
76066      vertices.push(new p5.Vector(0, 0, 0));
76067      vertices.push(new p5.Vector(0, 1, 0));
76068      vertices.push(new p5.Vector(1, 0, 0));
76069      this.strokeIndices = [[0, 1], [1, 2], [2, 0]];
76070      this.vertices = vertices;
76071      this.faces = [[0, 1, 2]];
76072      this.uvs = [0, 0, 0, 1, 1, 1];
76073    };
76074    var triGeom = new p5.Geometry(1, 1, _triangle);
76075    triGeom._makeTriangleEdges()._edgesToVertices();
76076    triGeom.computeNormals();
76077    this.createBuffers(gId, triGeom);
76078  }
76079
76080  // only one triangle is cached, one point is at the origin, and the
76081  // two adjacent sides are tne unit vectors along the X & Y axes.
76082  //
76083  // this matrix multiplication transforms those two unit vectors
76084  // onto the required vector prior to rendering, and moves the
76085  // origin appropriately.
76086  var uMVMatrix = this.uMVMatrix.copy();
76087  try {
76088    // prettier-ignore
76089    var mult = new p5.Matrix([
76090      x2 - x1, y2 - y1, 0, 0, // the resulting unit X-axis
76091      x3 - x1, y3 - y1, 0, 0, // the resulting unit Y-axis
76092      0, 0, 1, 0,             // the resulting unit Z-axis (unchanged)
76093      x1, y1, 0, 1            // the resulting origin
76094    ]).mult(this.uMVMatrix);
76095
76096    this.uMVMatrix = mult;
76097
76098    this.drawBuffers(gId);
76099  } finally {
76100    this.uMVMatrix = uMVMatrix;
76101  }
76102
76103  return this;
76104};
76105
76106p5.RendererGL.prototype.ellipse = function(args) {
76107  var x = args[0];
76108  var y = args[1];
76109  var width = args[2];
76110  var height = args[3];
76111  //detailX and Y are optional 6th & 7th
76112  //arguments
76113  var detailX = args[4] || 24;
76114  var gId = 'ellipse|' + detailX;
76115  if (!this.geometryInHash(gId)) {
76116    var _ellipse = function() {
76117      this.vertices.push(new p5.Vector(0.5, 0.5, 0));
76118      this.uvs.push([0.5, 0.5]);
76119
76120      for (var i = 0; i < this.detailX; i++) {
76121        var u = i / this.detailX;
76122        var theta = 2 * Math.PI * u;
76123
76124        var _x = 0.5 + Math.cos(theta) / 2;
76125        var _y = 0.5 + Math.sin(theta) / 2;
76126
76127        this.vertices.push(new p5.Vector(_x, _y, 0));
76128        this.uvs.push(_x, _y);
76129
76130        this.faces.push([0, (i + 1) % this.detailX + 1, i + 1]);
76131      }
76132    };
76133    var ellipseGeom = new p5.Geometry(detailX, 1, _ellipse);
76134    ellipseGeom.computeNormals();
76135    if (detailX <= 50) {
76136      ellipseGeom._makeTriangleEdges()._edgesToVertices();
76137    } else {
76138      console.log('Cannot stroke ellipse with more than 50 detailX');
76139    }
76140
76141    this.createBuffers(gId, ellipseGeom);
76142  }
76143
76144  // only a single ellipse (of a given detail) is cached: a circle of
76145  // _diameter_ 1 (radius 0.5).
76146  //
76147  // before rendering, this circle is squished (technical term ;)
76148  // appropriately and moved to the required location.
76149  var uMVMatrix = this.uMVMatrix.copy();
76150  try {
76151    this.uMVMatrix.translate([x, y, 0]);
76152    this.uMVMatrix.scale(width, height, 1);
76153
76154    this.drawBuffers(gId);
76155  } finally {
76156    this.uMVMatrix = uMVMatrix;
76157  }
76158  return this;
76159};
76160
76161p5.RendererGL.prototype.rect = function(args) {
76162  var perPixelLighting = this.attributes.perPixelLighting;
76163  var x = args[0];
76164  var y = args[1];
76165  var width = args[2];
76166  var height = args[3];
76167  var detailX = args[4] || (perPixelLighting ? 1 : 24);
76168  var detailY = args[5] || (perPixelLighting ? 1 : 16);
76169  var gId = 'rect|' + detailX + '|' + detailY;
76170  if (!this.geometryInHash(gId)) {
76171    var _rect = function() {
76172      for (var i = 0; i <= this.detailY; i++) {
76173        var v = i / this.detailY;
76174        for (var j = 0; j <= this.detailX; j++) {
76175          var u = j / this.detailX;
76176          var p = new p5.Vector(u, v, 0);
76177          this.vertices.push(p);
76178          this.uvs.push(u, v);
76179        }
76180      }
76181    };
76182    var rectGeom = new p5.Geometry(detailX, detailY, _rect);
76183    rectGeom
76184      .computeFaces()
76185      .computeNormals()
76186      ._makeTriangleEdges()
76187      ._edgesToVertices();
76188    this.createBuffers(gId, rectGeom);
76189  }
76190
76191  // only a single rectangle (of a given detail) is cached: a square with
76192  // opposite corners at (0,0) & (1,1).
76193  //
76194  // before rendering, this square is scaled & moved to the required location.
76195  var uMVMatrix = this.uMVMatrix.copy();
76196  try {
76197    this.uMVMatrix.translate([x, y, 0]);
76198    this.uMVMatrix.scale(width, height, 1);
76199
76200    this.drawBuffers(gId);
76201  } finally {
76202    this.uMVMatrix = uMVMatrix;
76203  }
76204  return this;
76205};
76206
76207p5.RendererGL.prototype.quad = function(x1, y1, x2, y2, x3, y3, x4, y4) {
76208  var gId =
76209    'quad|' +
76210    x1 +
76211    '|' +
76212    y1 +
76213    '|' +
76214    x2 +
76215    '|' +
76216    y2 +
76217    '|' +
76218    x3 +
76219    '|' +
76220    y3 +
76221    '|' +
76222    x4 +
76223    '|' +
76224    y4;
76225  if (!this.geometryInHash(gId)) {
76226    var _quad = function() {
76227      this.vertices.push(new p5.Vector(x1, y1, 0));
76228      this.vertices.push(new p5.Vector(x2, y2, 0));
76229      this.vertices.push(new p5.Vector(x3, y3, 0));
76230      this.vertices.push(new p5.Vector(x4, y4, 0));
76231      this.uvs.push(0, 0, 1, 0, 1, 1, 0, 1);
76232      this.strokeIndices = [[0, 1], [1, 2], [2, 3], [3, 0]];
76233    };
76234    var quadGeom = new p5.Geometry(2, 2, _quad);
76235    quadGeom
76236      .computeNormals()
76237      ._makeTriangleEdges()
76238      ._edgesToVertices();
76239    quadGeom.faces = [[0, 1, 2], [2, 3, 0]];
76240    this.createBuffers(gId, quadGeom);
76241  }
76242  this.drawBuffers(gId);
76243  return this;
76244};
76245
76246//this implementation of bezier curve
76247//is based on Bernstein polynomial
76248// pretier-ignore
76249p5.RendererGL.prototype.bezier = function(
76250  x1,
76251  y1,
76252  z1, // x2
76253  x2, // y2
76254  y2, // x3
76255  z2, // y3
76256  x3, // x4
76257  y3, // y4
76258  z3,
76259  x4,
76260  y4,
76261  z4
76262) {
76263  if (arguments.length === 8) {
76264    x4 = x3;
76265    y4 = y3;
76266    x3 = y2;
76267    y3 = x2;
76268    x2 = z1;
76269    y2 = x2;
76270    z1 = z2 = z3 = z4 = 0;
76271  }
76272
76273  var bezierDetail = this._pInst._bezierDetail || 20; //value of Bezier detail
76274  this.beginShape();
76275  for (var i = 0; i <= bezierDetail; i++) {
76276    var c1 = Math.pow(1 - i / bezierDetail, 3);
76277    var c2 = 3 * (i / bezierDetail) * Math.pow(1 - i / bezierDetail, 2);
76278    var c3 = 3 * Math.pow(i / bezierDetail, 2) * (1 - i / bezierDetail);
76279    var c4 = Math.pow(i / bezierDetail, 3);
76280    this.vertex(
76281      x1 * c1 + x2 * c2 + x3 * c3 + x4 * c4,
76282      y1 * c1 + y2 * c2 + y3 * c3 + y4 * c4,
76283      z1 * c1 + z2 * c2 + z3 * c3 + z4 * c4
76284    );
76285  }
76286  this.endShape();
76287  return this;
76288};
76289
76290// pretier-ignore
76291p5.RendererGL.prototype.curve = function(
76292  x1,
76293  y1,
76294  z1, // x2
76295  x2, // y2
76296  y2, // x3
76297  z2, // y3
76298  x3, // x4
76299  y3, // y4
76300  z3,
76301  x4,
76302  y4,
76303  z4
76304) {
76305  if (arguments.length === 8) {
76306    x4 = x3;
76307    y4 = y3;
76308    x3 = y2;
76309    y3 = x2;
76310    x2 = z1;
76311    y2 = x2;
76312    z1 = z2 = z3 = z4 = 0;
76313  }
76314  var curveDetail = this._pInst._curveDetail;
76315  this.beginShape();
76316  for (var i = 0; i <= curveDetail; i++) {
76317    var c1 = Math.pow(i / curveDetail, 3) * 0.5;
76318    var c2 = Math.pow(i / curveDetail, 2) * 0.5;
76319    var c3 = i / curveDetail * 0.5;
76320    var c4 = 0.5;
76321    var vx =
76322      c1 * (-x1 + 3 * x2 - 3 * x3 + x4) +
76323      c2 * (2 * x1 - 5 * x2 + 4 * x3 - x4) +
76324      c3 * (-x1 + x3) +
76325      c4 * (2 * x2);
76326    var vy =
76327      c1 * (-y1 + 3 * y2 - 3 * y3 + y4) +
76328      c2 * (2 * y1 - 5 * y2 + 4 * y3 - y4) +
76329      c3 * (-y1 + y3) +
76330      c4 * (2 * y2);
76331    var vz =
76332      c1 * (-z1 + 3 * z2 - 3 * z3 + z4) +
76333      c2 * (2 * z1 - 5 * z2 + 4 * z3 - z4) +
76334      c3 * (-z1 + z3) +
76335      c4 * (2 * z2);
76336    this.vertex(vx, vy, vz);
76337  }
76338  this.endShape();
76339  return this;
76340};
76341
76342/**
76343 * Draw a line given two points
76344 * @private
76345 * @param {Number} x0 x-coordinate of first vertex
76346 * @param {Number} y0 y-coordinate of first vertex
76347 * @param {Number} z0 z-coordinate of first vertex
76348 * @param {Number} x1 x-coordinate of second vertex
76349 * @param {Number} y1 y-coordinate of second vertex
76350 * @param {Number} z1 z-coordinate of second vertex
76351 * @chainable
76352 * @example
76353 * <div>
76354 * <code>
76355 * //draw a line
76356 * function setup() {
76357 *   createCanvas(100, 100, WEBGL);
76358 * }
76359 *
76360 * function draw() {
76361 *   background(200);
76362 *   rotateX(frameCount * 0.01);
76363 *   rotateY(frameCount * 0.01);
76364 *   // Use fill instead of stroke to change the color of shape.
76365 *   fill(255, 0, 0);
76366 *   line(10, 10, 0, 60, 60, 20);
76367 * }
76368 * </code>
76369 * </div>
76370 */
76371p5.RendererGL.prototype.line = function() {
76372  if (arguments.length === 6) {
76373    this.beginShape();
76374    this.vertex(arguments[0], arguments[1], arguments[2]);
76375    this.vertex(arguments[3], arguments[4], arguments[5]);
76376    this.endShape();
76377  } else if (arguments.length === 4) {
76378    this.beginShape();
76379    this.vertex(arguments[0], arguments[1], 0);
76380    this.vertex(arguments[2], arguments[3], 0);
76381    this.endShape();
76382  }
76383  return this;
76384};
76385
76386module.exports = p5;
76387
76388},{"../core/core":22,"./p5.Geometry":68}]},{},[13])(13)
76389});

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.