UNPKG

3.59 MBJavaScriptView Raw
1/*! p5.js v1.1.9 July 22, 2020 */
2(function(f) {
3 if (typeof exports === 'object' && typeof module !== 'undefined') {
4 module.exports = f();
5 } else if (typeof define === 'function' && define.amd) {
6 define([], f);
7 } else {
8 var g;
9 if (typeof window !== 'undefined') {
10 g = window;
11 } else if (typeof global !== 'undefined') {
12 g = global;
13 } else if (typeof self !== 'undefined') {
14 g = self;
15 } else {
16 g = this;
17 }
18 g.p5 = f();
19 }
20})(function() {
21 var define, module, exports;
22 return (function() {
23 function r(e, n, t) {
24 function o(i, f) {
25 if (!n[i]) {
26 if (!e[i]) {
27 var c = 'function' == typeof require && require;
28 if (!f && c) return c(i, !0);
29 if (u) return u(i, !0);
30 var a = new Error("Cannot find module '" + i + "'");
31 throw ((a.code = 'MODULE_NOT_FOUND'), a);
32 }
33 var p = (n[i] = { exports: {} });
34 e[i][0].call(
35 p.exports,
36 function(r) {
37 var n = e[i][1][r];
38 return o(n || r);
39 },
40 p,
41 p.exports,
42 r,
43 e,
44 n,
45 t
46 );
47 }
48 return n[i].exports;
49 }
50 for (var u = 'function' == typeof require && require, i = 0; i < t.length; i++)
51 o(t[i]);
52 return o;
53 }
54 return r;
55 })()(
56 {
57 1: [
58 function(_dereq_, module, exports) {
59 module.exports = {
60 p5: {
61 alpha: {
62 name: 'alpha',
63 params: [
64 {
65 name: 'color',
66 description:
67 '<p><a href="#/p5.Color">p5.Color</a> object, color components,\n or CSS color</p>\n',
68 type: 'p5.Color|Number[]|String'
69 }
70 ],
71 class: 'p5',
72 module: 'Color'
73 },
74 blue: {
75 name: 'blue',
76 params: [
77 {
78 name: 'color',
79 description:
80 '<p><a href="#/p5.Color">p5.Color</a> object, color components,\n or CSS color</p>\n',
81 type: 'p5.Color|Number[]|String'
82 }
83 ],
84 class: 'p5',
85 module: 'Color'
86 },
87 brightness: {
88 name: 'brightness',
89 params: [
90 {
91 name: 'color',
92 description:
93 '<p><a href="#/p5.Color">p5.Color</a> object, color components,\n or CSS color</p>\n',
94 type: 'p5.Color|Number[]|String'
95 }
96 ],
97 class: 'p5',
98 module: 'Color'
99 },
100 color: {
101 name: 'color',
102 class: 'p5',
103 module: 'Color',
104 overloads: [
105 {
106 params: [
107 {
108 name: 'gray',
109 description:
110 '<p>number specifying value between white and black.</p>\n',
111 type: 'Number'
112 },
113 {
114 name: 'alpha',
115 description:
116 '<p>alpha value relative to current color range\n (default is 0-255)</p>\n',
117 type: 'Number',
118 optional: true
119 }
120 ]
121 },
122 {
123 params: [
124 {
125 name: 'v1',
126 description:
127 '<p>red or hue value relative to\n the current color range</p>\n',
128 type: 'Number'
129 },
130 {
131 name: 'v2',
132 description:
133 '<p>green or saturation value\n relative to the current color range</p>\n',
134 type: 'Number'
135 },
136 {
137 name: 'v3',
138 description:
139 '<p>blue or brightness value\n relative to the current color range</p>\n',
140 type: 'Number'
141 },
142 {
143 name: 'alpha',
144 description: '',
145 type: 'Number',
146 optional: true
147 }
148 ]
149 },
150 {
151 params: [
152 {
153 name: 'value',
154 description: '<p>a color string</p>\n',
155 type: 'String'
156 }
157 ]
158 },
159 {
160 params: [
161 {
162 name: 'values',
163 description:
164 '<p>an array containing the red,green,blue &\n and alpha components of the color</p>\n',
165 type: 'Number[]'
166 }
167 ]
168 },
169 {
170 params: [
171 {
172 name: 'color',
173 description: '',
174 type: 'p5.Color'
175 }
176 ]
177 }
178 ]
179 },
180 green: {
181 name: 'green',
182 params: [
183 {
184 name: 'color',
185 description:
186 '<p><a href="#/p5.Color">p5.Color</a> object, color components,\n or CSS color</p>\n',
187 type: 'p5.Color|Number[]|String'
188 }
189 ],
190 class: 'p5',
191 module: 'Color'
192 },
193 hue: {
194 name: 'hue',
195 params: [
196 {
197 name: 'color',
198 description:
199 '<p><a href="#/p5.Color">p5.Color</a> object, color components,\n or CSS color</p>\n',
200 type: 'p5.Color|Number[]|String'
201 }
202 ],
203 class: 'p5',
204 module: 'Color'
205 },
206 lerpColor: {
207 name: 'lerpColor',
208 params: [
209 {
210 name: 'c1',
211 description: '<p>interpolate from this color</p>\n',
212 type: 'p5.Color'
213 },
214 {
215 name: 'c2',
216 description: '<p>interpolate to this color</p>\n',
217 type: 'p5.Color'
218 },
219 {
220 name: 'amt',
221 description: '<p>number between 0 and 1</p>\n',
222 type: 'Number'
223 }
224 ],
225 class: 'p5',
226 module: 'Color'
227 },
228 lightness: {
229 name: 'lightness',
230 params: [
231 {
232 name: 'color',
233 description:
234 '<p><a href="#/p5.Color">p5.Color</a> object, color components,\n or CSS color</p>\n',
235 type: 'p5.Color|Number[]|String'
236 }
237 ],
238 class: 'p5',
239 module: 'Color'
240 },
241 red: {
242 name: 'red',
243 params: [
244 {
245 name: 'color',
246 description:
247 '<p><a href="#/p5.Color">p5.Color</a> object, color components,\n or CSS color</p>\n',
248 type: 'p5.Color|Number[]|String'
249 }
250 ],
251 class: 'p5',
252 module: 'Color'
253 },
254 saturation: {
255 name: 'saturation',
256 params: [
257 {
258 name: 'color',
259 description:
260 '<p><a href="#/p5.Color">p5.Color</a> object, color components,\n or CSS color</p>\n',
261 type: 'p5.Color|Number[]|String'
262 }
263 ],
264 class: 'p5',
265 module: 'Color'
266 },
267 background: {
268 name: 'background',
269 class: 'p5',
270 module: 'Color',
271 overloads: [
272 {
273 params: [
274 {
275 name: 'color',
276 description:
277 '<p>any value created by the <a href="#/p5/color">color()</a> function</p>\n',
278 type: 'p5.Color'
279 }
280 ],
281 chainable: 1
282 },
283 {
284 params: [
285 {
286 name: 'colorstring',
287 description:
288 '<p>color string, possible formats include: integer\n rgb() or rgba(), percentage rgb() or rgba(),\n 3-digit hex, 6-digit hex</p>\n',
289 type: 'String'
290 },
291 {
292 name: 'a',
293 description:
294 '<p>opacity of the background relative to current\n color range (default is 0-255)</p>\n',
295 type: 'Number',
296 optional: true
297 }
298 ],
299 chainable: 1
300 },
301 {
302 params: [
303 {
304 name: 'gray',
305 description: '<p>specifies a value between white and black</p>\n',
306 type: 'Number'
307 },
308 {
309 name: 'a',
310 description: '',
311 type: 'Number',
312 optional: true
313 }
314 ],
315 chainable: 1
316 },
317 {
318 params: [
319 {
320 name: 'v1',
321 description:
322 '<p>red or hue value (depending on the current color\n mode)</p>\n',
323 type: 'Number'
324 },
325 {
326 name: 'v2',
327 description:
328 '<p>green or saturation value (depending on the current\n color mode)</p>\n',
329 type: 'Number'
330 },
331 {
332 name: 'v3',
333 description:
334 '<p>blue or brightness value (depending on the current\n color mode)</p>\n',
335 type: 'Number'
336 },
337 {
338 name: 'a',
339 description: '',
340 type: 'Number',
341 optional: true
342 }
343 ],
344 chainable: 1
345 },
346 {
347 params: [
348 {
349 name: 'values',
350 description:
351 '<p>an array containing the red, green, blue\n and alpha components of the color</p>\n',
352 type: 'Number[]'
353 }
354 ],
355 chainable: 1
356 },
357 {
358 params: [
359 {
360 name: 'image',
361 description:
362 '<p>image created with <a href="#/p5/loadImage">loadImage()</a> or <a href="#/p5/createImage">createImage()</a>,\n to set as background\n (must be same size as the sketch window)</p>\n',
363 type: 'p5.Image'
364 },
365 {
366 name: 'a',
367 description: '',
368 type: 'Number',
369 optional: true
370 }
371 ],
372 chainable: 1
373 }
374 ]
375 },
376 clear: {
377 name: 'clear',
378 class: 'p5',
379 module: 'Color'
380 },
381 colorMode: {
382 name: 'colorMode',
383 class: 'p5',
384 module: 'Color',
385 overloads: [
386 {
387 params: [
388 {
389 name: 'mode',
390 description:
391 '<p>either RGB, HSB or HSL, corresponding to\n Red/Green/Blue and Hue/Saturation/Brightness\n (or Lightness)</p>\n',
392 type: 'Constant'
393 },
394 {
395 name: 'max',
396 description: '<p>range for all values</p>\n',
397 type: 'Number',
398 optional: true
399 }
400 ],
401 chainable: 1
402 },
403 {
404 params: [
405 {
406 name: 'mode',
407 description: '',
408 type: 'Constant'
409 },
410 {
411 name: 'max1',
412 description:
413 '<p>range for the red or hue depending on the\n current color mode</p>\n',
414 type: 'Number'
415 },
416 {
417 name: 'max2',
418 description:
419 '<p>range for the green or saturation depending\n on the current color mode</p>\n',
420 type: 'Number'
421 },
422 {
423 name: 'max3',
424 description:
425 '<p>range for the blue or brightness/lightness\n depending on the current color mode</p>\n',
426 type: 'Number'
427 },
428 {
429 name: 'maxA',
430 description: '<p>range for the alpha</p>\n',
431 type: 'Number',
432 optional: true
433 }
434 ],
435 chainable: 1
436 }
437 ]
438 },
439 fill: {
440 name: 'fill',
441 class: 'p5',
442 module: 'Color',
443 overloads: [
444 {
445 params: [
446 {
447 name: 'v1',
448 description:
449 '<p>red or hue value relative to\n the current color range</p>\n',
450 type: 'Number'
451 },
452 {
453 name: 'v2',
454 description:
455 '<p>green or saturation value\n relative to the current color range</p>\n',
456 type: 'Number'
457 },
458 {
459 name: 'v3',
460 description:
461 '<p>blue or brightness value\n relative to the current color range</p>\n',
462 type: 'Number'
463 },
464 {
465 name: 'alpha',
466 description: '',
467 type: 'Number',
468 optional: true
469 }
470 ],
471 chainable: 1
472 },
473 {
474 params: [
475 {
476 name: 'value',
477 description: '<p>a color string</p>\n',
478 type: 'String'
479 }
480 ],
481 chainable: 1
482 },
483 {
484 params: [
485 {
486 name: 'gray',
487 description: '<p>a gray value</p>\n',
488 type: 'Number'
489 },
490 {
491 name: 'alpha',
492 description: '',
493 type: 'Number',
494 optional: true
495 }
496 ],
497 chainable: 1
498 },
499 {
500 params: [
501 {
502 name: 'values',
503 description:
504 '<p>an array containing the red,green,blue &\n and alpha components of the color</p>\n',
505 type: 'Number[]'
506 }
507 ],
508 chainable: 1
509 },
510 {
511 params: [
512 {
513 name: 'color',
514 description: '<p>the fill color</p>\n',
515 type: 'p5.Color'
516 }
517 ],
518 chainable: 1
519 }
520 ]
521 },
522 noFill: {
523 name: 'noFill',
524 class: 'p5',
525 module: 'Color'
526 },
527 noStroke: {
528 name: 'noStroke',
529 class: 'p5',
530 module: 'Color'
531 },
532 stroke: {
533 name: 'stroke',
534 class: 'p5',
535 module: 'Color',
536 overloads: [
537 {
538 params: [
539 {
540 name: 'v1',
541 description:
542 '<p>red or hue value relative to\n the current color range</p>\n',
543 type: 'Number'
544 },
545 {
546 name: 'v2',
547 description:
548 '<p>green or saturation value\n relative to the current color range</p>\n',
549 type: 'Number'
550 },
551 {
552 name: 'v3',
553 description:
554 '<p>blue or brightness value\n relative to the current color range</p>\n',
555 type: 'Number'
556 },
557 {
558 name: 'alpha',
559 description: '',
560 type: 'Number',
561 optional: true
562 }
563 ],
564 chainable: 1
565 },
566 {
567 params: [
568 {
569 name: 'value',
570 description: '<p>a color string</p>\n',
571 type: 'String'
572 }
573 ],
574 chainable: 1
575 },
576 {
577 params: [
578 {
579 name: 'gray',
580 description: '<p>a gray value</p>\n',
581 type: 'Number'
582 },
583 {
584 name: 'alpha',
585 description: '',
586 type: 'Number',
587 optional: true
588 }
589 ],
590 chainable: 1
591 },
592 {
593 params: [
594 {
595 name: 'values',
596 description:
597 '<p>an array containing the red,green,blue &\n and alpha components of the color</p>\n',
598 type: 'Number[]'
599 }
600 ],
601 chainable: 1
602 },
603 {
604 params: [
605 {
606 name: 'color',
607 description: '<p>the stroke color</p>\n',
608 type: 'p5.Color'
609 }
610 ],
611 chainable: 1
612 }
613 ]
614 },
615 erase: {
616 name: 'erase',
617 params: [
618 {
619 name: 'strengthFill',
620 description:
621 "<p>A number (0-255) for the strength of erasing for a shape's fill.\n This will default to 255 when no argument is given, which\n is full strength.</p>\n",
622 type: 'Number',
623 optional: true
624 },
625 {
626 name: 'strengthStroke',
627 description:
628 "<p>A number (0-255) for the strength of erasing for a shape's stroke.\n This will default to 255 when no argument is given, which\n is full strength.</p>\n",
629 type: 'Number',
630 optional: true
631 }
632 ],
633 class: 'p5',
634 module: 'Color'
635 },
636 noErase: {
637 name: 'noErase',
638 class: 'p5',
639 module: 'Color'
640 },
641 arc: {
642 name: 'arc',
643 params: [
644 {
645 name: 'x',
646 description: "<p>x-coordinate of the arc's ellipse</p>\n",
647 type: 'Number'
648 },
649 {
650 name: 'y',
651 description: "<p>y-coordinate of the arc's ellipse</p>\n",
652 type: 'Number'
653 },
654 {
655 name: 'w',
656 description: "<p>width of the arc's ellipse by default</p>\n",
657 type: 'Number'
658 },
659 {
660 name: 'h',
661 description: "<p>height of the arc's ellipse by default</p>\n",
662 type: 'Number'
663 },
664 {
665 name: 'start',
666 description: '<p>angle to start the arc, specified in radians</p>\n',
667 type: 'Number'
668 },
669 {
670 name: 'stop',
671 description: '<p>angle to stop the arc, specified in radians</p>\n',
672 type: 'Number'
673 },
674 {
675 name: 'mode',
676 description:
677 '<p>optional parameter to determine the way of drawing\n the arc. either CHORD, PIE or OPEN</p>\n',
678 type: 'Constant',
679 optional: true
680 },
681 {
682 name: 'detail',
683 description:
684 '<p>optional parameter for WebGL mode only. This is to\n specify the number of vertices that makes up the\n perimeter of the arc. Default value is 25.</p>\n',
685 type: 'Number',
686 optional: true
687 }
688 ],
689 class: 'p5',
690 module: 'Shape'
691 },
692 ellipse: {
693 name: 'ellipse',
694 class: 'p5',
695 module: 'Shape',
696 overloads: [
697 {
698 params: [
699 {
700 name: 'x',
701 description: '<p>x-coordinate of the center of ellipse.</p>\n',
702 type: 'Number'
703 },
704 {
705 name: 'y',
706 description: '<p>y-coordinate of the center of ellipse.</p>\n',
707 type: 'Number'
708 },
709 {
710 name: 'w',
711 description: '<p>width of the ellipse.</p>\n',
712 type: 'Number'
713 },
714 {
715 name: 'h',
716 description: '<p>height of the ellipse.</p>\n',
717 type: 'Number',
718 optional: true
719 }
720 ],
721 chainable: 1
722 },
723 {
724 params: [
725 {
726 name: 'x',
727 description: '',
728 type: 'Number'
729 },
730 {
731 name: 'y',
732 description: '',
733 type: 'Number'
734 },
735 {
736 name: 'w',
737 description: '',
738 type: 'Number'
739 },
740 {
741 name: 'h',
742 description: '',
743 type: 'Number'
744 },
745 {
746 name: 'detail',
747 description:
748 '<p>number of radial sectors to draw (for WebGL mode)</p>\n',
749 type: 'Integer'
750 }
751 ]
752 }
753 ]
754 },
755 circle: {
756 name: 'circle',
757 params: [
758 {
759 name: 'x',
760 description: '<p>x-coordinate of the centre of the circle.</p>\n',
761 type: 'Number'
762 },
763 {
764 name: 'y',
765 description: '<p>y-coordinate of the centre of the circle.</p>\n',
766 type: 'Number'
767 },
768 {
769 name: 'd',
770 description: '<p>diameter of the circle.</p>\n',
771 type: 'Number'
772 }
773 ],
774 class: 'p5',
775 module: 'Shape'
776 },
777 line: {
778 name: 'line',
779 class: 'p5',
780 module: 'Shape',
781 overloads: [
782 {
783 params: [
784 {
785 name: 'x1',
786 description: '<p>the x-coordinate of the first point</p>\n',
787 type: 'Number'
788 },
789 {
790 name: 'y1',
791 description: '<p>the y-coordinate of the first point</p>\n',
792 type: 'Number'
793 },
794 {
795 name: 'x2',
796 description: '<p>the x-coordinate of the second point</p>\n',
797 type: 'Number'
798 },
799 {
800 name: 'y2',
801 description: '<p>the y-coordinate of the second point</p>\n',
802 type: 'Number'
803 }
804 ],
805 chainable: 1
806 },
807 {
808 params: [
809 {
810 name: 'x1',
811 description: '',
812 type: 'Number'
813 },
814 {
815 name: 'y1',
816 description: '',
817 type: 'Number'
818 },
819 {
820 name: 'z1',
821 description: '<p>the z-coordinate of the first point</p>\n',
822 type: 'Number'
823 },
824 {
825 name: 'x2',
826 description: '',
827 type: 'Number'
828 },
829 {
830 name: 'y2',
831 description: '',
832 type: 'Number'
833 },
834 {
835 name: 'z2',
836 description: '<p>the z-coordinate of the second point</p>\n',
837 type: 'Number'
838 }
839 ],
840 chainable: 1
841 }
842 ]
843 },
844 point: {
845 name: 'point',
846 class: 'p5',
847 module: 'Shape',
848 overloads: [
849 {
850 params: [
851 {
852 name: 'x',
853 description: '<p>the x-coordinate</p>\n',
854 type: 'Number'
855 },
856 {
857 name: 'y',
858 description: '<p>the y-coordinate</p>\n',
859 type: 'Number'
860 },
861 {
862 name: 'z',
863 description: '<p>the z-coordinate (for WebGL mode)</p>\n',
864 type: 'Number',
865 optional: true
866 }
867 ],
868 chainable: 1
869 },
870 {
871 params: [
872 {
873 name: 'coordinate_vector',
874 description: '<p>the coordinate vector</p>\n',
875 type: 'p5.Vector'
876 }
877 ],
878 chainable: 1
879 }
880 ]
881 },
882 quad: {
883 name: 'quad',
884 class: 'p5',
885 module: 'Shape',
886 overloads: [
887 {
888 params: [
889 {
890 name: 'x1',
891 description: '<p>the x-coordinate of the first point</p>\n',
892 type: 'Number'
893 },
894 {
895 name: 'y1',
896 description: '<p>the y-coordinate of the first point</p>\n',
897 type: 'Number'
898 },
899 {
900 name: 'x2',
901 description: '<p>the x-coordinate of the second point</p>\n',
902 type: 'Number'
903 },
904 {
905 name: 'y2',
906 description: '<p>the y-coordinate of the second point</p>\n',
907 type: 'Number'
908 },
909 {
910 name: 'x3',
911 description: '<p>the x-coordinate of the third point</p>\n',
912 type: 'Number'
913 },
914 {
915 name: 'y3',
916 description: '<p>the y-coordinate of the third point</p>\n',
917 type: 'Number'
918 },
919 {
920 name: 'x4',
921 description: '<p>the x-coordinate of the fourth point</p>\n',
922 type: 'Number'
923 },
924 {
925 name: 'y4',
926 description: '<p>the y-coordinate of the fourth point</p>\n',
927 type: 'Number'
928 }
929 ],
930 chainable: 1
931 },
932 {
933 params: [
934 {
935 name: 'x1',
936 description: '',
937 type: 'Number'
938 },
939 {
940 name: 'y1',
941 description: '',
942 type: 'Number'
943 },
944 {
945 name: 'z1',
946 description: '<p>the z-coordinate of the first point</p>\n',
947 type: 'Number'
948 },
949 {
950 name: 'x2',
951 description: '',
952 type: 'Number'
953 },
954 {
955 name: 'y2',
956 description: '',
957 type: 'Number'
958 },
959 {
960 name: 'z2',
961 description: '<p>the z-coordinate of the second point</p>\n',
962 type: 'Number'
963 },
964 {
965 name: 'x3',
966 description: '',
967 type: 'Number'
968 },
969 {
970 name: 'y3',
971 description: '',
972 type: 'Number'
973 },
974 {
975 name: 'z3',
976 description: '<p>the z-coordinate of the third point</p>\n',
977 type: 'Number'
978 },
979 {
980 name: 'x4',
981 description: '',
982 type: 'Number'
983 },
984 {
985 name: 'y4',
986 description: '',
987 type: 'Number'
988 },
989 {
990 name: 'z4',
991 description: '<p>the z-coordinate of the fourth point</p>\n',
992 type: 'Number'
993 }
994 ],
995 chainable: 1
996 }
997 ]
998 },
999 rect: {
1000 name: 'rect',
1001 class: 'p5',
1002 module: 'Shape',
1003 overloads: [
1004 {
1005 params: [
1006 {
1007 name: 'x',
1008 description: '<p>x-coordinate of the rectangle.</p>\n',
1009 type: 'Number'
1010 },
1011 {
1012 name: 'y',
1013 description: '<p>y-coordinate of the rectangle.</p>\n',
1014 type: 'Number'
1015 },
1016 {
1017 name: 'w',
1018 description: '<p>width of the rectangle.</p>\n',
1019 type: 'Number'
1020 },
1021 {
1022 name: 'h',
1023 description: '<p>height of the rectangle.</p>\n',
1024 type: 'Number',
1025 optional: true
1026 },
1027 {
1028 name: 'tl',
1029 description: '<p>optional radius of top-left corner.</p>\n',
1030 type: 'Number',
1031 optional: true
1032 },
1033 {
1034 name: 'tr',
1035 description: '<p>optional radius of top-right corner.</p>\n',
1036 type: 'Number',
1037 optional: true
1038 },
1039 {
1040 name: 'br',
1041 description: '<p>optional radius of bottom-right corner.</p>\n',
1042 type: 'Number',
1043 optional: true
1044 },
1045 {
1046 name: 'bl',
1047 description: '<p>optional radius of bottom-left corner.</p>\n',
1048 type: 'Number',
1049 optional: true
1050 }
1051 ],
1052 chainable: 1
1053 },
1054 {
1055 params: [
1056 {
1057 name: 'x',
1058 description: '',
1059 type: 'Number'
1060 },
1061 {
1062 name: 'y',
1063 description: '',
1064 type: 'Number'
1065 },
1066 {
1067 name: 'w',
1068 description: '',
1069 type: 'Number'
1070 },
1071 {
1072 name: 'h',
1073 description: '',
1074 type: 'Number'
1075 },
1076 {
1077 name: 'detailX',
1078 description:
1079 '<p>number of segments in the x-direction (for WebGL mode)</p>\n',
1080 type: 'Integer',
1081 optional: true
1082 },
1083 {
1084 name: 'detailY',
1085 description:
1086 '<p>number of segments in the y-direction (for WebGL mode)</p>\n',
1087 type: 'Integer',
1088 optional: true
1089 }
1090 ],
1091 chainable: 1
1092 }
1093 ]
1094 },
1095 square: {
1096 name: 'square',
1097 params: [
1098 {
1099 name: 'x',
1100 description: '<p>x-coordinate of the square.</p>\n',
1101 type: 'Number'
1102 },
1103 {
1104 name: 'y',
1105 description: '<p>y-coordinate of the square.</p>\n',
1106 type: 'Number'
1107 },
1108 {
1109 name: 's',
1110 description: '<p>side size of the square.</p>\n',
1111 type: 'Number'
1112 },
1113 {
1114 name: 'tl',
1115 description: '<p>optional radius of top-left corner.</p>\n',
1116 type: 'Number',
1117 optional: true
1118 },
1119 {
1120 name: 'tr',
1121 description: '<p>optional radius of top-right corner.</p>\n',
1122 type: 'Number',
1123 optional: true
1124 },
1125 {
1126 name: 'br',
1127 description: '<p>optional radius of bottom-right corner.</p>\n',
1128 type: 'Number',
1129 optional: true
1130 },
1131 {
1132 name: 'bl',
1133 description: '<p>optional radius of bottom-left corner.</p>\n',
1134 type: 'Number',
1135 optional: true
1136 }
1137 ],
1138 class: 'p5',
1139 module: 'Shape'
1140 },
1141 triangle: {
1142 name: 'triangle',
1143 params: [
1144 {
1145 name: 'x1',
1146 description: '<p>x-coordinate of the first point</p>\n',
1147 type: 'Number'
1148 },
1149 {
1150 name: 'y1',
1151 description: '<p>y-coordinate of the first point</p>\n',
1152 type: 'Number'
1153 },
1154 {
1155 name: 'x2',
1156 description: '<p>x-coordinate of the second point</p>\n',
1157 type: 'Number'
1158 },
1159 {
1160 name: 'y2',
1161 description: '<p>y-coordinate of the second point</p>\n',
1162 type: 'Number'
1163 },
1164 {
1165 name: 'x3',
1166 description: '<p>x-coordinate of the third point</p>\n',
1167 type: 'Number'
1168 },
1169 {
1170 name: 'y3',
1171 description: '<p>y-coordinate of the third point</p>\n',
1172 type: 'Number'
1173 }
1174 ],
1175 class: 'p5',
1176 module: 'Shape'
1177 },
1178 ellipseMode: {
1179 name: 'ellipseMode',
1180 params: [
1181 {
1182 name: 'mode',
1183 description: '<p>either CENTER, RADIUS, CORNER, or CORNERS</p>\n',
1184 type: 'Constant'
1185 }
1186 ],
1187 class: 'p5',
1188 module: 'Shape'
1189 },
1190 noSmooth: {
1191 name: 'noSmooth',
1192 class: 'p5',
1193 module: 'Shape'
1194 },
1195 rectMode: {
1196 name: 'rectMode',
1197 params: [
1198 {
1199 name: 'mode',
1200 description: '<p>either CORNER, CORNERS, CENTER, or RADIUS</p>\n',
1201 type: 'Constant'
1202 }
1203 ],
1204 class: 'p5',
1205 module: 'Shape'
1206 },
1207 smooth: {
1208 name: 'smooth',
1209 class: 'p5',
1210 module: 'Shape'
1211 },
1212 strokeCap: {
1213 name: 'strokeCap',
1214 params: [
1215 {
1216 name: 'cap',
1217 description: '<p>either ROUND, SQUARE or PROJECT</p>\n',
1218 type: 'Constant'
1219 }
1220 ],
1221 class: 'p5',
1222 module: 'Shape'
1223 },
1224 strokeJoin: {
1225 name: 'strokeJoin',
1226 params: [
1227 {
1228 name: 'join',
1229 description: '<p>either MITER, BEVEL, ROUND</p>\n',
1230 type: 'Constant'
1231 }
1232 ],
1233 class: 'p5',
1234 module: 'Shape'
1235 },
1236 strokeWeight: {
1237 name: 'strokeWeight',
1238 params: [
1239 {
1240 name: 'weight',
1241 description: '<p>the weight of the stroke (in pixels)</p>\n',
1242 type: 'Number'
1243 }
1244 ],
1245 class: 'p5',
1246 module: 'Shape'
1247 },
1248 bezier: {
1249 name: 'bezier',
1250 class: 'p5',
1251 module: 'Shape',
1252 overloads: [
1253 {
1254 params: [
1255 {
1256 name: 'x1',
1257 description: '<p>x-coordinate for the first anchor point</p>\n',
1258 type: 'Number'
1259 },
1260 {
1261 name: 'y1',
1262 description: '<p>y-coordinate for the first anchor point</p>\n',
1263 type: 'Number'
1264 },
1265 {
1266 name: 'x2',
1267 description: '<p>x-coordinate for the first control point</p>\n',
1268 type: 'Number'
1269 },
1270 {
1271 name: 'y2',
1272 description: '<p>y-coordinate for the first control point</p>\n',
1273 type: 'Number'
1274 },
1275 {
1276 name: 'x3',
1277 description: '<p>x-coordinate for the second control point</p>\n',
1278 type: 'Number'
1279 },
1280 {
1281 name: 'y3',
1282 description: '<p>y-coordinate for the second control point</p>\n',
1283 type: 'Number'
1284 },
1285 {
1286 name: 'x4',
1287 description: '<p>x-coordinate for the second anchor point</p>\n',
1288 type: 'Number'
1289 },
1290 {
1291 name: 'y4',
1292 description: '<p>y-coordinate for the second anchor point</p>\n',
1293 type: 'Number'
1294 }
1295 ],
1296 chainable: 1
1297 },
1298 {
1299 params: [
1300 {
1301 name: 'x1',
1302 description: '',
1303 type: 'Number'
1304 },
1305 {
1306 name: 'y1',
1307 description: '',
1308 type: 'Number'
1309 },
1310 {
1311 name: 'z1',
1312 description: '<p>z-coordinate for the first anchor point</p>\n',
1313 type: 'Number'
1314 },
1315 {
1316 name: 'x2',
1317 description: '',
1318 type: 'Number'
1319 },
1320 {
1321 name: 'y2',
1322 description: '',
1323 type: 'Number'
1324 },
1325 {
1326 name: 'z2',
1327 description: '<p>z-coordinate for the first control point</p>\n',
1328 type: 'Number'
1329 },
1330 {
1331 name: 'x3',
1332 description: '',
1333 type: 'Number'
1334 },
1335 {
1336 name: 'y3',
1337 description: '',
1338 type: 'Number'
1339 },
1340 {
1341 name: 'z3',
1342 description: '<p>z-coordinate for the second control point</p>\n',
1343 type: 'Number'
1344 },
1345 {
1346 name: 'x4',
1347 description: '',
1348 type: 'Number'
1349 },
1350 {
1351 name: 'y4',
1352 description: '',
1353 type: 'Number'
1354 },
1355 {
1356 name: 'z4',
1357 description: '<p>z-coordinate for the second anchor point</p>\n',
1358 type: 'Number'
1359 }
1360 ],
1361 chainable: 1
1362 }
1363 ]
1364 },
1365 bezierDetail: {
1366 name: 'bezierDetail',
1367 params: [
1368 {
1369 name: 'detail',
1370 description: '<p>resolution of the curves</p>\n',
1371 type: 'Number'
1372 }
1373 ],
1374 class: 'p5',
1375 module: 'Shape'
1376 },
1377 bezierPoint: {
1378 name: 'bezierPoint',
1379 params: [
1380 {
1381 name: 'a',
1382 description: '<p>coordinate of first point on the curve</p>\n',
1383 type: 'Number'
1384 },
1385 {
1386 name: 'b',
1387 description: '<p>coordinate of first control point</p>\n',
1388 type: 'Number'
1389 },
1390 {
1391 name: 'c',
1392 description: '<p>coordinate of second control point</p>\n',
1393 type: 'Number'
1394 },
1395 {
1396 name: 'd',
1397 description: '<p>coordinate of second point on the curve</p>\n',
1398 type: 'Number'
1399 },
1400 {
1401 name: 't',
1402 description: '<p>value between 0 and 1</p>\n',
1403 type: 'Number'
1404 }
1405 ],
1406 class: 'p5',
1407 module: 'Shape'
1408 },
1409 bezierTangent: {
1410 name: 'bezierTangent',
1411 params: [
1412 {
1413 name: 'a',
1414 description: '<p>coordinate of first point on the curve</p>\n',
1415 type: 'Number'
1416 },
1417 {
1418 name: 'b',
1419 description: '<p>coordinate of first control point</p>\n',
1420 type: 'Number'
1421 },
1422 {
1423 name: 'c',
1424 description: '<p>coordinate of second control point</p>\n',
1425 type: 'Number'
1426 },
1427 {
1428 name: 'd',
1429 description: '<p>coordinate of second point on the curve</p>\n',
1430 type: 'Number'
1431 },
1432 {
1433 name: 't',
1434 description: '<p>value between 0 and 1</p>\n',
1435 type: 'Number'
1436 }
1437 ],
1438 class: 'p5',
1439 module: 'Shape'
1440 },
1441 curve: {
1442 name: 'curve',
1443 class: 'p5',
1444 module: 'Shape',
1445 overloads: [
1446 {
1447 params: [
1448 {
1449 name: 'x1',
1450 description:
1451 '<p>x-coordinate for the beginning control point</p>\n',
1452 type: 'Number'
1453 },
1454 {
1455 name: 'y1',
1456 description:
1457 '<p>y-coordinate for the beginning control point</p>\n',
1458 type: 'Number'
1459 },
1460 {
1461 name: 'x2',
1462 description: '<p>x-coordinate for the first point</p>\n',
1463 type: 'Number'
1464 },
1465 {
1466 name: 'y2',
1467 description: '<p>y-coordinate for the first point</p>\n',
1468 type: 'Number'
1469 },
1470 {
1471 name: 'x3',
1472 description: '<p>x-coordinate for the second point</p>\n',
1473 type: 'Number'
1474 },
1475 {
1476 name: 'y3',
1477 description: '<p>y-coordinate for the second point</p>\n',
1478 type: 'Number'
1479 },
1480 {
1481 name: 'x4',
1482 description: '<p>x-coordinate for the ending control point</p>\n',
1483 type: 'Number'
1484 },
1485 {
1486 name: 'y4',
1487 description: '<p>y-coordinate for the ending control point</p>\n',
1488 type: 'Number'
1489 }
1490 ],
1491 chainable: 1
1492 },
1493 {
1494 params: [
1495 {
1496 name: 'x1',
1497 description: '',
1498 type: 'Number'
1499 },
1500 {
1501 name: 'y1',
1502 description: '',
1503 type: 'Number'
1504 },
1505 {
1506 name: 'z1',
1507 description:
1508 '<p>z-coordinate for the beginning control point</p>\n',
1509 type: 'Number'
1510 },
1511 {
1512 name: 'x2',
1513 description: '',
1514 type: 'Number'
1515 },
1516 {
1517 name: 'y2',
1518 description: '',
1519 type: 'Number'
1520 },
1521 {
1522 name: 'z2',
1523 description: '<p>z-coordinate for the first point</p>\n',
1524 type: 'Number'
1525 },
1526 {
1527 name: 'x3',
1528 description: '',
1529 type: 'Number'
1530 },
1531 {
1532 name: 'y3',
1533 description: '',
1534 type: 'Number'
1535 },
1536 {
1537 name: 'z3',
1538 description: '<p>z-coordinate for the second point</p>\n',
1539 type: 'Number'
1540 },
1541 {
1542 name: 'x4',
1543 description: '',
1544 type: 'Number'
1545 },
1546 {
1547 name: 'y4',
1548 description: '',
1549 type: 'Number'
1550 },
1551 {
1552 name: 'z4',
1553 description: '<p>z-coordinate for the ending control point</p>\n',
1554 type: 'Number'
1555 }
1556 ],
1557 chainable: 1
1558 }
1559 ]
1560 },
1561 curveDetail: {
1562 name: 'curveDetail',
1563 params: [
1564 {
1565 name: 'resolution',
1566 description: '<p>resolution of the curves</p>\n',
1567 type: 'Number'
1568 }
1569 ],
1570 class: 'p5',
1571 module: 'Shape'
1572 },
1573 curveTightness: {
1574 name: 'curveTightness',
1575 params: [
1576 {
1577 name: 'amount',
1578 description:
1579 '<p>amount of deformation from the original vertices</p>\n',
1580 type: 'Number'
1581 }
1582 ],
1583 class: 'p5',
1584 module: 'Shape'
1585 },
1586 curvePoint: {
1587 name: 'curvePoint',
1588 params: [
1589 {
1590 name: 'a',
1591 description: '<p>coordinate of first control point of the curve</p>\n',
1592 type: 'Number'
1593 },
1594 {
1595 name: 'b',
1596 description: '<p>coordinate of first point</p>\n',
1597 type: 'Number'
1598 },
1599 {
1600 name: 'c',
1601 description: '<p>coordinate of second point</p>\n',
1602 type: 'Number'
1603 },
1604 {
1605 name: 'd',
1606 description: '<p>coordinate of second control point</p>\n',
1607 type: 'Number'
1608 },
1609 {
1610 name: 't',
1611 description: '<p>value between 0 and 1</p>\n',
1612 type: 'Number'
1613 }
1614 ],
1615 class: 'p5',
1616 module: 'Shape'
1617 },
1618 curveTangent: {
1619 name: 'curveTangent',
1620 params: [
1621 {
1622 name: 'a',
1623 description: '<p>coordinate of first control point</p>\n',
1624 type: 'Number'
1625 },
1626 {
1627 name: 'b',
1628 description: '<p>coordinate of first point on the curve</p>\n',
1629 type: 'Number'
1630 },
1631 {
1632 name: 'c',
1633 description: '<p>coordinate of second point on the curve</p>\n',
1634 type: 'Number'
1635 },
1636 {
1637 name: 'd',
1638 description: '<p>coordinate of second conrol point</p>\n',
1639 type: 'Number'
1640 },
1641 {
1642 name: 't',
1643 description: '<p>value between 0 and 1</p>\n',
1644 type: 'Number'
1645 }
1646 ],
1647 class: 'p5',
1648 module: 'Shape'
1649 },
1650 beginContour: {
1651 name: 'beginContour',
1652 class: 'p5',
1653 module: 'Shape'
1654 },
1655 beginShape: {
1656 name: 'beginShape',
1657 params: [
1658 {
1659 name: 'kind',
1660 description:
1661 '<p>either POINTS, LINES, TRIANGLES, TRIANGLE_FAN\n TRIANGLE_STRIP, QUADS, QUAD_STRIP or TESS</p>\n',
1662 type: 'Constant',
1663 optional: true
1664 }
1665 ],
1666 class: 'p5',
1667 module: 'Shape'
1668 },
1669 bezierVertex: {
1670 name: 'bezierVertex',
1671 class: 'p5',
1672 module: 'Shape',
1673 overloads: [
1674 {
1675 params: [
1676 {
1677 name: 'x2',
1678 description: '<p>x-coordinate for the first control point</p>\n',
1679 type: 'Number'
1680 },
1681 {
1682 name: 'y2',
1683 description: '<p>y-coordinate for the first control point</p>\n',
1684 type: 'Number'
1685 },
1686 {
1687 name: 'x3',
1688 description: '<p>x-coordinate for the second control point</p>\n',
1689 type: 'Number'
1690 },
1691 {
1692 name: 'y3',
1693 description: '<p>y-coordinate for the second control point</p>\n',
1694 type: 'Number'
1695 },
1696 {
1697 name: 'x4',
1698 description: '<p>x-coordinate for the anchor point</p>\n',
1699 type: 'Number'
1700 },
1701 {
1702 name: 'y4',
1703 description: '<p>y-coordinate for the anchor point</p>\n',
1704 type: 'Number'
1705 }
1706 ],
1707 chainable: 1
1708 },
1709 {
1710 params: [
1711 {
1712 name: 'x2',
1713 description: '',
1714 type: 'Number'
1715 },
1716 {
1717 name: 'y2',
1718 description: '',
1719 type: 'Number'
1720 },
1721 {
1722 name: 'z2',
1723 description:
1724 '<p>z-coordinate for the first control point (for WebGL mode)</p>\n',
1725 type: 'Number'
1726 },
1727 {
1728 name: 'x3',
1729 description: '',
1730 type: 'Number'
1731 },
1732 {
1733 name: 'y3',
1734 description: '',
1735 type: 'Number'
1736 },
1737 {
1738 name: 'z3',
1739 description:
1740 '<p>z-coordinate for the second control point (for WebGL mode)</p>\n',
1741 type: 'Number'
1742 },
1743 {
1744 name: 'x4',
1745 description: '',
1746 type: 'Number'
1747 },
1748 {
1749 name: 'y4',
1750 description: '',
1751 type: 'Number'
1752 },
1753 {
1754 name: 'z4',
1755 description:
1756 '<p>z-coordinate for the anchor point (for WebGL mode)</p>\n',
1757 type: 'Number'
1758 }
1759 ],
1760 chainable: 1
1761 }
1762 ]
1763 },
1764 curveVertex: {
1765 name: 'curveVertex',
1766 class: 'p5',
1767 module: 'Shape',
1768 overloads: [
1769 {
1770 params: [
1771 {
1772 name: 'x',
1773 description: '<p>x-coordinate of the vertex</p>\n',
1774 type: 'Number'
1775 },
1776 {
1777 name: 'y',
1778 description: '<p>y-coordinate of the vertex</p>\n',
1779 type: 'Number'
1780 }
1781 ],
1782 chainable: 1
1783 },
1784 {
1785 params: [
1786 {
1787 name: 'x',
1788 description: '',
1789 type: 'Number'
1790 },
1791 {
1792 name: 'y',
1793 description: '',
1794 type: 'Number'
1795 },
1796 {
1797 name: 'z',
1798 description: '<p>z-coordinate of the vertex (for WebGL mode)</p>\n',
1799 type: 'Number',
1800 optional: true
1801 }
1802 ],
1803 chainable: 1
1804 }
1805 ]
1806 },
1807 endContour: {
1808 name: 'endContour',
1809 class: 'p5',
1810 module: 'Shape'
1811 },
1812 endShape: {
1813 name: 'endShape',
1814 params: [
1815 {
1816 name: 'mode',
1817 description: '<p>use CLOSE to close the shape</p>\n',
1818 type: 'Constant',
1819 optional: true
1820 }
1821 ],
1822 class: 'p5',
1823 module: 'Shape'
1824 },
1825 quadraticVertex: {
1826 name: 'quadraticVertex',
1827 class: 'p5',
1828 module: 'Shape',
1829 overloads: [
1830 {
1831 params: [
1832 {
1833 name: 'cx',
1834 description: '<p>x-coordinate for the control point</p>\n',
1835 type: 'Number'
1836 },
1837 {
1838 name: 'cy',
1839 description: '<p>y-coordinate for the control point</p>\n',
1840 type: 'Number'
1841 },
1842 {
1843 name: 'x3',
1844 description: '<p>x-coordinate for the anchor point</p>\n',
1845 type: 'Number'
1846 },
1847 {
1848 name: 'y3',
1849 description: '<p>y-coordinate for the anchor point</p>\n',
1850 type: 'Number'
1851 }
1852 ],
1853 chainable: 1
1854 },
1855 {
1856 params: [
1857 {
1858 name: 'cx',
1859 description: '',
1860 type: 'Number'
1861 },
1862 {
1863 name: 'cy',
1864 description: '',
1865 type: 'Number'
1866 },
1867 {
1868 name: 'cz',
1869 description:
1870 '<p>z-coordinate for the control point (for WebGL mode)</p>\n',
1871 type: 'Number'
1872 },
1873 {
1874 name: 'x3',
1875 description: '',
1876 type: 'Number'
1877 },
1878 {
1879 name: 'y3',
1880 description: '',
1881 type: 'Number'
1882 },
1883 {
1884 name: 'z3',
1885 description:
1886 '<p>z-coordinate for the anchor point (for WebGL mode)</p>\n',
1887 type: 'Number'
1888 }
1889 ],
1890 chainable: 1
1891 }
1892 ]
1893 },
1894 vertex: {
1895 name: 'vertex',
1896 class: 'p5',
1897 module: 'Shape',
1898 overloads: [
1899 {
1900 params: [
1901 {
1902 name: 'x',
1903 description: '<p>x-coordinate of the vertex</p>\n',
1904 type: 'Number'
1905 },
1906 {
1907 name: 'y',
1908 description: '<p>y-coordinate of the vertex</p>\n',
1909 type: 'Number'
1910 }
1911 ],
1912 chainable: 1
1913 },
1914 {
1915 params: [
1916 {
1917 name: 'x',
1918 description: '',
1919 type: 'Number'
1920 },
1921 {
1922 name: 'y',
1923 description: '',
1924 type: 'Number'
1925 },
1926 {
1927 name: 'z',
1928 description: '<p>z-coordinate of the vertex</p>\n',
1929 type: 'Number'
1930 },
1931 {
1932 name: 'u',
1933 description: "<p>the vertex's texture u-coordinate</p>\n",
1934 type: 'Number',
1935 optional: true
1936 },
1937 {
1938 name: 'v',
1939 description: "<p>the vertex's texture v-coordinate</p>\n",
1940 type: 'Number',
1941 optional: true
1942 }
1943 ],
1944 chainable: 1
1945 }
1946 ]
1947 },
1948 P2D: {
1949 name: 'P2D',
1950 class: 'p5',
1951 module: 'Constants'
1952 },
1953 WEBGL: {
1954 name: 'WEBGL',
1955 class: 'p5',
1956 module: 'Constants'
1957 },
1958 ARROW: {
1959 name: 'ARROW',
1960 class: 'p5',
1961 module: 'Constants'
1962 },
1963 CROSS: {
1964 name: 'CROSS',
1965 class: 'p5',
1966 module: 'Constants'
1967 },
1968 HAND: {
1969 name: 'HAND',
1970 class: 'p5',
1971 module: 'Constants'
1972 },
1973 MOVE: {
1974 name: 'MOVE',
1975 class: 'p5',
1976 module: 'Constants'
1977 },
1978 TEXT: {
1979 name: 'TEXT',
1980 class: 'p5',
1981 module: 'Constants'
1982 },
1983 WAIT: {
1984 name: 'WAIT',
1985 class: 'p5',
1986 module: 'Constants'
1987 },
1988 HALF_PI: {
1989 name: 'HALF_PI',
1990 class: 'p5',
1991 module: 'Constants'
1992 },
1993 PI: {
1994 name: 'PI',
1995 class: 'p5',
1996 module: 'Constants'
1997 },
1998 QUARTER_PI: {
1999 name: 'QUARTER_PI',
2000 class: 'p5',
2001 module: 'Constants'
2002 },
2003 TAU: {
2004 name: 'TAU',
2005 class: 'p5',
2006 module: 'Constants'
2007 },
2008 TWO_PI: {
2009 name: 'TWO_PI',
2010 class: 'p5',
2011 module: 'Constants'
2012 },
2013 DEGREES: {
2014 name: 'DEGREES',
2015 class: 'p5',
2016 module: 'Constants'
2017 },
2018 RADIANS: {
2019 name: 'RADIANS',
2020 class: 'p5',
2021 module: 'Constants'
2022 },
2023 CORNER: {
2024 name: 'CORNER',
2025 class: 'p5',
2026 module: 'Constants'
2027 },
2028 CORNERS: {
2029 name: 'CORNERS',
2030 class: 'p5',
2031 module: 'Constants'
2032 },
2033 RADIUS: {
2034 name: 'RADIUS',
2035 class: 'p5',
2036 module: 'Constants'
2037 },
2038 RIGHT: {
2039 name: 'RIGHT',
2040 class: 'p5',
2041 module: 'Constants'
2042 },
2043 LEFT: {
2044 name: 'LEFT',
2045 class: 'p5',
2046 module: 'Constants'
2047 },
2048 CENTER: {
2049 name: 'CENTER',
2050 class: 'p5',
2051 module: 'Constants'
2052 },
2053 TOP: {
2054 name: 'TOP',
2055 class: 'p5',
2056 module: 'Constants'
2057 },
2058 BOTTOM: {
2059 name: 'BOTTOM',
2060 class: 'p5',
2061 module: 'Constants'
2062 },
2063 BASELINE: {
2064 name: 'BASELINE',
2065 class: 'p5',
2066 module: 'Constants'
2067 },
2068 POINTS: {
2069 name: 'POINTS',
2070 class: 'p5',
2071 module: 'Constants'
2072 },
2073 LINES: {
2074 name: 'LINES',
2075 class: 'p5',
2076 module: 'Constants'
2077 },
2078 LINE_STRIP: {
2079 name: 'LINE_STRIP',
2080 class: 'p5',
2081 module: 'Constants'
2082 },
2083 LINE_LOOP: {
2084 name: 'LINE_LOOP',
2085 class: 'p5',
2086 module: 'Constants'
2087 },
2088 TRIANGLES: {
2089 name: 'TRIANGLES',
2090 class: 'p5',
2091 module: 'Constants'
2092 },
2093 TRIANGLE_FAN: {
2094 name: 'TRIANGLE_FAN',
2095 class: 'p5',
2096 module: 'Constants'
2097 },
2098 TRIANGLE_STRIP: {
2099 name: 'TRIANGLE_STRIP',
2100 class: 'p5',
2101 module: 'Constants'
2102 },
2103 QUADS: {
2104 name: 'QUADS',
2105 class: 'p5',
2106 module: 'Constants'
2107 },
2108 QUAD_STRIP: {
2109 name: 'QUAD_STRIP',
2110 class: 'p5',
2111 module: 'Constants'
2112 },
2113 TESS: {
2114 name: 'TESS',
2115 class: 'p5',
2116 module: 'Constants'
2117 },
2118 CLOSE: {
2119 name: 'CLOSE',
2120 class: 'p5',
2121 module: 'Constants'
2122 },
2123 OPEN: {
2124 name: 'OPEN',
2125 class: 'p5',
2126 module: 'Constants'
2127 },
2128 CHORD: {
2129 name: 'CHORD',
2130 class: 'p5',
2131 module: 'Constants'
2132 },
2133 PIE: {
2134 name: 'PIE',
2135 class: 'p5',
2136 module: 'Constants'
2137 },
2138 PROJECT: {
2139 name: 'PROJECT',
2140 class: 'p5',
2141 module: 'Constants'
2142 },
2143 SQUARE: {
2144 name: 'SQUARE',
2145 class: 'p5',
2146 module: 'Constants'
2147 },
2148 ROUND: {
2149 name: 'ROUND',
2150 class: 'p5',
2151 module: 'Constants'
2152 },
2153 BEVEL: {
2154 name: 'BEVEL',
2155 class: 'p5',
2156 module: 'Constants'
2157 },
2158 MITER: {
2159 name: 'MITER',
2160 class: 'p5',
2161 module: 'Constants'
2162 },
2163 RGB: {
2164 name: 'RGB',
2165 class: 'p5',
2166 module: 'Constants'
2167 },
2168 HSB: {
2169 name: 'HSB',
2170 class: 'p5',
2171 module: 'Constants'
2172 },
2173 HSL: {
2174 name: 'HSL',
2175 class: 'p5',
2176 module: 'Constants'
2177 },
2178 AUTO: {
2179 name: 'AUTO',
2180 class: 'p5',
2181 module: 'Constants'
2182 },
2183 ALT: {
2184 name: 'ALT',
2185 class: 'p5',
2186 module: 'Constants'
2187 },
2188 BACKSPACE: {
2189 name: 'BACKSPACE',
2190 class: 'p5',
2191 module: 'Constants'
2192 },
2193 CONTROL: {
2194 name: 'CONTROL',
2195 class: 'p5',
2196 module: 'Constants'
2197 },
2198 DELETE: {
2199 name: 'DELETE',
2200 class: 'p5',
2201 module: 'Constants'
2202 },
2203 DOWN_ARROW: {
2204 name: 'DOWN_ARROW',
2205 class: 'p5',
2206 module: 'Constants'
2207 },
2208 ENTER: {
2209 name: 'ENTER',
2210 class: 'p5',
2211 module: 'Constants'
2212 },
2213 ESCAPE: {
2214 name: 'ESCAPE',
2215 class: 'p5',
2216 module: 'Constants'
2217 },
2218 LEFT_ARROW: {
2219 name: 'LEFT_ARROW',
2220 class: 'p5',
2221 module: 'Constants'
2222 },
2223 OPTION: {
2224 name: 'OPTION',
2225 class: 'p5',
2226 module: 'Constants'
2227 },
2228 RETURN: {
2229 name: 'RETURN',
2230 class: 'p5',
2231 module: 'Constants'
2232 },
2233 RIGHT_ARROW: {
2234 name: 'RIGHT_ARROW',
2235 class: 'p5',
2236 module: 'Constants'
2237 },
2238 SHIFT: {
2239 name: 'SHIFT',
2240 class: 'p5',
2241 module: 'Constants'
2242 },
2243 TAB: {
2244 name: 'TAB',
2245 class: 'p5',
2246 module: 'Constants'
2247 },
2248 UP_ARROW: {
2249 name: 'UP_ARROW',
2250 class: 'p5',
2251 module: 'Constants'
2252 },
2253 BLEND: {
2254 name: 'BLEND',
2255 class: 'p5',
2256 module: 'Constants'
2257 },
2258 REMOVE: {
2259 name: 'REMOVE',
2260 class: 'p5',
2261 module: 'Constants'
2262 },
2263 ADD: {
2264 name: 'ADD',
2265 class: 'p5',
2266 module: 'Constants'
2267 },
2268 DARKEST: {
2269 name: 'DARKEST',
2270 class: 'p5',
2271 module: 'Constants'
2272 },
2273 LIGHTEST: {
2274 name: 'LIGHTEST',
2275 class: 'p5',
2276 module: 'Constants'
2277 },
2278 DIFFERENCE: {
2279 name: 'DIFFERENCE',
2280 class: 'p5',
2281 module: 'Constants'
2282 },
2283 SUBTRACT: {
2284 name: 'SUBTRACT',
2285 class: 'p5',
2286 module: 'Constants'
2287 },
2288 EXCLUSION: {
2289 name: 'EXCLUSION',
2290 class: 'p5',
2291 module: 'Constants'
2292 },
2293 MULTIPLY: {
2294 name: 'MULTIPLY',
2295 class: 'p5',
2296 module: 'Constants'
2297 },
2298 SCREEN: {
2299 name: 'SCREEN',
2300 class: 'p5',
2301 module: 'Constants'
2302 },
2303 REPLACE: {
2304 name: 'REPLACE',
2305 class: 'p5',
2306 module: 'Constants'
2307 },
2308 OVERLAY: {
2309 name: 'OVERLAY',
2310 class: 'p5',
2311 module: 'Constants'
2312 },
2313 HARD_LIGHT: {
2314 name: 'HARD_LIGHT',
2315 class: 'p5',
2316 module: 'Constants'
2317 },
2318 SOFT_LIGHT: {
2319 name: 'SOFT_LIGHT',
2320 class: 'p5',
2321 module: 'Constants'
2322 },
2323 DODGE: {
2324 name: 'DODGE',
2325 class: 'p5',
2326 module: 'Constants'
2327 },
2328 BURN: {
2329 name: 'BURN',
2330 class: 'p5',
2331 module: 'Constants'
2332 },
2333 THRESHOLD: {
2334 name: 'THRESHOLD',
2335 class: 'p5',
2336 module: 'Constants'
2337 },
2338 GRAY: {
2339 name: 'GRAY',
2340 class: 'p5',
2341 module: 'Constants'
2342 },
2343 OPAQUE: {
2344 name: 'OPAQUE',
2345 class: 'p5',
2346 module: 'Constants'
2347 },
2348 INVERT: {
2349 name: 'INVERT',
2350 class: 'p5',
2351 module: 'Constants'
2352 },
2353 POSTERIZE: {
2354 name: 'POSTERIZE',
2355 class: 'p5',
2356 module: 'Constants'
2357 },
2358 DILATE: {
2359 name: 'DILATE',
2360 class: 'p5',
2361 module: 'Constants'
2362 },
2363 ERODE: {
2364 name: 'ERODE',
2365 class: 'p5',
2366 module: 'Constants'
2367 },
2368 BLUR: {
2369 name: 'BLUR',
2370 class: 'p5',
2371 module: 'Constants'
2372 },
2373 NORMAL: {
2374 name: 'NORMAL',
2375 class: 'p5',
2376 module: 'Constants'
2377 },
2378 ITALIC: {
2379 name: 'ITALIC',
2380 class: 'p5',
2381 module: 'Constants'
2382 },
2383 BOLD: {
2384 name: 'BOLD',
2385 class: 'p5',
2386 module: 'Constants'
2387 },
2388 BOLDITALIC: {
2389 name: 'BOLDITALIC',
2390 class: 'p5',
2391 module: 'Constants'
2392 },
2393 LINEAR: {
2394 name: 'LINEAR',
2395 class: 'p5',
2396 module: 'Constants'
2397 },
2398 QUADRATIC: {
2399 name: 'QUADRATIC',
2400 class: 'p5',
2401 module: 'Constants'
2402 },
2403 BEZIER: {
2404 name: 'BEZIER',
2405 class: 'p5',
2406 module: 'Constants'
2407 },
2408 CURVE: {
2409 name: 'CURVE',
2410 class: 'p5',
2411 module: 'Constants'
2412 },
2413 STROKE: {
2414 name: 'STROKE',
2415 class: 'p5',
2416 module: 'Constants'
2417 },
2418 FILL: {
2419 name: 'FILL',
2420 class: 'p5',
2421 module: 'Constants'
2422 },
2423 TEXTURE: {
2424 name: 'TEXTURE',
2425 class: 'p5',
2426 module: 'Constants'
2427 },
2428 IMMEDIATE: {
2429 name: 'IMMEDIATE',
2430 class: 'p5',
2431 module: 'Constants'
2432 },
2433 IMAGE: {
2434 name: 'IMAGE',
2435 class: 'p5',
2436 module: 'Constants'
2437 },
2438 NEAREST: {
2439 name: 'NEAREST',
2440 class: 'p5',
2441 module: 'Constants'
2442 },
2443 REPEAT: {
2444 name: 'REPEAT',
2445 class: 'p5',
2446 module: 'Constants'
2447 },
2448 CLAMP: {
2449 name: 'CLAMP',
2450 class: 'p5',
2451 module: 'Constants'
2452 },
2453 MIRROR: {
2454 name: 'MIRROR',
2455 class: 'p5',
2456 module: 'Constants'
2457 },
2458 LANDSCAPE: {
2459 name: 'LANDSCAPE',
2460 class: 'p5',
2461 module: 'Constants'
2462 },
2463 PORTRAIT: {
2464 name: 'PORTRAIT',
2465 class: 'p5',
2466 module: 'Constants'
2467 },
2468 GRID: {
2469 name: 'GRID',
2470 class: 'p5',
2471 module: 'Constants'
2472 },
2473 AXES: {
2474 name: 'AXES',
2475 class: 'p5',
2476 module: 'Constants'
2477 },
2478 print: {
2479 name: 'print',
2480 params: [
2481 {
2482 name: 'contents',
2483 description:
2484 '<p>any combination of Number, String, Object, Boolean,\n Array to print</p>\n',
2485 type: 'Any'
2486 }
2487 ],
2488 class: 'p5',
2489 module: 'Environment'
2490 },
2491 frameCount: {
2492 name: 'frameCount',
2493 class: 'p5',
2494 module: 'Environment'
2495 },
2496 deltaTime: {
2497 name: 'deltaTime',
2498 class: 'p5',
2499 module: 'Environment'
2500 },
2501 focused: {
2502 name: 'focused',
2503 class: 'p5',
2504 module: 'Environment'
2505 },
2506 cursor: {
2507 name: 'cursor',
2508 params: [
2509 {
2510 name: 'type',
2511 description:
2512 "<p>Built-In: either ARROW, CROSS, HAND, MOVE, TEXT and WAIT\n Native CSS properties: 'grab', 'progress', 'cell' etc.\n External: path for cursor's images\n (Allowed File extensions: .cur, .gif, .jpg, .jpeg, .png)\n For more information on Native CSS cursors and url visit:\n <a href=\"https://developer.mozilla.org/en-US/docs/Web/CSS/cursor\">https://developer.mozilla.org/en-US/docs/Web/CSS/cursor</a></p>\n",
2513 type: 'String|Constant'
2514 },
2515 {
2516 name: 'x',
2517 description:
2518 '<p>the horizontal active spot of the cursor (must be less than 32)</p>\n',
2519 type: 'Number',
2520 optional: true
2521 },
2522 {
2523 name: 'y',
2524 description:
2525 '<p>the vertical active spot of the cursor (must be less than 32)</p>\n',
2526 type: 'Number',
2527 optional: true
2528 }
2529 ],
2530 class: 'p5',
2531 module: 'Environment'
2532 },
2533 frameRate: {
2534 name: 'frameRate',
2535 class: 'p5',
2536 module: 'Environment',
2537 overloads: [
2538 {
2539 params: [
2540 {
2541 name: 'fps',
2542 description:
2543 '<p>number of frames to be displayed every second</p>\n',
2544 type: 'Number'
2545 }
2546 ],
2547 chainable: 1
2548 },
2549 {
2550 params: []
2551 }
2552 ]
2553 },
2554 noCursor: {
2555 name: 'noCursor',
2556 class: 'p5',
2557 module: 'Environment'
2558 },
2559 displayWidth: {
2560 name: 'displayWidth',
2561 class: 'p5',
2562 module: 'Environment'
2563 },
2564 displayHeight: {
2565 name: 'displayHeight',
2566 class: 'p5',
2567 module: 'Environment'
2568 },
2569 windowWidth: {
2570 name: 'windowWidth',
2571 class: 'p5',
2572 module: 'Environment'
2573 },
2574 windowHeight: {
2575 name: 'windowHeight',
2576 class: 'p5',
2577 module: 'Environment'
2578 },
2579 windowResized: {
2580 name: 'windowResized',
2581 class: 'p5',
2582 module: 'Environment'
2583 },
2584 width: {
2585 name: 'width',
2586 class: 'p5',
2587 module: 'Environment'
2588 },
2589 height: {
2590 name: 'height',
2591 class: 'p5',
2592 module: 'Environment'
2593 },
2594 fullscreen: {
2595 name: 'fullscreen',
2596 params: [
2597 {
2598 name: 'val',
2599 description:
2600 '<p>whether the sketch should be in fullscreen mode\nor not</p>\n',
2601 type: 'Boolean',
2602 optional: true
2603 }
2604 ],
2605 class: 'p5',
2606 module: 'Environment'
2607 },
2608 pixelDensity: {
2609 name: 'pixelDensity',
2610 class: 'p5',
2611 module: 'Environment',
2612 overloads: [
2613 {
2614 params: [
2615 {
2616 name: 'val',
2617 description: '<p>whether or how much the sketch should scale</p>\n',
2618 type: 'Number'
2619 }
2620 ],
2621 chainable: 1
2622 },
2623 {
2624 params: []
2625 }
2626 ]
2627 },
2628 displayDensity: {
2629 name: 'displayDensity',
2630 class: 'p5',
2631 module: 'Environment'
2632 },
2633 getURL: {
2634 name: 'getURL',
2635 class: 'p5',
2636 module: 'Environment'
2637 },
2638 getURLPath: {
2639 name: 'getURLPath',
2640 class: 'p5',
2641 module: 'Environment'
2642 },
2643 getURLParams: {
2644 name: 'getURLParams',
2645 class: 'p5',
2646 module: 'Environment'
2647 },
2648 preload: {
2649 name: 'preload',
2650 class: 'p5',
2651 module: 'Structure'
2652 },
2653 setup: {
2654 name: 'setup',
2655 class: 'p5',
2656 module: 'Structure'
2657 },
2658 draw: {
2659 name: 'draw',
2660 class: 'p5',
2661 module: 'Structure'
2662 },
2663 remove: {
2664 name: 'remove',
2665 class: 'p5',
2666 module: 'Structure'
2667 },
2668 disableFriendlyErrors: {
2669 name: 'disableFriendlyErrors',
2670 class: 'p5',
2671 module: 'Structure'
2672 },
2673 let: {
2674 name: 'let',
2675 class: 'p5',
2676 module: 'Foundation'
2677 },
2678 const: {
2679 name: 'const',
2680 class: 'p5',
2681 module: 'Foundation'
2682 },
2683 '===': {
2684 name: '===',
2685 class: 'p5',
2686 module: 'Foundation'
2687 },
2688 '>': {
2689 name: '>',
2690 class: 'p5',
2691 module: 'Foundation'
2692 },
2693 '>=': {
2694 name: '>=',
2695 class: 'p5',
2696 module: 'Foundation'
2697 },
2698 '<': {
2699 name: '<',
2700 class: 'p5',
2701 module: 'Foundation'
2702 },
2703 '<=': {
2704 name: '<=',
2705 class: 'p5',
2706 module: 'Foundation'
2707 },
2708 'if-else': {
2709 name: 'if-else',
2710 class: 'p5',
2711 module: 'Foundation'
2712 },
2713 function: {
2714 name: 'function',
2715 class: 'p5',
2716 module: 'Foundation'
2717 },
2718 return: {
2719 name: 'return',
2720 class: 'p5',
2721 module: 'Foundation'
2722 },
2723 boolean: {
2724 name: 'boolean',
2725 params: [
2726 {
2727 name: 'n',
2728 description: '<p>value to parse</p>\n',
2729 type: 'String|Boolean|Number|Array'
2730 }
2731 ],
2732 class: 'p5',
2733 module: 'Data'
2734 },
2735 string: {
2736 name: 'string',
2737 class: 'p5',
2738 module: 'Foundation'
2739 },
2740 number: {
2741 name: 'number',
2742 class: 'p5',
2743 module: 'Foundation'
2744 },
2745 object: {
2746 name: 'object',
2747 class: 'p5',
2748 module: 'Foundation'
2749 },
2750 class: {
2751 name: 'class',
2752 class: 'p5',
2753 module: 'Foundation'
2754 },
2755 for: {
2756 name: 'for',
2757 class: 'p5',
2758 module: 'Foundation'
2759 },
2760 while: {
2761 name: 'while',
2762 class: 'p5',
2763 module: 'Foundation'
2764 },
2765 createCanvas: {
2766 name: 'createCanvas',
2767 params: [
2768 {
2769 name: 'w',
2770 description: '<p>width of the canvas</p>\n',
2771 type: 'Number'
2772 },
2773 {
2774 name: 'h',
2775 description: '<p>height of the canvas</p>\n',
2776 type: 'Number'
2777 },
2778 {
2779 name: 'renderer',
2780 description: '<p>either P2D or WEBGL</p>\n',
2781 type: 'Constant',
2782 optional: true
2783 }
2784 ],
2785 class: 'p5',
2786 module: 'Rendering'
2787 },
2788 resizeCanvas: {
2789 name: 'resizeCanvas',
2790 params: [
2791 {
2792 name: 'w',
2793 description: '<p>width of the canvas</p>\n',
2794 type: 'Number'
2795 },
2796 {
2797 name: 'h',
2798 description: '<p>height of the canvas</p>\n',
2799 type: 'Number'
2800 },
2801 {
2802 name: 'noRedraw',
2803 description: "<p>don't redraw the canvas immediately</p>\n",
2804 type: 'Boolean',
2805 optional: true
2806 }
2807 ],
2808 class: 'p5',
2809 module: 'Rendering'
2810 },
2811 noCanvas: {
2812 name: 'noCanvas',
2813 class: 'p5',
2814 module: 'Rendering'
2815 },
2816 createGraphics: {
2817 name: 'createGraphics',
2818 params: [
2819 {
2820 name: 'w',
2821 description: '<p>width of the offscreen graphics buffer</p>\n',
2822 type: 'Number'
2823 },
2824 {
2825 name: 'h',
2826 description: '<p>height of the offscreen graphics buffer</p>\n',
2827 type: 'Number'
2828 },
2829 {
2830 name: 'renderer',
2831 description:
2832 '<p>either P2D or WEBGL\n undefined defaults to p2d</p>\n',
2833 type: 'Constant',
2834 optional: true
2835 }
2836 ],
2837 class: 'p5',
2838 module: 'Rendering'
2839 },
2840 blendMode: {
2841 name: 'blendMode',
2842 params: [
2843 {
2844 name: 'mode',
2845 description:
2846 '<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, REMOVE or SUBTRACT</p>\n',
2847 type: 'Constant'
2848 }
2849 ],
2850 class: 'p5',
2851 module: 'Rendering'
2852 },
2853 drawingContext: {
2854 name: 'drawingContext',
2855 class: 'p5',
2856 module: 'Rendering'
2857 },
2858 noLoop: {
2859 name: 'noLoop',
2860 class: 'p5',
2861 module: 'Structure'
2862 },
2863 loop: {
2864 name: 'loop',
2865 class: 'p5',
2866 module: 'Structure'
2867 },
2868 isLooping: {
2869 name: 'isLooping',
2870 class: 'p5',
2871 module: 'Structure'
2872 },
2873 push: {
2874 name: 'push',
2875 class: 'p5',
2876 module: 'Structure'
2877 },
2878 pop: {
2879 name: 'pop',
2880 class: 'p5',
2881 module: 'Structure'
2882 },
2883 redraw: {
2884 name: 'redraw',
2885 params: [
2886 {
2887 name: 'n',
2888 description: '<p>Redraw for n-times. The default value is 1.</p>\n',
2889 type: 'Integer',
2890 optional: true
2891 }
2892 ],
2893 class: 'p5',
2894 module: 'Structure'
2895 },
2896 p5: {
2897 name: 'p5',
2898 params: [
2899 {
2900 name: 'sketch',
2901 description: '<p>a function containing a p5.js sketch</p>\n',
2902 type: 'Object'
2903 },
2904 {
2905 name: 'node',
2906 description:
2907 '<p>ID or pointer to HTML DOM node to contain sketch in</p>\n',
2908 type: 'String|Object'
2909 }
2910 ],
2911 class: 'p5',
2912 module: 'Structure'
2913 },
2914 applyMatrix: {
2915 name: 'applyMatrix',
2916 params: [
2917 {
2918 name: 'a',
2919 description:
2920 '<p>numbers which define the 2x3 matrix to be multiplied</p>\n',
2921 type: 'Number'
2922 },
2923 {
2924 name: 'b',
2925 description:
2926 '<p>numbers which define the 2x3 matrix to be multiplied</p>\n',
2927 type: 'Number'
2928 },
2929 {
2930 name: 'c',
2931 description:
2932 '<p>numbers which define the 2x3 matrix to be multiplied</p>\n',
2933 type: 'Number'
2934 },
2935 {
2936 name: 'd',
2937 description:
2938 '<p>numbers which define the 2x3 matrix to be multiplied</p>\n',
2939 type: 'Number'
2940 },
2941 {
2942 name: 'e',
2943 description:
2944 '<p>numbers which define the 2x3 matrix to be multiplied</p>\n',
2945 type: 'Number'
2946 },
2947 {
2948 name: 'f',
2949 description:
2950 '<p>numbers which define the 2x3 matrix to be multiplied</p>\n',
2951 type: 'Number'
2952 }
2953 ],
2954 class: 'p5',
2955 module: 'Transform'
2956 },
2957 resetMatrix: {
2958 name: 'resetMatrix',
2959 class: 'p5',
2960 module: 'Transform'
2961 },
2962 rotate: {
2963 name: 'rotate',
2964 params: [
2965 {
2966 name: 'angle',
2967 description:
2968 '<p>the angle of rotation, specified in radians\n or degrees, depending on current angleMode</p>\n',
2969 type: 'Number'
2970 },
2971 {
2972 name: 'axis',
2973 description: '<p>(in 3d) the axis to rotate around</p>\n',
2974 type: 'p5.Vector|Number[]',
2975 optional: true
2976 }
2977 ],
2978 class: 'p5',
2979 module: 'Transform'
2980 },
2981 rotateX: {
2982 name: 'rotateX',
2983 params: [
2984 {
2985 name: 'angle',
2986 description:
2987 '<p>the angle of rotation, specified in radians\n or degrees, depending on current angleMode</p>\n',
2988 type: 'Number'
2989 }
2990 ],
2991 class: 'p5',
2992 module: 'Transform'
2993 },
2994 rotateY: {
2995 name: 'rotateY',
2996 params: [
2997 {
2998 name: 'angle',
2999 description:
3000 '<p>the angle of rotation, specified in radians\n or degrees, depending on current angleMode</p>\n',
3001 type: 'Number'
3002 }
3003 ],
3004 class: 'p5',
3005 module: 'Transform'
3006 },
3007 rotateZ: {
3008 name: 'rotateZ',
3009 params: [
3010 {
3011 name: 'angle',
3012 description:
3013 '<p>the angle of rotation, specified in radians\n or degrees, depending on current angleMode</p>\n',
3014 type: 'Number'
3015 }
3016 ],
3017 class: 'p5',
3018 module: 'Transform'
3019 },
3020 scale: {
3021 name: 'scale',
3022 class: 'p5',
3023 module: 'Transform',
3024 overloads: [
3025 {
3026 params: [
3027 {
3028 name: 's',
3029 description:
3030 '<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',
3031 type: 'Number|p5.Vector|Number[]'
3032 },
3033 {
3034 name: 'y',
3035 description: '<p>percent to scale the object in the y-axis</p>\n',
3036 type: 'Number',
3037 optional: true
3038 },
3039 {
3040 name: 'z',
3041 description:
3042 '<p>percent to scale the object in the z-axis (webgl only)</p>\n',
3043 type: 'Number',
3044 optional: true
3045 }
3046 ],
3047 chainable: 1
3048 },
3049 {
3050 params: [
3051 {
3052 name: 'scales',
3053 description: '<p>per-axis percents to scale the object</p>\n',
3054 type: 'p5.Vector|Number[]'
3055 }
3056 ],
3057 chainable: 1
3058 }
3059 ]
3060 },
3061 shearX: {
3062 name: 'shearX',
3063 params: [
3064 {
3065 name: 'angle',
3066 description:
3067 '<p>angle of shear specified in radians or degrees,\n depending on current angleMode</p>\n',
3068 type: 'Number'
3069 }
3070 ],
3071 class: 'p5',
3072 module: 'Transform'
3073 },
3074 shearY: {
3075 name: 'shearY',
3076 params: [
3077 {
3078 name: 'angle',
3079 description:
3080 '<p>angle of shear specified in radians or degrees,\n depending on current angleMode</p>\n',
3081 type: 'Number'
3082 }
3083 ],
3084 class: 'p5',
3085 module: 'Transform'
3086 },
3087 translate: {
3088 name: 'translate',
3089 class: 'p5',
3090 module: 'Transform',
3091 overloads: [
3092 {
3093 params: [
3094 {
3095 name: 'x',
3096 description: '<p>left/right translation</p>\n',
3097 type: 'Number'
3098 },
3099 {
3100 name: 'y',
3101 description: '<p>up/down translation</p>\n',
3102 type: 'Number'
3103 },
3104 {
3105 name: 'z',
3106 description: '<p>forward/backward translation (webgl only)</p>\n',
3107 type: 'Number',
3108 optional: true
3109 }
3110 ],
3111 chainable: 1
3112 },
3113 {
3114 params: [
3115 {
3116 name: 'vector',
3117 description: '<p>the vector to translate by</p>\n',
3118 type: 'p5.Vector'
3119 }
3120 ],
3121 chainable: 1
3122 }
3123 ]
3124 },
3125 storeItem: {
3126 name: 'storeItem',
3127 params: [
3128 {
3129 name: 'key',
3130 description: '',
3131 type: 'String'
3132 },
3133 {
3134 name: 'value',
3135 description: '',
3136 type: 'String|Number|Object|Boolean|p5.Color|p5.Vector'
3137 }
3138 ],
3139 class: 'p5',
3140 module: 'Data'
3141 },
3142 getItem: {
3143 name: 'getItem',
3144 params: [
3145 {
3146 name: 'key',
3147 description:
3148 '<p>name that you wish to use to store in local storage</p>\n',
3149 type: 'String'
3150 }
3151 ],
3152 class: 'p5',
3153 module: 'Data'
3154 },
3155 clearStorage: {
3156 name: 'clearStorage',
3157 class: 'p5',
3158 module: 'Data'
3159 },
3160 removeItem: {
3161 name: 'removeItem',
3162 params: [
3163 {
3164 name: 'key',
3165 description: '',
3166 type: 'String'
3167 }
3168 ],
3169 class: 'p5',
3170 module: 'Data'
3171 },
3172 createStringDict: {
3173 name: 'createStringDict',
3174 class: 'p5',
3175 module: 'Data',
3176 overloads: [
3177 {
3178 params: [
3179 {
3180 name: 'key',
3181 description: '',
3182 type: 'String'
3183 },
3184 {
3185 name: 'value',
3186 description: '',
3187 type: 'String'
3188 }
3189 ]
3190 },
3191 {
3192 params: [
3193 {
3194 name: 'object',
3195 description: '<p>object</p>\n',
3196 type: 'Object'
3197 }
3198 ]
3199 }
3200 ]
3201 },
3202 createNumberDict: {
3203 name: 'createNumberDict',
3204 class: 'p5',
3205 module: 'Data',
3206 overloads: [
3207 {
3208 params: [
3209 {
3210 name: 'key',
3211 description: '',
3212 type: 'Number'
3213 },
3214 {
3215 name: 'value',
3216 description: '',
3217 type: 'Number'
3218 }
3219 ]
3220 },
3221 {
3222 params: [
3223 {
3224 name: 'object',
3225 description: '<p>object</p>\n',
3226 type: 'Object'
3227 }
3228 ]
3229 }
3230 ]
3231 },
3232 select: {
3233 name: 'select',
3234 params: [
3235 {
3236 name: 'selectors',
3237 description: '<p>CSS selector string of element to search for</p>\n',
3238 type: 'String'
3239 },
3240 {
3241 name: 'container',
3242 description:
3243 '<p>CSS selector string, <a href="#/p5.Element">p5.Element</a>, or\n HTML element to search within</p>\n',
3244 type: 'String|p5.Element|HTMLElement',
3245 optional: true
3246 }
3247 ],
3248 class: 'p5',
3249 module: 'DOM'
3250 },
3251 selectAll: {
3252 name: 'selectAll',
3253 params: [
3254 {
3255 name: 'selectors',
3256 description: '<p>CSS selector string of elements to search for</p>\n',
3257 type: 'String'
3258 },
3259 {
3260 name: 'container',
3261 description:
3262 '<p>CSS selector string, <a href="#/p5.Element">p5.Element</a>\n , or HTML element to search within</p>\n',
3263 type: 'String|p5.Element|HTMLElement',
3264 optional: true
3265 }
3266 ],
3267 class: 'p5',
3268 module: 'DOM'
3269 },
3270 removeElements: {
3271 name: 'removeElements',
3272 class: 'p5',
3273 module: 'DOM'
3274 },
3275 changed: {
3276 name: 'changed',
3277 params: [
3278 {
3279 name: 'fxn',
3280 description:
3281 '<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',
3282 type: 'Function|Boolean'
3283 }
3284 ],
3285 class: 'p5',
3286 module: 'DOM'
3287 },
3288 input: {
3289 name: 'input',
3290 params: [
3291 {
3292 name: 'fxn',
3293 description:
3294 '<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',
3295 type: 'Function|Boolean'
3296 }
3297 ],
3298 class: 'p5',
3299 module: 'DOM'
3300 },
3301 createDiv: {
3302 name: 'createDiv',
3303 params: [
3304 {
3305 name: 'html',
3306 description: '<p>inner HTML for element created</p>\n',
3307 type: 'String',
3308 optional: true
3309 }
3310 ],
3311 class: 'p5',
3312 module: 'DOM'
3313 },
3314 createP: {
3315 name: 'createP',
3316 params: [
3317 {
3318 name: 'html',
3319 description: '<p>inner HTML for element created</p>\n',
3320 type: 'String',
3321 optional: true
3322 }
3323 ],
3324 class: 'p5',
3325 module: 'DOM'
3326 },
3327 createSpan: {
3328 name: 'createSpan',
3329 params: [
3330 {
3331 name: 'html',
3332 description: '<p>inner HTML for element created</p>\n',
3333 type: 'String',
3334 optional: true
3335 }
3336 ],
3337 class: 'p5',
3338 module: 'DOM'
3339 },
3340 createImg: {
3341 name: 'createImg',
3342 class: 'p5',
3343 module: 'DOM',
3344 overloads: [
3345 {
3346 params: [
3347 {
3348 name: 'src',
3349 description: '<p>src path or url for image</p>\n',
3350 type: 'String'
3351 },
3352 {
3353 name: 'alt',
3354 description:
3355 '<p><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Img#Attributes">alternate text</a> to be used if image does not load. You can use also an empty string (<code>""</code>) if that an image is not intended to be viewed.</p>\n',
3356 type: 'String'
3357 }
3358 ]
3359 },
3360 {
3361 params: [
3362 {
3363 name: 'src',
3364 description: '',
3365 type: 'String'
3366 },
3367 {
3368 name: 'alt',
3369 description: '',
3370 type: 'String'
3371 },
3372 {
3373 name: 'crossOrigin',
3374 description:
3375 '<p><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes">crossOrigin property</a> of the <code>img</code> element; use either \'anonymous\' or \'use-credentials\' to retrieve the image with cross-origin access (for later use with <code>canvas</code>. if an empty string(<code>""</code>) is passed, CORS is not used</p>\n',
3376 type: 'String'
3377 },
3378 {
3379 name: 'successCallback',
3380 description:
3381 '<p>callback to be called once image data is loaded with the <a href="#/p5.Element">p5.Element</a> as argument</p>\n',
3382 type: 'Function',
3383 optional: true
3384 }
3385 ]
3386 }
3387 ]
3388 },
3389 createA: {
3390 name: 'createA',
3391 params: [
3392 {
3393 name: 'href',
3394 description: '<p>url of page to link to</p>\n',
3395 type: 'String'
3396 },
3397 {
3398 name: 'html',
3399 description: '<p>inner html of link element to display</p>\n',
3400 type: 'String'
3401 },
3402 {
3403 name: 'target',
3404 description:
3405 '<p>target where new link should open,\n could be _blank, _self, _parent, _top.</p>\n',
3406 type: 'String',
3407 optional: true
3408 }
3409 ],
3410 class: 'p5',
3411 module: 'DOM'
3412 },
3413 createSlider: {
3414 name: 'createSlider',
3415 params: [
3416 {
3417 name: 'min',
3418 description: '<p>minimum value of the slider</p>\n',
3419 type: 'Number'
3420 },
3421 {
3422 name: 'max',
3423 description: '<p>maximum value of the slider</p>\n',
3424 type: 'Number'
3425 },
3426 {
3427 name: 'value',
3428 description: '<p>default value of the slider</p>\n',
3429 type: 'Number',
3430 optional: true
3431 },
3432 {
3433 name: 'step',
3434 description:
3435 '<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',
3436 type: 'Number',
3437 optional: true
3438 }
3439 ],
3440 class: 'p5',
3441 module: 'DOM'
3442 },
3443 createButton: {
3444 name: 'createButton',
3445 params: [
3446 {
3447 name: 'label',
3448 description: '<p>label displayed on the button</p>\n',
3449 type: 'String'
3450 },
3451 {
3452 name: 'value',
3453 description: '<p>value of the button</p>\n',
3454 type: 'String',
3455 optional: true
3456 }
3457 ],
3458 class: 'p5',
3459 module: 'DOM'
3460 },
3461 createCheckbox: {
3462 name: 'createCheckbox',
3463 params: [
3464 {
3465 name: 'label',
3466 description: '<p>label displayed after checkbox</p>\n',
3467 type: 'String',
3468 optional: true
3469 },
3470 {
3471 name: 'value',
3472 description:
3473 '<p>value of the checkbox; checked is true, unchecked is false</p>\n',
3474 type: 'Boolean',
3475 optional: true
3476 }
3477 ],
3478 class: 'p5',
3479 module: 'DOM'
3480 },
3481 createSelect: {
3482 name: 'createSelect',
3483 class: 'p5',
3484 module: 'DOM',
3485 overloads: [
3486 {
3487 params: [
3488 {
3489 name: 'multiple',
3490 description:
3491 '<p>true if dropdown should support multiple selections</p>\n',
3492 type: 'Boolean',
3493 optional: true
3494 }
3495 ]
3496 },
3497 {
3498 params: [
3499 {
3500 name: 'existing',
3501 description: '<p>DOM select element</p>\n',
3502 type: 'Object'
3503 }
3504 ]
3505 }
3506 ]
3507 },
3508 createRadio: {
3509 name: 'createRadio',
3510 class: 'p5',
3511 module: 'DOM',
3512 overloads: [
3513 {
3514 params: [
3515 {
3516 name: 'containerElement',
3517 description:
3518 '<p>An container HTML Element either a div\nor span inside which all existing radio inputs will be considered as options.</p>\n',
3519 type: 'Object'
3520 },
3521 {
3522 name: 'name',
3523 description: '<p>A name parameter for each Input Element.</p>\n',
3524 type: 'String',
3525 optional: true
3526 }
3527 ]
3528 },
3529 {
3530 params: [
3531 {
3532 name: 'name',
3533 description: '',
3534 type: 'String'
3535 }
3536 ]
3537 },
3538 {
3539 params: []
3540 }
3541 ]
3542 },
3543 createColorPicker: {
3544 name: 'createColorPicker',
3545 params: [
3546 {
3547 name: 'value',
3548 description: '<p>default color of element</p>\n',
3549 type: 'String|p5.Color',
3550 optional: true
3551 }
3552 ],
3553 class: 'p5',
3554 module: 'DOM'
3555 },
3556 createInput: {
3557 name: 'createInput',
3558 class: 'p5',
3559 module: 'DOM',
3560 overloads: [
3561 {
3562 params: [
3563 {
3564 name: 'value',
3565 description: '<p>default value of the input box</p>\n',
3566 type: 'String'
3567 },
3568 {
3569 name: 'type',
3570 description:
3571 '<p>type of text, ie text, password etc. Defaults to text.\n Needs a value to be specified first.</p>\n',
3572 type: 'String',
3573 optional: true
3574 }
3575 ]
3576 },
3577 {
3578 params: [
3579 {
3580 name: 'value',
3581 description: '',
3582 type: 'String',
3583 optional: true
3584 }
3585 ]
3586 }
3587 ]
3588 },
3589 createFileInput: {
3590 name: 'createFileInput',
3591 params: [
3592 {
3593 name: 'callback',
3594 description: '<p>callback function for when a file is loaded</p>\n',
3595 type: 'Function'
3596 },
3597 {
3598 name: 'multiple',
3599 description:
3600 '<p>optional, to allow multiple files to be selected</p>\n',
3601 type: 'Boolean',
3602 optional: true
3603 }
3604 ],
3605 class: 'p5',
3606 module: 'DOM'
3607 },
3608 createVideo: {
3609 name: 'createVideo',
3610 params: [
3611 {
3612 name: 'src',
3613 description:
3614 '<p>path to a video file, or array of paths for\n supporting different browsers</p>\n',
3615 type: 'String|String[]'
3616 },
3617 {
3618 name: 'callback',
3619 description:
3620 "<p>callback function to be called upon\n 'canplaythrough' 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",
3621 type: 'Function',
3622 optional: true
3623 }
3624 ],
3625 class: 'p5',
3626 module: 'DOM'
3627 },
3628 createAudio: {
3629 name: 'createAudio',
3630 params: [
3631 {
3632 name: 'src',
3633 description:
3634 '<p>path to an audio file, or array of paths\n for supporting different browsers</p>\n',
3635 type: 'String|String[]',
3636 optional: true
3637 },
3638 {
3639 name: 'callback',
3640 description:
3641 "<p>callback function to be called upon\n 'canplaythrough' 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",
3642 type: 'Function',
3643 optional: true
3644 }
3645 ],
3646 class: 'p5',
3647 module: 'DOM'
3648 },
3649 VIDEO: {
3650 name: 'VIDEO',
3651 class: 'p5',
3652 module: 'DOM'
3653 },
3654 AUDIO: {
3655 name: 'AUDIO',
3656 class: 'p5',
3657 module: 'DOM'
3658 },
3659 createCapture: {
3660 name: 'createCapture',
3661 params: [
3662 {
3663 name: 'type',
3664 description:
3665 '<p>type of capture, either VIDEO or\n AUDIO if none specified, default both,\n or a Constraints object</p>\n',
3666 type: 'String|Constant|Object'
3667 },
3668 {
3669 name: 'callback',
3670 description:
3671 '<p>function to be called once\n stream has loaded</p>\n',
3672 type: 'Function',
3673 optional: true
3674 }
3675 ],
3676 class: 'p5',
3677 module: 'DOM'
3678 },
3679 createElement: {
3680 name: 'createElement',
3681 params: [
3682 {
3683 name: 'tag',
3684 description: '<p>tag for the new element</p>\n',
3685 type: 'String'
3686 },
3687 {
3688 name: 'content',
3689 description: '<p>html content to be inserted into the element</p>\n',
3690 type: 'String',
3691 optional: true
3692 }
3693 ],
3694 class: 'p5',
3695 module: 'DOM'
3696 },
3697 deviceOrientation: {
3698 name: 'deviceOrientation',
3699 class: 'p5',
3700 module: 'Events'
3701 },
3702 accelerationX: {
3703 name: 'accelerationX',
3704 class: 'p5',
3705 module: 'Events'
3706 },
3707 accelerationY: {
3708 name: 'accelerationY',
3709 class: 'p5',
3710 module: 'Events'
3711 },
3712 accelerationZ: {
3713 name: 'accelerationZ',
3714 class: 'p5',
3715 module: 'Events'
3716 },
3717 pAccelerationX: {
3718 name: 'pAccelerationX',
3719 class: 'p5',
3720 module: 'Events'
3721 },
3722 pAccelerationY: {
3723 name: 'pAccelerationY',
3724 class: 'p5',
3725 module: 'Events'
3726 },
3727 pAccelerationZ: {
3728 name: 'pAccelerationZ',
3729 class: 'p5',
3730 module: 'Events'
3731 },
3732 rotationX: {
3733 name: 'rotationX',
3734 class: 'p5',
3735 module: 'Events'
3736 },
3737 rotationY: {
3738 name: 'rotationY',
3739 class: 'p5',
3740 module: 'Events'
3741 },
3742 rotationZ: {
3743 name: 'rotationZ',
3744 class: 'p5',
3745 module: 'Events'
3746 },
3747 pRotationX: {
3748 name: 'pRotationX',
3749 class: 'p5',
3750 module: 'Events'
3751 },
3752 pRotationY: {
3753 name: 'pRotationY',
3754 class: 'p5',
3755 module: 'Events'
3756 },
3757 pRotationZ: {
3758 name: 'pRotationZ',
3759 class: 'p5',
3760 module: 'Events'
3761 },
3762 turnAxis: {
3763 name: 'turnAxis',
3764 class: 'p5',
3765 module: 'Events'
3766 },
3767 setMoveThreshold: {
3768 name: 'setMoveThreshold',
3769 params: [
3770 {
3771 name: 'value',
3772 description: '<p>The threshold value</p>\n',
3773 type: 'Number'
3774 }
3775 ],
3776 class: 'p5',
3777 module: 'Events'
3778 },
3779 setShakeThreshold: {
3780 name: 'setShakeThreshold',
3781 params: [
3782 {
3783 name: 'value',
3784 description: '<p>The threshold value</p>\n',
3785 type: 'Number'
3786 }
3787 ],
3788 class: 'p5',
3789 module: 'Events'
3790 },
3791 deviceMoved: {
3792 name: 'deviceMoved',
3793 class: 'p5',
3794 module: 'Events'
3795 },
3796 deviceTurned: {
3797 name: 'deviceTurned',
3798 class: 'p5',
3799 module: 'Events'
3800 },
3801 deviceShaken: {
3802 name: 'deviceShaken',
3803 class: 'p5',
3804 module: 'Events'
3805 },
3806 keyIsPressed: {
3807 name: 'keyIsPressed',
3808 class: 'p5',
3809 module: 'Events'
3810 },
3811 key: {
3812 name: 'key',
3813 class: 'p5',
3814 module: 'Events'
3815 },
3816 keyCode: {
3817 name: 'keyCode',
3818 class: 'p5',
3819 module: 'Events'
3820 },
3821 keyPressed: {
3822 name: 'keyPressed',
3823 class: 'p5',
3824 module: 'Events'
3825 },
3826 keyReleased: {
3827 name: 'keyReleased',
3828 class: 'p5',
3829 module: 'Events'
3830 },
3831 keyTyped: {
3832 name: 'keyTyped',
3833 class: 'p5',
3834 module: 'Events'
3835 },
3836 keyIsDown: {
3837 name: 'keyIsDown',
3838 params: [
3839 {
3840 name: 'code',
3841 description: '<p>The key to check for.</p>\n',
3842 type: 'Number'
3843 }
3844 ],
3845 class: 'p5',
3846 module: 'Events'
3847 },
3848 movedX: {
3849 name: 'movedX',
3850 class: 'p5',
3851 module: 'Events'
3852 },
3853 movedY: {
3854 name: 'movedY',
3855 class: 'p5',
3856 module: 'Events'
3857 },
3858 mouseX: {
3859 name: 'mouseX',
3860 class: 'p5',
3861 module: 'Events'
3862 },
3863 mouseY: {
3864 name: 'mouseY',
3865 class: 'p5',
3866 module: 'Events'
3867 },
3868 pmouseX: {
3869 name: 'pmouseX',
3870 class: 'p5',
3871 module: 'Events'
3872 },
3873 pmouseY: {
3874 name: 'pmouseY',
3875 class: 'p5',
3876 module: 'Events'
3877 },
3878 winMouseX: {
3879 name: 'winMouseX',
3880 class: 'p5',
3881 module: 'Events'
3882 },
3883 winMouseY: {
3884 name: 'winMouseY',
3885 class: 'p5',
3886 module: 'Events'
3887 },
3888 pwinMouseX: {
3889 name: 'pwinMouseX',
3890 class: 'p5',
3891 module: 'Events'
3892 },
3893 pwinMouseY: {
3894 name: 'pwinMouseY',
3895 class: 'p5',
3896 module: 'Events'
3897 },
3898 mouseButton: {
3899 name: 'mouseButton',
3900 class: 'p5',
3901 module: 'Events'
3902 },
3903 mouseIsPressed: {
3904 name: 'mouseIsPressed',
3905 class: 'p5',
3906 module: 'Events'
3907 },
3908 mouseMoved: {
3909 name: 'mouseMoved',
3910 params: [
3911 {
3912 name: 'event',
3913 description: '<p>optional MouseEvent callback argument.</p>\n',
3914 type: 'Object',
3915 optional: true
3916 }
3917 ],
3918 class: 'p5',
3919 module: 'Events'
3920 },
3921 mouseDragged: {
3922 name: 'mouseDragged',
3923 params: [
3924 {
3925 name: 'event',
3926 description: '<p>optional MouseEvent callback argument.</p>\n',
3927 type: 'Object',
3928 optional: true
3929 }
3930 ],
3931 class: 'p5',
3932 module: 'Events'
3933 },
3934 mousePressed: {
3935 name: 'mousePressed',
3936 params: [
3937 {
3938 name: 'event',
3939 description: '<p>optional MouseEvent callback argument.</p>\n',
3940 type: 'Object',
3941 optional: true
3942 }
3943 ],
3944 class: 'p5',
3945 module: 'Events'
3946 },
3947 mouseReleased: {
3948 name: 'mouseReleased',
3949 params: [
3950 {
3951 name: 'event',
3952 description: '<p>optional MouseEvent callback argument.</p>\n',
3953 type: 'Object',
3954 optional: true
3955 }
3956 ],
3957 class: 'p5',
3958 module: 'Events'
3959 },
3960 mouseClicked: {
3961 name: 'mouseClicked',
3962 params: [
3963 {
3964 name: 'event',
3965 description: '<p>optional MouseEvent callback argument.</p>\n',
3966 type: 'Object',
3967 optional: true
3968 }
3969 ],
3970 class: 'p5',
3971 module: 'Events'
3972 },
3973 doubleClicked: {
3974 name: 'doubleClicked',
3975 params: [
3976 {
3977 name: 'event',
3978 description: '<p>optional MouseEvent callback argument.</p>\n',
3979 type: 'Object',
3980 optional: true
3981 }
3982 ],
3983 class: 'p5',
3984 module: 'Events'
3985 },
3986 mouseWheel: {
3987 name: 'mouseWheel',
3988 params: [
3989 {
3990 name: 'event',
3991 description: '<p>optional WheelEvent callback argument.</p>\n',
3992 type: 'Object',
3993 optional: true
3994 }
3995 ],
3996 class: 'p5',
3997 module: 'Events'
3998 },
3999 requestPointerLock: {
4000 name: 'requestPointerLock',
4001 class: 'p5',
4002 module: 'Events'
4003 },
4004 exitPointerLock: {
4005 name: 'exitPointerLock',
4006 class: 'p5',
4007 module: 'Events'
4008 },
4009 touches: {
4010 name: 'touches',
4011 class: 'p5',
4012 module: 'Events'
4013 },
4014 touchStarted: {
4015 name: 'touchStarted',
4016 params: [
4017 {
4018 name: 'event',
4019 description: '<p>optional TouchEvent callback argument.</p>\n',
4020 type: 'Object',
4021 optional: true
4022 }
4023 ],
4024 class: 'p5',
4025 module: 'Events'
4026 },
4027 touchMoved: {
4028 name: 'touchMoved',
4029 params: [
4030 {
4031 name: 'event',
4032 description: '<p>optional TouchEvent callback argument.</p>\n',
4033 type: 'Object',
4034 optional: true
4035 }
4036 ],
4037 class: 'p5',
4038 module: 'Events'
4039 },
4040 touchEnded: {
4041 name: 'touchEnded',
4042 params: [
4043 {
4044 name: 'event',
4045 description: '<p>optional TouchEvent callback argument.</p>\n',
4046 type: 'Object',
4047 optional: true
4048 }
4049 ],
4050 class: 'p5',
4051 module: 'Events'
4052 },
4053 createImage: {
4054 name: 'createImage',
4055 params: [
4056 {
4057 name: 'width',
4058 description: '<p>width in pixels</p>\n',
4059 type: 'Integer'
4060 },
4061 {
4062 name: 'height',
4063 description: '<p>height in pixels</p>\n',
4064 type: 'Integer'
4065 }
4066 ],
4067 class: 'p5',
4068 module: 'Image'
4069 },
4070 saveCanvas: {
4071 name: 'saveCanvas',
4072 class: 'p5',
4073 module: 'Image',
4074 overloads: [
4075 {
4076 params: [
4077 {
4078 name: 'selectedCanvas',
4079 description:
4080 '<p>a variable\n representing a specific html5 canvas (optional)</p>\n',
4081 type: 'p5.Element|HTMLCanvasElement'
4082 },
4083 {
4084 name: 'filename',
4085 description: '',
4086 type: 'String',
4087 optional: true
4088 },
4089 {
4090 name: 'extension',
4091 description: "<p>'jpg' or 'png'</p>\n",
4092 type: 'String',
4093 optional: true
4094 }
4095 ]
4096 },
4097 {
4098 params: [
4099 {
4100 name: 'filename',
4101 description: '',
4102 type: 'String',
4103 optional: true
4104 },
4105 {
4106 name: 'extension',
4107 description: '',
4108 type: 'String',
4109 optional: true
4110 }
4111 ]
4112 }
4113 ]
4114 },
4115 saveFrames: {
4116 name: 'saveFrames',
4117 params: [
4118 {
4119 name: 'filename',
4120 description: '',
4121 type: 'String'
4122 },
4123 {
4124 name: 'extension',
4125 description: "<p>'jpg' or 'png'</p>\n",
4126 type: 'String'
4127 },
4128 {
4129 name: 'duration',
4130 description: '<p>Duration in seconds to save the frames for.</p>\n',
4131 type: 'Number'
4132 },
4133 {
4134 name: 'framerate',
4135 description: '<p>Framerate to save the frames in.</p>\n',
4136 type: 'Number'
4137 },
4138 {
4139 name: 'callback',
4140 description:
4141 '<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',
4142 type: 'Function(Array)',
4143 optional: true
4144 }
4145 ],
4146 class: 'p5',
4147 module: 'Image'
4148 },
4149 loadImage: {
4150 name: 'loadImage',
4151 params: [
4152 {
4153 name: 'path',
4154 description: '<p>Path of the image to be loaded</p>\n',
4155 type: 'String'
4156 },
4157 {
4158 name: 'successCallback',
4159 description:
4160 '<p>Function to be called once\n the image is loaded. Will be passed the\n <a href="#/p5.Image">p5.Image</a>.</p>\n',
4161 type: 'function(p5.Image)',
4162 optional: true
4163 },
4164 {
4165 name: 'failureCallback',
4166 description:
4167 '<p>called with event error if\n the image fails to load.</p>\n',
4168 type: 'Function(Event)',
4169 optional: true
4170 }
4171 ],
4172 class: 'p5',
4173 module: 'Image'
4174 },
4175 image: {
4176 name: 'image',
4177 class: 'p5',
4178 module: 'Image',
4179 overloads: [
4180 {
4181 params: [
4182 {
4183 name: 'img',
4184 description: '<p>the image to display</p>\n',
4185 type: 'p5.Image|p5.Element'
4186 },
4187 {
4188 name: 'x',
4189 description:
4190 '<p>the x-coordinate of the top-left corner of the image</p>\n',
4191 type: 'Number'
4192 },
4193 {
4194 name: 'y',
4195 description:
4196 '<p>the y-coordinate of the top-left corner of the image</p>\n',
4197 type: 'Number'
4198 },
4199 {
4200 name: 'width',
4201 description: '<p>the width to draw the image</p>\n',
4202 type: 'Number',
4203 optional: true
4204 },
4205 {
4206 name: 'height',
4207 description: '<p>the height to draw the image</p>\n',
4208 type: 'Number',
4209 optional: true
4210 }
4211 ]
4212 },
4213 {
4214 params: [
4215 {
4216 name: 'img',
4217 description: '',
4218 type: 'p5.Image|p5.Element'
4219 },
4220 {
4221 name: 'dx',
4222 description:
4223 '<p>the x-coordinate of the destination\n rectangle in which to draw the source image</p>\n',
4224 type: 'Number'
4225 },
4226 {
4227 name: 'dy',
4228 description:
4229 '<p>the y-coordinate of the destination\n rectangle in which to draw the source image</p>\n',
4230 type: 'Number'
4231 },
4232 {
4233 name: 'dWidth',
4234 description: '<p>the width of the destination rectangle</p>\n',
4235 type: 'Number'
4236 },
4237 {
4238 name: 'dHeight',
4239 description: '<p>the height of the destination rectangle</p>\n',
4240 type: 'Number'
4241 },
4242 {
4243 name: 'sx',
4244 description:
4245 '<p>the x-coordinate of the subsection of the source\nimage to draw into the destination rectangle</p>\n',
4246 type: 'Number'
4247 },
4248 {
4249 name: 'sy',
4250 description:
4251 '<p>the y-coordinate of the subsection of the source\nimage to draw into the destination rectangle</p>\n',
4252 type: 'Number'
4253 },
4254 {
4255 name: 'sWidth',
4256 description:
4257 '<p>the width of the subsection of the\n source image to draw into the destination\n rectangle</p>\n',
4258 type: 'Number',
4259 optional: true
4260 },
4261 {
4262 name: 'sHeight',
4263 description:
4264 '<p>the height of the subsection of the\n source image to draw into the destination rectangle</p>\n',
4265 type: 'Number',
4266 optional: true
4267 }
4268 ]
4269 }
4270 ]
4271 },
4272 tint: {
4273 name: 'tint',
4274 class: 'p5',
4275 module: 'Image',
4276 overloads: [
4277 {
4278 params: [
4279 {
4280 name: 'v1',
4281 description:
4282 '<p>red or hue value relative to\n the current color range</p>\n',
4283 type: 'Number'
4284 },
4285 {
4286 name: 'v2',
4287 description:
4288 '<p>green or saturation value\n relative to the current color range</p>\n',
4289 type: 'Number'
4290 },
4291 {
4292 name: 'v3',
4293 description:
4294 '<p>blue or brightness value\n relative to the current color range</p>\n',
4295 type: 'Number'
4296 },
4297 {
4298 name: 'alpha',
4299 description: '',
4300 type: 'Number',
4301 optional: true
4302 }
4303 ]
4304 },
4305 {
4306 params: [
4307 {
4308 name: 'value',
4309 description: '<p>a color string</p>\n',
4310 type: 'String'
4311 }
4312 ]
4313 },
4314 {
4315 params: [
4316 {
4317 name: 'gray',
4318 description: '<p>a gray value</p>\n',
4319 type: 'Number'
4320 },
4321 {
4322 name: 'alpha',
4323 description: '',
4324 type: 'Number',
4325 optional: true
4326 }
4327 ]
4328 },
4329 {
4330 params: [
4331 {
4332 name: 'values',
4333 description:
4334 '<p>an array containing the red,green,blue &\n and alpha components of the color</p>\n',
4335 type: 'Number[]'
4336 }
4337 ]
4338 },
4339 {
4340 params: [
4341 {
4342 name: 'color',
4343 description: '<p>the tint color</p>\n',
4344 type: 'p5.Color'
4345 }
4346 ]
4347 }
4348 ]
4349 },
4350 noTint: {
4351 name: 'noTint',
4352 class: 'p5',
4353 module: 'Image'
4354 },
4355 imageMode: {
4356 name: 'imageMode',
4357 params: [
4358 {
4359 name: 'mode',
4360 description: '<p>either CORNER, CORNERS, or CENTER</p>\n',
4361 type: 'Constant'
4362 }
4363 ],
4364 class: 'p5',
4365 module: 'Image'
4366 },
4367 pixels: {
4368 name: 'pixels',
4369 class: 'p5',
4370 module: 'Image'
4371 },
4372 blend: {
4373 name: 'blend',
4374 class: 'p5',
4375 module: 'Image',
4376 overloads: [
4377 {
4378 params: [
4379 {
4380 name: 'srcImage',
4381 description: '<p>source image</p>\n',
4382 type: 'p5.Image'
4383 },
4384 {
4385 name: 'sx',
4386 description:
4387 "<p>X coordinate of the source's upper left corner</p>\n",
4388 type: 'Integer'
4389 },
4390 {
4391 name: 'sy',
4392 description:
4393 "<p>Y coordinate of the source's upper left corner</p>\n",
4394 type: 'Integer'
4395 },
4396 {
4397 name: 'sw',
4398 description: '<p>source image width</p>\n',
4399 type: 'Integer'
4400 },
4401 {
4402 name: 'sh',
4403 description: '<p>source image height</p>\n',
4404 type: 'Integer'
4405 },
4406 {
4407 name: 'dx',
4408 description:
4409 "<p>X coordinate of the destination's upper left corner</p>\n",
4410 type: 'Integer'
4411 },
4412 {
4413 name: 'dy',
4414 description:
4415 "<p>Y coordinate of the destination's upper left corner</p>\n",
4416 type: 'Integer'
4417 },
4418 {
4419 name: 'dw',
4420 description: '<p>destination image width</p>\n',
4421 type: 'Integer'
4422 },
4423 {
4424 name: 'dh',
4425 description: '<p>destination image height</p>\n',
4426 type: 'Integer'
4427 },
4428 {
4429 name: 'blendMode',
4430 description:
4431 '<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',
4432 type: 'Constant'
4433 }
4434 ]
4435 },
4436 {
4437 params: [
4438 {
4439 name: 'sx',
4440 description: '',
4441 type: 'Integer'
4442 },
4443 {
4444 name: 'sy',
4445 description: '',
4446 type: 'Integer'
4447 },
4448 {
4449 name: 'sw',
4450 description: '',
4451 type: 'Integer'
4452 },
4453 {
4454 name: 'sh',
4455 description: '',
4456 type: 'Integer'
4457 },
4458 {
4459 name: 'dx',
4460 description: '',
4461 type: 'Integer'
4462 },
4463 {
4464 name: 'dy',
4465 description: '',
4466 type: 'Integer'
4467 },
4468 {
4469 name: 'dw',
4470 description: '',
4471 type: 'Integer'
4472 },
4473 {
4474 name: 'dh',
4475 description: '',
4476 type: 'Integer'
4477 },
4478 {
4479 name: 'blendMode',
4480 description: '',
4481 type: 'Constant'
4482 }
4483 ]
4484 }
4485 ]
4486 },
4487 copy: {
4488 name: 'copy',
4489 class: 'p5',
4490 module: 'Image',
4491 overloads: [
4492 {
4493 params: [
4494 {
4495 name: 'srcImage',
4496 description: '<p>source image</p>\n',
4497 type: 'p5.Image|p5.Element'
4498 },
4499 {
4500 name: 'sx',
4501 description:
4502 "<p>X coordinate of the source's upper left corner</p>\n",
4503 type: 'Integer'
4504 },
4505 {
4506 name: 'sy',
4507 description:
4508 "<p>Y coordinate of the source's upper left corner</p>\n",
4509 type: 'Integer'
4510 },
4511 {
4512 name: 'sw',
4513 description: '<p>source image width</p>\n',
4514 type: 'Integer'
4515 },
4516 {
4517 name: 'sh',
4518 description: '<p>source image height</p>\n',
4519 type: 'Integer'
4520 },
4521 {
4522 name: 'dx',
4523 description:
4524 "<p>X coordinate of the destination's upper left corner</p>\n",
4525 type: 'Integer'
4526 },
4527 {
4528 name: 'dy',
4529 description:
4530 "<p>Y coordinate of the destination's upper left corner</p>\n",
4531 type: 'Integer'
4532 },
4533 {
4534 name: 'dw',
4535 description: '<p>destination image width</p>\n',
4536 type: 'Integer'
4537 },
4538 {
4539 name: 'dh',
4540 description: '<p>destination image height</p>\n',
4541 type: 'Integer'
4542 }
4543 ]
4544 },
4545 {
4546 params: [
4547 {
4548 name: 'sx',
4549 description: '',
4550 type: 'Integer'
4551 },
4552 {
4553 name: 'sy',
4554 description: '',
4555 type: 'Integer'
4556 },
4557 {
4558 name: 'sw',
4559 description: '',
4560 type: 'Integer'
4561 },
4562 {
4563 name: 'sh',
4564 description: '',
4565 type: 'Integer'
4566 },
4567 {
4568 name: 'dx',
4569 description: '',
4570 type: 'Integer'
4571 },
4572 {
4573 name: 'dy',
4574 description: '',
4575 type: 'Integer'
4576 },
4577 {
4578 name: 'dw',
4579 description: '',
4580 type: 'Integer'
4581 },
4582 {
4583 name: 'dh',
4584 description: '',
4585 type: 'Integer'
4586 }
4587 ]
4588 }
4589 ]
4590 },
4591 filter: {
4592 name: 'filter',
4593 params: [
4594 {
4595 name: 'filterType',
4596 description:
4597 '<p>either THRESHOLD, GRAY, OPAQUE, INVERT,\n POSTERIZE, BLUR, ERODE, DILATE or BLUR.\n See Filters.js for docs on\n each available filter</p>\n',
4598 type: 'Constant'
4599 },
4600 {
4601 name: 'filterParam',
4602 description:
4603 '<p>an optional parameter unique\n to each filter, see above</p>\n',
4604 type: 'Number',
4605 optional: true
4606 }
4607 ],
4608 class: 'p5',
4609 module: 'Image'
4610 },
4611 get: {
4612 name: 'get',
4613 class: 'p5',
4614 module: 'Image',
4615 overloads: [
4616 {
4617 params: [
4618 {
4619 name: 'x',
4620 description: '<p>x-coordinate of the pixel</p>\n',
4621 type: 'Number'
4622 },
4623 {
4624 name: 'y',
4625 description: '<p>y-coordinate of the pixel</p>\n',
4626 type: 'Number'
4627 },
4628 {
4629 name: 'w',
4630 description: '<p>width</p>\n',
4631 type: 'Number'
4632 },
4633 {
4634 name: 'h',
4635 description: '<p>height</p>\n',
4636 type: 'Number'
4637 }
4638 ]
4639 },
4640 {
4641 params: []
4642 },
4643 {
4644 params: [
4645 {
4646 name: 'x',
4647 description: '',
4648 type: 'Number'
4649 },
4650 {
4651 name: 'y',
4652 description: '',
4653 type: 'Number'
4654 }
4655 ]
4656 }
4657 ]
4658 },
4659 loadPixels: {
4660 name: 'loadPixels',
4661 class: 'p5',
4662 module: 'Image'
4663 },
4664 set: {
4665 name: 'set',
4666 params: [
4667 {
4668 name: 'x',
4669 description: '<p>x-coordinate of the pixel</p>\n',
4670 type: 'Number'
4671 },
4672 {
4673 name: 'y',
4674 description: '<p>y-coordinate of the pixel</p>\n',
4675 type: 'Number'
4676 },
4677 {
4678 name: 'c',
4679 description:
4680 '<p>insert a grayscale value | a pixel array |\n a <a href="#/p5.Color">p5.Color</a> object | a <a href="#/p5.Image">p5.Image</a> to copy</p>\n',
4681 type: 'Number|Number[]|Object'
4682 }
4683 ],
4684 class: 'p5',
4685 module: 'Image'
4686 },
4687 updatePixels: {
4688 name: 'updatePixels',
4689 params: [
4690 {
4691 name: 'x',
4692 description:
4693 '<p>x-coordinate of the upper-left corner of region\n to update</p>\n',
4694 type: 'Number',
4695 optional: true
4696 },
4697 {
4698 name: 'y',
4699 description:
4700 '<p>y-coordinate of the upper-left corner of region\n to update</p>\n',
4701 type: 'Number',
4702 optional: true
4703 },
4704 {
4705 name: 'w',
4706 description: '<p>width of region to update</p>\n',
4707 type: 'Number',
4708 optional: true
4709 },
4710 {
4711 name: 'h',
4712 description: '<p>height of region to update</p>\n',
4713 type: 'Number',
4714 optional: true
4715 }
4716 ],
4717 class: 'p5',
4718 module: 'Image'
4719 },
4720 loadJSON: {
4721 name: 'loadJSON',
4722 class: 'p5',
4723 module: 'IO',
4724 overloads: [
4725 {
4726 params: [
4727 {
4728 name: 'path',
4729 description: '<p>name of the file or url to load</p>\n',
4730 type: 'String'
4731 },
4732 {
4733 name: 'jsonpOptions',
4734 description: '<p>options object for jsonp related settings</p>\n',
4735 type: 'Object',
4736 optional: true
4737 },
4738 {
4739 name: 'datatype',
4740 description: '<p>"json" or "jsonp"</p>\n',
4741 type: 'String',
4742 optional: true
4743 },
4744 {
4745 name: 'callback',
4746 description:
4747 '<p>function to be executed after\n <a href="#/p5/loadJSON">loadJSON()</a> completes, data is passed\n in as first argument</p>\n',
4748 type: 'Function',
4749 optional: true
4750 },
4751 {
4752 name: 'errorCallback',
4753 description:
4754 '<p>function to be executed if\n there is an error, response is passed\n in as first argument</p>\n',
4755 type: 'Function',
4756 optional: true
4757 }
4758 ]
4759 },
4760 {
4761 params: [
4762 {
4763 name: 'path',
4764 description: '',
4765 type: 'String'
4766 },
4767 {
4768 name: 'datatype',
4769 description: '',
4770 type: 'String'
4771 },
4772 {
4773 name: 'callback',
4774 description: '',
4775 type: 'Function',
4776 optional: true
4777 },
4778 {
4779 name: 'errorCallback',
4780 description: '',
4781 type: 'Function',
4782 optional: true
4783 }
4784 ]
4785 },
4786 {
4787 params: [
4788 {
4789 name: 'path',
4790 description: '',
4791 type: 'String'
4792 },
4793 {
4794 name: 'callback',
4795 description: '',
4796 type: 'Function'
4797 },
4798 {
4799 name: 'errorCallback',
4800 description: '',
4801 type: 'Function',
4802 optional: true
4803 }
4804 ]
4805 }
4806 ]
4807 },
4808 loadStrings: {
4809 name: 'loadStrings',
4810 params: [
4811 {
4812 name: 'filename',
4813 description: '<p>name of the file or url to load</p>\n',
4814 type: 'String'
4815 },
4816 {
4817 name: 'callback',
4818 description:
4819 '<p>function to be executed after <a href="#/p5/loadStrings">loadStrings()</a>\n completes, Array is passed in as first\n argument</p>\n',
4820 type: 'Function',
4821 optional: true
4822 },
4823 {
4824 name: 'errorCallback',
4825 description:
4826 '<p>function to be executed if\n there is an error, response is passed\n in as first argument</p>\n',
4827 type: 'Function',
4828 optional: true
4829 }
4830 ],
4831 class: 'p5',
4832 module: 'IO'
4833 },
4834 loadTable: {
4835 name: 'loadTable',
4836 params: [
4837 {
4838 name: 'filename',
4839 description: '<p>name of the file or URL to load</p>\n',
4840 type: 'String'
4841 },
4842 {
4843 name: 'extension',
4844 description:
4845 '<p>parse the table by comma-separated values "csv", semicolon-separated\n values "ssv", or tab-separated values "tsv"</p>\n',
4846 type: 'String',
4847 optional: true
4848 },
4849 {
4850 name: 'header',
4851 description: '<p>"header" to indicate table has header row</p>\n',
4852 type: 'String',
4853 optional: true
4854 },
4855 {
4856 name: 'callback',
4857 description:
4858 '<p>function to be executed after\n <a href="#/p5/loadTable">loadTable()</a> completes. On success, the\n <a href="#/p5.Table">Table</a> object is passed in as the\n first argument.</p>\n',
4859 type: 'Function',
4860 optional: true
4861 },
4862 {
4863 name: 'errorCallback',
4864 description:
4865 '<p>function to be executed if\n there is an error, response is passed\n in as first argument</p>\n',
4866 type: 'Function',
4867 optional: true
4868 }
4869 ],
4870 class: 'p5',
4871 module: 'IO'
4872 },
4873 loadXML: {
4874 name: 'loadXML',
4875 params: [
4876 {
4877 name: 'filename',
4878 description: '<p>name of the file or URL to load</p>\n',
4879 type: 'String'
4880 },
4881 {
4882 name: 'callback',
4883 description:
4884 '<p>function to be executed after <a href="#/p5/loadXML">loadXML()</a>\n completes, XML object is passed in as\n first argument</p>\n',
4885 type: 'Function',
4886 optional: true
4887 },
4888 {
4889 name: 'errorCallback',
4890 description:
4891 '<p>function to be executed if\n there is an error, response is passed\n in as first argument</p>\n',
4892 type: 'Function',
4893 optional: true
4894 }
4895 ],
4896 class: 'p5',
4897 module: 'IO'
4898 },
4899 loadBytes: {
4900 name: 'loadBytes',
4901 params: [
4902 {
4903 name: 'file',
4904 description: '<p>name of the file or URL to load</p>\n',
4905 type: 'String'
4906 },
4907 {
4908 name: 'callback',
4909 description:
4910 '<p>function to be executed after <a href="#/p5/loadBytes">loadBytes()</a>\n completes</p>\n',
4911 type: 'Function',
4912 optional: true
4913 },
4914 {
4915 name: 'errorCallback',
4916 description:
4917 '<p>function to be executed if there\n is an error</p>\n',
4918 type: 'Function',
4919 optional: true
4920 }
4921 ],
4922 class: 'p5',
4923 module: 'IO'
4924 },
4925 httpGet: {
4926 name: 'httpGet',
4927 class: 'p5',
4928 module: 'IO',
4929 overloads: [
4930 {
4931 params: [
4932 {
4933 name: 'path',
4934 description: '<p>name of the file or url to load</p>\n',
4935 type: 'String'
4936 },
4937 {
4938 name: 'datatype',
4939 description:
4940 '<p>"json", "jsonp", "binary", "arrayBuffer",\n "xml", or "text"</p>\n',
4941 type: 'String',
4942 optional: true
4943 },
4944 {
4945 name: 'data',
4946 description: '<p>param data passed sent with request</p>\n',
4947 type: 'Object|Boolean',
4948 optional: true
4949 },
4950 {
4951 name: 'callback',
4952 description:
4953 '<p>function to be executed after\n <a href="#/p5/httpGet">httpGet()</a> completes, data is passed in\n as first argument</p>\n',
4954 type: 'Function',
4955 optional: true
4956 },
4957 {
4958 name: 'errorCallback',
4959 description:
4960 '<p>function to be executed if\n there is an error, response is passed\n in as first argument</p>\n',
4961 type: 'Function',
4962 optional: true
4963 }
4964 ]
4965 },
4966 {
4967 params: [
4968 {
4969 name: 'path',
4970 description: '',
4971 type: 'String'
4972 },
4973 {
4974 name: 'data',
4975 description: '',
4976 type: 'Object|Boolean'
4977 },
4978 {
4979 name: 'callback',
4980 description: '',
4981 type: 'Function',
4982 optional: true
4983 },
4984 {
4985 name: 'errorCallback',
4986 description: '',
4987 type: 'Function',
4988 optional: true
4989 }
4990 ]
4991 },
4992 {
4993 params: [
4994 {
4995 name: 'path',
4996 description: '',
4997 type: 'String'
4998 },
4999 {
5000 name: 'callback',
5001 description: '',
5002 type: 'Function'
5003 },
5004 {
5005 name: 'errorCallback',
5006 description: '',
5007 type: 'Function',
5008 optional: true
5009 }
5010 ]
5011 }
5012 ]
5013 },
5014 httpPost: {
5015 name: 'httpPost',
5016 class: 'p5',
5017 module: 'IO',
5018 overloads: [
5019 {
5020 params: [
5021 {
5022 name: 'path',
5023 description: '<p>name of the file or url to load</p>\n',
5024 type: 'String'
5025 },
5026 {
5027 name: 'datatype',
5028 description:
5029 '<p>"json", "jsonp", "xml", or "text".\n If omitted, <a href="#/p5/httpPost">httpPost()</a> will guess.</p>\n',
5030 type: 'String',
5031 optional: true
5032 },
5033 {
5034 name: 'data',
5035 description: '<p>param data passed sent with request</p>\n',
5036 type: 'Object|Boolean',
5037 optional: true
5038 },
5039 {
5040 name: 'callback',
5041 description:
5042 '<p>function to be executed after\n <a href="#/p5/httpPost">httpPost()</a> completes, data is passed in\n as first argument</p>\n',
5043 type: 'Function',
5044 optional: true
5045 },
5046 {
5047 name: 'errorCallback',
5048 description:
5049 '<p>function to be executed if\n there is an error, response is passed\n in as first argument</p>\n',
5050 type: 'Function',
5051 optional: true
5052 }
5053 ]
5054 },
5055 {
5056 params: [
5057 {
5058 name: 'path',
5059 description: '',
5060 type: 'String'
5061 },
5062 {
5063 name: 'data',
5064 description: '',
5065 type: 'Object|Boolean'
5066 },
5067 {
5068 name: 'callback',
5069 description: '',
5070 type: 'Function',
5071 optional: true
5072 },
5073 {
5074 name: 'errorCallback',
5075 description: '',
5076 type: 'Function',
5077 optional: true
5078 }
5079 ]
5080 },
5081 {
5082 params: [
5083 {
5084 name: 'path',
5085 description: '',
5086 type: 'String'
5087 },
5088 {
5089 name: 'callback',
5090 description: '',
5091 type: 'Function'
5092 },
5093 {
5094 name: 'errorCallback',
5095 description: '',
5096 type: 'Function',
5097 optional: true
5098 }
5099 ]
5100 }
5101 ]
5102 },
5103 httpDo: {
5104 name: 'httpDo',
5105 class: 'p5',
5106 module: 'IO',
5107 overloads: [
5108 {
5109 params: [
5110 {
5111 name: 'path',
5112 description: '<p>name of the file or url to load</p>\n',
5113 type: 'String'
5114 },
5115 {
5116 name: 'method',
5117 description:
5118 '<p>either "GET", "POST", or "PUT",\n defaults to "GET"</p>\n',
5119 type: 'String',
5120 optional: true
5121 },
5122 {
5123 name: 'datatype',
5124 description: '<p>"json", "jsonp", "xml", or "text"</p>\n',
5125 type: 'String',
5126 optional: true
5127 },
5128 {
5129 name: 'data',
5130 description: '<p>param data passed sent with request</p>\n',
5131 type: 'Object',
5132 optional: true
5133 },
5134 {
5135 name: 'callback',
5136 description:
5137 '<p>function to be executed after\n <a href="#/p5/httpGet">httpGet()</a> completes, data is passed in\n as first argument</p>\n',
5138 type: 'Function',
5139 optional: true
5140 },
5141 {
5142 name: 'errorCallback',
5143 description:
5144 '<p>function to be executed if\n there is an error, response is passed\n in as first argument</p>\n',
5145 type: 'Function',
5146 optional: true
5147 }
5148 ]
5149 },
5150 {
5151 params: [
5152 {
5153 name: 'path',
5154 description: '',
5155 type: 'String'
5156 },
5157 {
5158 name: 'options',
5159 description:
5160 '<p>Request object options as documented in the\n "fetch" API\n<a href="https://developer.mozilla.org/en/docs/Web/API/Fetch_API">reference</a></p>\n',
5161 type: 'Object'
5162 },
5163 {
5164 name: 'callback',
5165 description: '',
5166 type: 'Function',
5167 optional: true
5168 },
5169 {
5170 name: 'errorCallback',
5171 description: '',
5172 type: 'Function',
5173 optional: true
5174 }
5175 ]
5176 }
5177 ]
5178 },
5179 createWriter: {
5180 name: 'createWriter',
5181 params: [
5182 {
5183 name: 'name',
5184 description: '<p>name of the file to be created</p>\n',
5185 type: 'String'
5186 },
5187 {
5188 name: 'extension',
5189 description: '',
5190 type: 'String',
5191 optional: true
5192 }
5193 ],
5194 class: 'p5',
5195 module: 'IO'
5196 },
5197 save: {
5198 name: 'save',
5199 params: [
5200 {
5201 name: 'objectOrFilename',
5202 description:
5203 '<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',
5204 type: 'Object|String',
5205 optional: true
5206 },
5207 {
5208 name: 'filename',
5209 description:
5210 '<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',
5211 type: 'String',
5212 optional: true
5213 },
5214 {
5215 name: 'options',
5216 description:
5217 '<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',
5218 type: 'Boolean|String',
5219 optional: true
5220 }
5221 ],
5222 class: 'p5',
5223 module: 'IO'
5224 },
5225 saveJSON: {
5226 name: 'saveJSON',
5227 params: [
5228 {
5229 name: 'json',
5230 description: '',
5231 type: 'Array|Object'
5232 },
5233 {
5234 name: 'filename',
5235 description: '',
5236 type: 'String'
5237 },
5238 {
5239 name: 'optimize',
5240 description:
5241 '<p>If true, removes line breaks\n and spaces from the output\n file to optimize filesize\n (but not readability).</p>\n',
5242 type: 'Boolean',
5243 optional: true
5244 }
5245 ],
5246 class: 'p5',
5247 module: 'IO'
5248 },
5249 saveStrings: {
5250 name: 'saveStrings',
5251 params: [
5252 {
5253 name: 'list',
5254 description: '<p>string array to be written</p>\n',
5255 type: 'String[]'
5256 },
5257 {
5258 name: 'filename',
5259 description: '<p>filename for output</p>\n',
5260 type: 'String'
5261 },
5262 {
5263 name: 'extension',
5264 description: "<p>the filename's extension</p>\n",
5265 type: 'String',
5266 optional: true
5267 },
5268 {
5269 name: 'isCRLF',
5270 description: '<p>if true, change line-break to CRLF</p>\n',
5271 type: 'Boolean',
5272 optional: true
5273 }
5274 ],
5275 class: 'p5',
5276 module: 'IO'
5277 },
5278 saveTable: {
5279 name: 'saveTable',
5280 params: [
5281 {
5282 name: 'Table',
5283 description:
5284 '<p>the <a href="#/p5.Table">Table</a> object to save to a file</p>\n',
5285 type: 'p5.Table'
5286 },
5287 {
5288 name: 'filename',
5289 description: '<p>the filename to which the Table should be saved</p>\n',
5290 type: 'String'
5291 },
5292 {
5293 name: 'options',
5294 description: '<p>can be one of "tsv", "csv", or "html"</p>\n',
5295 type: 'String',
5296 optional: true
5297 }
5298 ],
5299 class: 'p5',
5300 module: 'IO'
5301 },
5302 abs: {
5303 name: 'abs',
5304 params: [
5305 {
5306 name: 'n',
5307 description: '<p>number to compute</p>\n',
5308 type: 'Number'
5309 }
5310 ],
5311 class: 'p5',
5312 module: 'Math'
5313 },
5314 ceil: {
5315 name: 'ceil',
5316 params: [
5317 {
5318 name: 'n',
5319 description: '<p>number to round up</p>\n',
5320 type: 'Number'
5321 }
5322 ],
5323 class: 'p5',
5324 module: 'Math'
5325 },
5326 constrain: {
5327 name: 'constrain',
5328 params: [
5329 {
5330 name: 'n',
5331 description: '<p>number to constrain</p>\n',
5332 type: 'Number'
5333 },
5334 {
5335 name: 'low',
5336 description: '<p>minimum limit</p>\n',
5337 type: 'Number'
5338 },
5339 {
5340 name: 'high',
5341 description: '<p>maximum limit</p>\n',
5342 type: 'Number'
5343 }
5344 ],
5345 class: 'p5',
5346 module: 'Math'
5347 },
5348 dist: {
5349 name: 'dist',
5350 class: 'p5',
5351 module: 'Math',
5352 overloads: [
5353 {
5354 params: [
5355 {
5356 name: 'x1',
5357 description: '<p>x-coordinate of the first point</p>\n',
5358 type: 'Number'
5359 },
5360 {
5361 name: 'y1',
5362 description: '<p>y-coordinate of the first point</p>\n',
5363 type: 'Number'
5364 },
5365 {
5366 name: 'x2',
5367 description: '<p>x-coordinate of the second point</p>\n',
5368 type: 'Number'
5369 },
5370 {
5371 name: 'y2',
5372 description: '<p>y-coordinate of the second point</p>\n',
5373 type: 'Number'
5374 }
5375 ]
5376 },
5377 {
5378 params: [
5379 {
5380 name: 'x1',
5381 description: '',
5382 type: 'Number'
5383 },
5384 {
5385 name: 'y1',
5386 description: '',
5387 type: 'Number'
5388 },
5389 {
5390 name: 'z1',
5391 description: '<p>z-coordinate of the first point</p>\n',
5392 type: 'Number'
5393 },
5394 {
5395 name: 'x2',
5396 description: '',
5397 type: 'Number'
5398 },
5399 {
5400 name: 'y2',
5401 description: '',
5402 type: 'Number'
5403 },
5404 {
5405 name: 'z2',
5406 description: '<p>z-coordinate of the second point</p>\n',
5407 type: 'Number'
5408 }
5409 ]
5410 }
5411 ]
5412 },
5413 exp: {
5414 name: 'exp',
5415 params: [
5416 {
5417 name: 'n',
5418 description: '<p>exponent to raise</p>\n',
5419 type: 'Number'
5420 }
5421 ],
5422 class: 'p5',
5423 module: 'Math'
5424 },
5425 floor: {
5426 name: 'floor',
5427 params: [
5428 {
5429 name: 'n',
5430 description: '<p>number to round down</p>\n',
5431 type: 'Number'
5432 }
5433 ],
5434 class: 'p5',
5435 module: 'Math'
5436 },
5437 lerp: {
5438 name: 'lerp',
5439 params: [
5440 {
5441 name: 'start',
5442 description: '<p>first value</p>\n',
5443 type: 'Number'
5444 },
5445 {
5446 name: 'stop',
5447 description: '<p>second value</p>\n',
5448 type: 'Number'
5449 },
5450 {
5451 name: 'amt',
5452 description: '<p>number</p>\n',
5453 type: 'Number'
5454 }
5455 ],
5456 class: 'p5',
5457 module: 'Math'
5458 },
5459 log: {
5460 name: 'log',
5461 params: [
5462 {
5463 name: 'n',
5464 description: '<p>number greater than 0</p>\n',
5465 type: 'Number'
5466 }
5467 ],
5468 class: 'p5',
5469 module: 'Math'
5470 },
5471 mag: {
5472 name: 'mag',
5473 params: [
5474 {
5475 name: 'a',
5476 description: '<p>first value</p>\n',
5477 type: 'Number'
5478 },
5479 {
5480 name: 'b',
5481 description: '<p>second value</p>\n',
5482 type: 'Number'
5483 }
5484 ],
5485 class: 'p5',
5486 module: 'Math'
5487 },
5488 map: {
5489 name: 'map',
5490 params: [
5491 {
5492 name: 'value',
5493 description: '<p>the incoming value to be converted</p>\n',
5494 type: 'Number'
5495 },
5496 {
5497 name: 'start1',
5498 description: "<p>lower bound of the value's current range</p>\n",
5499 type: 'Number'
5500 },
5501 {
5502 name: 'stop1',
5503 description: "<p>upper bound of the value's current range</p>\n",
5504 type: 'Number'
5505 },
5506 {
5507 name: 'start2',
5508 description: "<p>lower bound of the value's target range</p>\n",
5509 type: 'Number'
5510 },
5511 {
5512 name: 'stop2',
5513 description: "<p>upper bound of the value's target range</p>\n",
5514 type: 'Number'
5515 },
5516 {
5517 name: 'withinBounds',
5518 description: '<p>constrain the value to the newly mapped range</p>\n',
5519 type: 'Boolean',
5520 optional: true
5521 }
5522 ],
5523 class: 'p5',
5524 module: 'Math'
5525 },
5526 max: {
5527 name: 'max',
5528 class: 'p5',
5529 module: 'Math',
5530 overloads: [
5531 {
5532 params: [
5533 {
5534 name: 'n0',
5535 description: '<p>Number to compare</p>\n',
5536 type: 'Number'
5537 },
5538 {
5539 name: 'n1',
5540 description: '<p>Number to compare</p>\n',
5541 type: 'Number'
5542 }
5543 ]
5544 },
5545 {
5546 params: [
5547 {
5548 name: 'nums',
5549 description: '<p>Numbers to compare</p>\n',
5550 type: 'Number[]'
5551 }
5552 ]
5553 }
5554 ]
5555 },
5556 min: {
5557 name: 'min',
5558 class: 'p5',
5559 module: 'Math',
5560 overloads: [
5561 {
5562 params: [
5563 {
5564 name: 'n0',
5565 description: '<p>Number to compare</p>\n',
5566 type: 'Number'
5567 },
5568 {
5569 name: 'n1',
5570 description: '<p>Number to compare</p>\n',
5571 type: 'Number'
5572 }
5573 ]
5574 },
5575 {
5576 params: [
5577 {
5578 name: 'nums',
5579 description: '<p>Numbers to compare</p>\n',
5580 type: 'Number[]'
5581 }
5582 ]
5583 }
5584 ]
5585 },
5586 norm: {
5587 name: 'norm',
5588 params: [
5589 {
5590 name: 'value',
5591 description: '<p>incoming value to be normalized</p>\n',
5592 type: 'Number'
5593 },
5594 {
5595 name: 'start',
5596 description: "<p>lower bound of the value's current range</p>\n",
5597 type: 'Number'
5598 },
5599 {
5600 name: 'stop',
5601 description: "<p>upper bound of the value's current range</p>\n",
5602 type: 'Number'
5603 }
5604 ],
5605 class: 'p5',
5606 module: 'Math'
5607 },
5608 pow: {
5609 name: 'pow',
5610 params: [
5611 {
5612 name: 'n',
5613 description: '<p>base of the exponential expression</p>\n',
5614 type: 'Number'
5615 },
5616 {
5617 name: 'e',
5618 description: '<p>power by which to raise the base</p>\n',
5619 type: 'Number'
5620 }
5621 ],
5622 class: 'p5',
5623 module: 'Math'
5624 },
5625 round: {
5626 name: 'round',
5627 params: [
5628 {
5629 name: 'n',
5630 description: '<p>number to round</p>\n',
5631 type: 'Number'
5632 },
5633 {
5634 name: 'decimals',
5635 description:
5636 '<p>number of decimal places to round to, default is 0</p>\n',
5637 type: 'Number',
5638 optional: true
5639 }
5640 ],
5641 class: 'p5',
5642 module: 'Math'
5643 },
5644 sq: {
5645 name: 'sq',
5646 params: [
5647 {
5648 name: 'n',
5649 description: '<p>number to square</p>\n',
5650 type: 'Number'
5651 }
5652 ],
5653 class: 'p5',
5654 module: 'Math'
5655 },
5656 sqrt: {
5657 name: 'sqrt',
5658 params: [
5659 {
5660 name: 'n',
5661 description: '<p>non-negative number to square root</p>\n',
5662 type: 'Number'
5663 }
5664 ],
5665 class: 'p5',
5666 module: 'Math'
5667 },
5668 fract: {
5669 name: 'fract',
5670 params: [
5671 {
5672 name: 'num',
5673 description:
5674 '<p>Number whose fractional part needs to be found out</p>\n',
5675 type: 'Number'
5676 }
5677 ],
5678 class: 'p5',
5679 module: 'Math'
5680 },
5681 createVector: {
5682 name: 'createVector',
5683 params: [
5684 {
5685 name: 'x',
5686 description: '<p>x component of the vector</p>\n',
5687 type: 'Number',
5688 optional: true
5689 },
5690 {
5691 name: 'y',
5692 description: '<p>y component of the vector</p>\n',
5693 type: 'Number',
5694 optional: true
5695 },
5696 {
5697 name: 'z',
5698 description: '<p>z component of the vector</p>\n',
5699 type: 'Number',
5700 optional: true
5701 }
5702 ],
5703 class: 'p5',
5704 module: 'Math'
5705 },
5706 noise: {
5707 name: 'noise',
5708 params: [
5709 {
5710 name: 'x',
5711 description: '<p>x-coordinate in noise space</p>\n',
5712 type: 'Number'
5713 },
5714 {
5715 name: 'y',
5716 description: '<p>y-coordinate in noise space</p>\n',
5717 type: 'Number',
5718 optional: true
5719 },
5720 {
5721 name: 'z',
5722 description: '<p>z-coordinate in noise space</p>\n',
5723 type: 'Number',
5724 optional: true
5725 }
5726 ],
5727 class: 'p5',
5728 module: 'Math'
5729 },
5730 noiseDetail: {
5731 name: 'noiseDetail',
5732 params: [
5733 {
5734 name: 'lod',
5735 description: '<p>number of octaves to be used by the noise</p>\n',
5736 type: 'Number'
5737 },
5738 {
5739 name: 'falloff',
5740 description: '<p>falloff factor for each octave</p>\n',
5741 type: 'Number'
5742 }
5743 ],
5744 class: 'p5',
5745 module: 'Math'
5746 },
5747 noiseSeed: {
5748 name: 'noiseSeed',
5749 params: [
5750 {
5751 name: 'seed',
5752 description: '<p>the seed value</p>\n',
5753 type: 'Number'
5754 }
5755 ],
5756 class: 'p5',
5757 module: 'Math'
5758 },
5759 randomSeed: {
5760 name: 'randomSeed',
5761 params: [
5762 {
5763 name: 'seed',
5764 description: '<p>the seed value</p>\n',
5765 type: 'Number'
5766 }
5767 ],
5768 class: 'p5',
5769 module: 'Math'
5770 },
5771 random: {
5772 name: 'random',
5773 class: 'p5',
5774 module: 'Math',
5775 overloads: [
5776 {
5777 params: [
5778 {
5779 name: 'min',
5780 description: '<p>the lower bound (inclusive)</p>\n',
5781 type: 'Number',
5782 optional: true
5783 },
5784 {
5785 name: 'max',
5786 description: '<p>the upper bound (exclusive)</p>\n',
5787 type: 'Number',
5788 optional: true
5789 }
5790 ]
5791 },
5792 {
5793 params: [
5794 {
5795 name: 'choices',
5796 description: '<p>the array to choose from</p>\n',
5797 type: 'Array'
5798 }
5799 ]
5800 }
5801 ]
5802 },
5803 randomGaussian: {
5804 name: 'randomGaussian',
5805 params: [
5806 {
5807 name: 'mean',
5808 description: '<p>the mean</p>\n',
5809 type: 'Number'
5810 },
5811 {
5812 name: 'sd',
5813 description: '<p>the standard deviation</p>\n',
5814 type: 'Number'
5815 }
5816 ],
5817 class: 'p5',
5818 module: 'Math'
5819 },
5820 acos: {
5821 name: 'acos',
5822 params: [
5823 {
5824 name: 'value',
5825 description: '<p>the value whose arc cosine is to be returned</p>\n',
5826 type: 'Number'
5827 }
5828 ],
5829 class: 'p5',
5830 module: 'Math'
5831 },
5832 asin: {
5833 name: 'asin',
5834 params: [
5835 {
5836 name: 'value',
5837 description: '<p>the value whose arc sine is to be returned</p>\n',
5838 type: 'Number'
5839 }
5840 ],
5841 class: 'p5',
5842 module: 'Math'
5843 },
5844 atan: {
5845 name: 'atan',
5846 params: [
5847 {
5848 name: 'value',
5849 description: '<p>the value whose arc tangent is to be returned</p>\n',
5850 type: 'Number'
5851 }
5852 ],
5853 class: 'p5',
5854 module: 'Math'
5855 },
5856 atan2: {
5857 name: 'atan2',
5858 params: [
5859 {
5860 name: 'y',
5861 description: '<p>y-coordinate of the point</p>\n',
5862 type: 'Number'
5863 },
5864 {
5865 name: 'x',
5866 description: '<p>x-coordinate of the point</p>\n',
5867 type: 'Number'
5868 }
5869 ],
5870 class: 'p5',
5871 module: 'Math'
5872 },
5873 cos: {
5874 name: 'cos',
5875 params: [
5876 {
5877 name: 'angle',
5878 description: '<p>the angle</p>\n',
5879 type: 'Number'
5880 }
5881 ],
5882 class: 'p5',
5883 module: 'Math'
5884 },
5885 sin: {
5886 name: 'sin',
5887 params: [
5888 {
5889 name: 'angle',
5890 description: '<p>the angle</p>\n',
5891 type: 'Number'
5892 }
5893 ],
5894 class: 'p5',
5895 module: 'Math'
5896 },
5897 tan: {
5898 name: 'tan',
5899 params: [
5900 {
5901 name: 'angle',
5902 description: '<p>the angle</p>\n',
5903 type: 'Number'
5904 }
5905 ],
5906 class: 'p5',
5907 module: 'Math'
5908 },
5909 degrees: {
5910 name: 'degrees',
5911 params: [
5912 {
5913 name: 'radians',
5914 description: '<p>the radians value to convert to degrees</p>\n',
5915 type: 'Number'
5916 }
5917 ],
5918 class: 'p5',
5919 module: 'Math'
5920 },
5921 radians: {
5922 name: 'radians',
5923 params: [
5924 {
5925 name: 'degrees',
5926 description: '<p>the degree value to convert to radians</p>\n',
5927 type: 'Number'
5928 }
5929 ],
5930 class: 'p5',
5931 module: 'Math'
5932 },
5933 angleMode: {
5934 name: 'angleMode',
5935 params: [
5936 {
5937 name: 'mode',
5938 description: '<p>either RADIANS or DEGREES</p>\n',
5939 type: 'Constant'
5940 }
5941 ],
5942 class: 'p5',
5943 module: 'Math'
5944 },
5945 textAlign: {
5946 name: 'textAlign',
5947 class: 'p5',
5948 module: 'Typography',
5949 overloads: [
5950 {
5951 params: [
5952 {
5953 name: 'horizAlign',
5954 description:
5955 '<p>horizontal alignment, either LEFT,\n CENTER, or RIGHT</p>\n',
5956 type: 'Constant'
5957 },
5958 {
5959 name: 'vertAlign',
5960 description:
5961 '<p>vertical alignment, either TOP,\n BOTTOM, CENTER, or BASELINE</p>\n',
5962 type: 'Constant',
5963 optional: true
5964 }
5965 ],
5966 chainable: 1
5967 },
5968 {
5969 params: []
5970 }
5971 ]
5972 },
5973 textLeading: {
5974 name: 'textLeading',
5975 class: 'p5',
5976 module: 'Typography',
5977 overloads: [
5978 {
5979 params: [
5980 {
5981 name: 'leading',
5982 description:
5983 '<p>the size in pixels for spacing between lines</p>\n',
5984 type: 'Number'
5985 }
5986 ],
5987 chainable: 1
5988 },
5989 {
5990 params: []
5991 }
5992 ]
5993 },
5994 textSize: {
5995 name: 'textSize',
5996 class: 'p5',
5997 module: 'Typography',
5998 overloads: [
5999 {
6000 params: [
6001 {
6002 name: 'theSize',
6003 description: '<p>the size of the letters in units of pixels</p>\n',
6004 type: 'Number'
6005 }
6006 ],
6007 chainable: 1
6008 },
6009 {
6010 params: []
6011 }
6012 ]
6013 },
6014 textStyle: {
6015 name: 'textStyle',
6016 class: 'p5',
6017 module: 'Typography',
6018 overloads: [
6019 {
6020 params: [
6021 {
6022 name: 'theStyle',
6023 description:
6024 '<p>styling for text, either NORMAL,\n ITALIC, BOLD or BOLDITALIC</p>\n',
6025 type: 'Constant'
6026 }
6027 ],
6028 chainable: 1
6029 },
6030 {
6031 params: []
6032 }
6033 ]
6034 },
6035 textWidth: {
6036 name: 'textWidth',
6037 params: [
6038 {
6039 name: 'theText',
6040 description: '<p>the String of characters to measure</p>\n',
6041 type: 'String'
6042 }
6043 ],
6044 class: 'p5',
6045 module: 'Typography'
6046 },
6047 textAscent: {
6048 name: 'textAscent',
6049 class: 'p5',
6050 module: 'Typography'
6051 },
6052 textDescent: {
6053 name: 'textDescent',
6054 class: 'p5',
6055 module: 'Typography'
6056 },
6057 loadFont: {
6058 name: 'loadFont',
6059 params: [
6060 {
6061 name: 'path',
6062 description: '<p>name of the file or url to load</p>\n',
6063 type: 'String'
6064 },
6065 {
6066 name: 'callback',
6067 description:
6068 '<p>function to be executed after\n <a href="#/p5/loadFont">loadFont()</a> completes</p>\n',
6069 type: 'Function',
6070 optional: true
6071 },
6072 {
6073 name: 'onError',
6074 description:
6075 '<p>function to be executed if\n an error occurs</p>\n',
6076 type: 'Function',
6077 optional: true
6078 }
6079 ],
6080 class: 'p5',
6081 module: 'Typography'
6082 },
6083 text: {
6084 name: 'text',
6085 params: [
6086 {
6087 name: 'str',
6088 description:
6089 '<p>the alphanumeric\n symbols to be displayed</p>\n',
6090 type: 'String|Object|Array|Number|Boolean'
6091 },
6092 {
6093 name: 'x',
6094 description: '<p>x-coordinate of text</p>\n',
6095 type: 'Number'
6096 },
6097 {
6098 name: 'y',
6099 description: '<p>y-coordinate of text</p>\n',
6100 type: 'Number'
6101 },
6102 {
6103 name: 'x2',
6104 description:
6105 '<p>by default, the width of the text box,\n see <a href="#/p5/rectMode">rectMode()</a> for more info</p>\n',
6106 type: 'Number',
6107 optional: true
6108 },
6109 {
6110 name: 'y2',
6111 description:
6112 '<p>by default, the height of the text box,\n see <a href="#/p5/rectMode">rectMode()</a> for more info</p>\n',
6113 type: 'Number',
6114 optional: true
6115 }
6116 ],
6117 class: 'p5',
6118 module: 'Typography'
6119 },
6120 textFont: {
6121 name: 'textFont',
6122 class: 'p5',
6123 module: 'Typography',
6124 overloads: [
6125 {
6126 params: []
6127 },
6128 {
6129 params: [
6130 {
6131 name: 'font',
6132 description:
6133 '<p>a font loaded via <a href="#/p5/loadFont">loadFont()</a>,\nor a String representing a <a href="https://mzl.la/2dOw8WD">web safe font</a>\n(a font that is generally available across all systems)</p>\n',
6134 type: 'Object|String'
6135 },
6136 {
6137 name: 'size',
6138 description: '<p>the font size to use</p>\n',
6139 type: 'Number',
6140 optional: true
6141 }
6142 ],
6143 chainable: 1
6144 }
6145 ]
6146 },
6147 append: {
6148 name: 'append',
6149 params: [
6150 {
6151 name: 'array',
6152 description: '<p>Array to append</p>\n',
6153 type: 'Array'
6154 },
6155 {
6156 name: 'value',
6157 description: '<p>to be added to the Array</p>\n',
6158 type: 'Any'
6159 }
6160 ],
6161 class: 'p5',
6162 module: 'Data'
6163 },
6164 arrayCopy: {
6165 name: 'arrayCopy',
6166 class: 'p5',
6167 module: 'Data',
6168 overloads: [
6169 {
6170 params: [
6171 {
6172 name: 'src',
6173 description: '<p>the source Array</p>\n',
6174 type: 'Array'
6175 },
6176 {
6177 name: 'srcPosition',
6178 description: '<p>starting position in the source Array</p>\n',
6179 type: 'Integer'
6180 },
6181 {
6182 name: 'dst',
6183 description: '<p>the destination Array</p>\n',
6184 type: 'Array'
6185 },
6186 {
6187 name: 'dstPosition',
6188 description: '<p>starting position in the destination Array</p>\n',
6189 type: 'Integer'
6190 },
6191 {
6192 name: 'length',
6193 description: '<p>number of Array elements to be copied</p>\n',
6194 type: 'Integer'
6195 }
6196 ]
6197 },
6198 {
6199 params: [
6200 {
6201 name: 'src',
6202 description: '',
6203 type: 'Array'
6204 },
6205 {
6206 name: 'dst',
6207 description: '',
6208 type: 'Array'
6209 },
6210 {
6211 name: 'length',
6212 description: '',
6213 type: 'Integer',
6214 optional: true
6215 }
6216 ]
6217 }
6218 ]
6219 },
6220 concat: {
6221 name: 'concat',
6222 params: [
6223 {
6224 name: 'a',
6225 description: '<p>first Array to concatenate</p>\n',
6226 type: 'Array'
6227 },
6228 {
6229 name: 'b',
6230 description: '<p>second Array to concatenate</p>\n',
6231 type: 'Array'
6232 }
6233 ],
6234 class: 'p5',
6235 module: 'Data'
6236 },
6237 reverse: {
6238 name: 'reverse',
6239 params: [
6240 {
6241 name: 'list',
6242 description: '<p>Array to reverse</p>\n',
6243 type: 'Array'
6244 }
6245 ],
6246 class: 'p5',
6247 module: 'Data'
6248 },
6249 shorten: {
6250 name: 'shorten',
6251 params: [
6252 {
6253 name: 'list',
6254 description: '<p>Array to shorten</p>\n',
6255 type: 'Array'
6256 }
6257 ],
6258 class: 'p5',
6259 module: 'Data'
6260 },
6261 shuffle: {
6262 name: 'shuffle',
6263 params: [
6264 {
6265 name: 'array',
6266 description: '<p>Array to shuffle</p>\n',
6267 type: 'Array'
6268 },
6269 {
6270 name: 'bool',
6271 description: '<p>modify passed array</p>\n',
6272 type: 'Boolean',
6273 optional: true
6274 }
6275 ],
6276 class: 'p5',
6277 module: 'Data'
6278 },
6279 sort: {
6280 name: 'sort',
6281 params: [
6282 {
6283 name: 'list',
6284 description: '<p>Array to sort</p>\n',
6285 type: 'Array'
6286 },
6287 {
6288 name: 'count',
6289 description: '<p>number of elements to sort, starting from 0</p>\n',
6290 type: 'Integer',
6291 optional: true
6292 }
6293 ],
6294 class: 'p5',
6295 module: 'Data'
6296 },
6297 splice: {
6298 name: 'splice',
6299 params: [
6300 {
6301 name: 'list',
6302 description: '<p>Array to splice into</p>\n',
6303 type: 'Array'
6304 },
6305 {
6306 name: 'value',
6307 description: '<p>value to be spliced in</p>\n',
6308 type: 'Any'
6309 },
6310 {
6311 name: 'position',
6312 description: '<p>in the array from which to insert data</p>\n',
6313 type: 'Integer'
6314 }
6315 ],
6316 class: 'p5',
6317 module: 'Data'
6318 },
6319 subset: {
6320 name: 'subset',
6321 params: [
6322 {
6323 name: 'list',
6324 description: '<p>Array to extract from</p>\n',
6325 type: 'Array'
6326 },
6327 {
6328 name: 'start',
6329 description: '<p>position to begin</p>\n',
6330 type: 'Integer'
6331 },
6332 {
6333 name: 'count',
6334 description: '<p>number of values to extract</p>\n',
6335 type: 'Integer',
6336 optional: true
6337 }
6338 ],
6339 class: 'p5',
6340 module: 'Data'
6341 },
6342 float: {
6343 name: 'float',
6344 params: [
6345 {
6346 name: 'str',
6347 description: '<p>float string to parse</p>\n',
6348 type: 'String'
6349 }
6350 ],
6351 class: 'p5',
6352 module: 'Data'
6353 },
6354 int: {
6355 name: 'int',
6356 class: 'p5',
6357 module: 'Data',
6358 overloads: [
6359 {
6360 params: [
6361 {
6362 name: 'n',
6363 description: '<p>value to parse</p>\n',
6364 type: 'String|Boolean|Number'
6365 },
6366 {
6367 name: 'radix',
6368 description: '<p>the radix to convert to (default: 10)</p>\n',
6369 type: 'Integer',
6370 optional: true
6371 }
6372 ]
6373 },
6374 {
6375 params: [
6376 {
6377 name: 'ns',
6378 description: '<p>values to parse</p>\n',
6379 type: 'Array'
6380 }
6381 ]
6382 }
6383 ]
6384 },
6385 str: {
6386 name: 'str',
6387 params: [
6388 {
6389 name: 'n',
6390 description: '<p>value to parse</p>\n',
6391 type: 'String|Boolean|Number|Array'
6392 }
6393 ],
6394 class: 'p5',
6395 module: 'Data'
6396 },
6397 byte: {
6398 name: 'byte',
6399 class: 'p5',
6400 module: 'Data',
6401 overloads: [
6402 {
6403 params: [
6404 {
6405 name: 'n',
6406 description: '<p>value to parse</p>\n',
6407 type: 'String|Boolean|Number'
6408 }
6409 ]
6410 },
6411 {
6412 params: [
6413 {
6414 name: 'ns',
6415 description: '<p>values to parse</p>\n',
6416 type: 'Array'
6417 }
6418 ]
6419 }
6420 ]
6421 },
6422 char: {
6423 name: 'char',
6424 class: 'p5',
6425 module: 'Data',
6426 overloads: [
6427 {
6428 params: [
6429 {
6430 name: 'n',
6431 description: '<p>value to parse</p>\n',
6432 type: 'String|Number'
6433 }
6434 ]
6435 },
6436 {
6437 params: [
6438 {
6439 name: 'ns',
6440 description: '<p>values to parse</p>\n',
6441 type: 'Array'
6442 }
6443 ]
6444 }
6445 ]
6446 },
6447 unchar: {
6448 name: 'unchar',
6449 class: 'p5',
6450 module: 'Data',
6451 overloads: [
6452 {
6453 params: [
6454 {
6455 name: 'n',
6456 description: '<p>value to parse</p>\n',
6457 type: 'String'
6458 }
6459 ]
6460 },
6461 {
6462 params: [
6463 {
6464 name: 'ns',
6465 description: '<p>values to parse</p>\n',
6466 type: 'Array'
6467 }
6468 ]
6469 }
6470 ]
6471 },
6472 hex: {
6473 name: 'hex',
6474 class: 'p5',
6475 module: 'Data',
6476 overloads: [
6477 {
6478 params: [
6479 {
6480 name: 'n',
6481 description: '<p>value to parse</p>\n',
6482 type: 'Number'
6483 },
6484 {
6485 name: 'digits',
6486 description: '',
6487 type: 'Number',
6488 optional: true
6489 }
6490 ]
6491 },
6492 {
6493 params: [
6494 {
6495 name: 'ns',
6496 description: '<p>array of values to parse</p>\n',
6497 type: 'Number[]'
6498 },
6499 {
6500 name: 'digits',
6501 description: '',
6502 type: 'Number',
6503 optional: true
6504 }
6505 ]
6506 }
6507 ]
6508 },
6509 unhex: {
6510 name: 'unhex',
6511 class: 'p5',
6512 module: 'Data',
6513 overloads: [
6514 {
6515 params: [
6516 {
6517 name: 'n',
6518 description: '<p>value to parse</p>\n',
6519 type: 'String'
6520 }
6521 ]
6522 },
6523 {
6524 params: [
6525 {
6526 name: 'ns',
6527 description: '<p>values to parse</p>\n',
6528 type: 'Array'
6529 }
6530 ]
6531 }
6532 ]
6533 },
6534 join: {
6535 name: 'join',
6536 params: [
6537 {
6538 name: 'list',
6539 description: '<p>array of Strings to be joined</p>\n',
6540 type: 'Array'
6541 },
6542 {
6543 name: 'separator',
6544 description: '<p>String to be placed between each item</p>\n',
6545 type: 'String'
6546 }
6547 ],
6548 class: 'p5',
6549 module: 'Data'
6550 },
6551 match: {
6552 name: 'match',
6553 params: [
6554 {
6555 name: 'str',
6556 description: '<p>the String to be searched</p>\n',
6557 type: 'String'
6558 },
6559 {
6560 name: 'regexp',
6561 description: '<p>the regexp to be used for matching</p>\n',
6562 type: 'String'
6563 }
6564 ],
6565 class: 'p5',
6566 module: 'Data'
6567 },
6568 matchAll: {
6569 name: 'matchAll',
6570 params: [
6571 {
6572 name: 'str',
6573 description: '<p>the String to be searched</p>\n',
6574 type: 'String'
6575 },
6576 {
6577 name: 'regexp',
6578 description: '<p>the regexp to be used for matching</p>\n',
6579 type: 'String'
6580 }
6581 ],
6582 class: 'p5',
6583 module: 'Data'
6584 },
6585 nf: {
6586 name: 'nf',
6587 class: 'p5',
6588 module: 'Data',
6589 overloads: [
6590 {
6591 params: [
6592 {
6593 name: 'num',
6594 description: '<p>the Number to format</p>\n',
6595 type: 'Number|String'
6596 },
6597 {
6598 name: 'left',
6599 description:
6600 '<p>number of digits to the left of the\n decimal point</p>\n',
6601 type: 'Integer|String',
6602 optional: true
6603 },
6604 {
6605 name: 'right',
6606 description:
6607 '<p>number of digits to the right of the\n decimal point</p>\n',
6608 type: 'Integer|String',
6609 optional: true
6610 }
6611 ]
6612 },
6613 {
6614 params: [
6615 {
6616 name: 'nums',
6617 description: '<p>the Numbers to format</p>\n',
6618 type: 'Array'
6619 },
6620 {
6621 name: 'left',
6622 description: '',
6623 type: 'Integer|String',
6624 optional: true
6625 },
6626 {
6627 name: 'right',
6628 description: '',
6629 type: 'Integer|String',
6630 optional: true
6631 }
6632 ]
6633 }
6634 ]
6635 },
6636 nfc: {
6637 name: 'nfc',
6638 class: 'p5',
6639 module: 'Data',
6640 overloads: [
6641 {
6642 params: [
6643 {
6644 name: 'num',
6645 description: '<p>the Number to format</p>\n',
6646 type: 'Number|String'
6647 },
6648 {
6649 name: 'right',
6650 description:
6651 '<p>number of digits to the right of the\n decimal point</p>\n',
6652 type: 'Integer|String',
6653 optional: true
6654 }
6655 ]
6656 },
6657 {
6658 params: [
6659 {
6660 name: 'nums',
6661 description: '<p>the Numbers to format</p>\n',
6662 type: 'Array'
6663 },
6664 {
6665 name: 'right',
6666 description: '',
6667 type: 'Integer|String',
6668 optional: true
6669 }
6670 ]
6671 }
6672 ]
6673 },
6674 nfp: {
6675 name: 'nfp',
6676 class: 'p5',
6677 module: 'Data',
6678 overloads: [
6679 {
6680 params: [
6681 {
6682 name: 'num',
6683 description: '<p>the Number to format</p>\n',
6684 type: 'Number'
6685 },
6686 {
6687 name: 'left',
6688 description:
6689 '<p>number of digits to the left of the decimal\n point</p>\n',
6690 type: 'Integer',
6691 optional: true
6692 },
6693 {
6694 name: 'right',
6695 description:
6696 '<p>number of digits to the right of the\n decimal point</p>\n',
6697 type: 'Integer',
6698 optional: true
6699 }
6700 ]
6701 },
6702 {
6703 params: [
6704 {
6705 name: 'nums',
6706 description: '<p>the Numbers to format</p>\n',
6707 type: 'Number[]'
6708 },
6709 {
6710 name: 'left',
6711 description: '',
6712 type: 'Integer',
6713 optional: true
6714 },
6715 {
6716 name: 'right',
6717 description: '',
6718 type: 'Integer',
6719 optional: true
6720 }
6721 ]
6722 }
6723 ]
6724 },
6725 nfs: {
6726 name: 'nfs',
6727 class: 'p5',
6728 module: 'Data',
6729 overloads: [
6730 {
6731 params: [
6732 {
6733 name: 'num',
6734 description: '<p>the Number to format</p>\n',
6735 type: 'Number'
6736 },
6737 {
6738 name: 'left',
6739 description:
6740 '<p>number of digits to the left of the decimal\n point</p>\n',
6741 type: 'Integer',
6742 optional: true
6743 },
6744 {
6745 name: 'right',
6746 description:
6747 '<p>number of digits to the right of the\n decimal point</p>\n',
6748 type: 'Integer',
6749 optional: true
6750 }
6751 ]
6752 },
6753 {
6754 params: [
6755 {
6756 name: 'nums',
6757 description: '<p>the Numbers to format</p>\n',
6758 type: 'Array'
6759 },
6760 {
6761 name: 'left',
6762 description: '',
6763 type: 'Integer',
6764 optional: true
6765 },
6766 {
6767 name: 'right',
6768 description: '',
6769 type: 'Integer',
6770 optional: true
6771 }
6772 ]
6773 }
6774 ]
6775 },
6776 split: {
6777 name: 'split',
6778 params: [
6779 {
6780 name: 'value',
6781 description: '<p>the String to be split</p>\n',
6782 type: 'String'
6783 },
6784 {
6785 name: 'delim',
6786 description: '<p>the String used to separate the data</p>\n',
6787 type: 'String'
6788 }
6789 ],
6790 class: 'p5',
6791 module: 'Data'
6792 },
6793 splitTokens: {
6794 name: 'splitTokens',
6795 params: [
6796 {
6797 name: 'value',
6798 description: '<p>the String to be split</p>\n',
6799 type: 'String'
6800 },
6801 {
6802 name: 'delim',
6803 description:
6804 '<p>list of individual Strings that will be used as\n separators</p>\n',
6805 type: 'String',
6806 optional: true
6807 }
6808 ],
6809 class: 'p5',
6810 module: 'Data'
6811 },
6812 trim: {
6813 name: 'trim',
6814 class: 'p5',
6815 module: 'Data',
6816 overloads: [
6817 {
6818 params: [
6819 {
6820 name: 'str',
6821 description: '<p>a String to be trimmed</p>\n',
6822 type: 'String'
6823 }
6824 ]
6825 },
6826 {
6827 params: [
6828 {
6829 name: 'strs',
6830 description: '<p>an Array of Strings to be trimmed</p>\n',
6831 type: 'Array'
6832 }
6833 ]
6834 }
6835 ]
6836 },
6837 day: {
6838 name: 'day',
6839 class: 'p5',
6840 module: 'IO'
6841 },
6842 hour: {
6843 name: 'hour',
6844 class: 'p5',
6845 module: 'IO'
6846 },
6847 minute: {
6848 name: 'minute',
6849 class: 'p5',
6850 module: 'IO'
6851 },
6852 millis: {
6853 name: 'millis',
6854 class: 'p5',
6855 module: 'IO'
6856 },
6857 month: {
6858 name: 'month',
6859 class: 'p5',
6860 module: 'IO'
6861 },
6862 second: {
6863 name: 'second',
6864 class: 'p5',
6865 module: 'IO'
6866 },
6867 year: {
6868 name: 'year',
6869 class: 'p5',
6870 module: 'IO'
6871 },
6872 plane: {
6873 name: 'plane',
6874 params: [
6875 {
6876 name: 'width',
6877 description: '<p>width of the plane</p>\n',
6878 type: 'Number',
6879 optional: true
6880 },
6881 {
6882 name: 'height',
6883 description: '<p>height of the plane</p>\n',
6884 type: 'Number',
6885 optional: true
6886 },
6887 {
6888 name: 'detailX',
6889 description:
6890 '<p>Optional number of triangle\n subdivisions in x-dimension</p>\n',
6891 type: 'Integer',
6892 optional: true
6893 },
6894 {
6895 name: 'detailY',
6896 description:
6897 '<p>Optional number of triangle\n subdivisions in y-dimension</p>\n',
6898 type: 'Integer',
6899 optional: true
6900 }
6901 ],
6902 class: 'p5',
6903 module: 'Shape'
6904 },
6905 box: {
6906 name: 'box',
6907 params: [
6908 {
6909 name: 'width',
6910 description: '<p>width of the box</p>\n',
6911 type: 'Number',
6912 optional: true
6913 },
6914 {
6915 name: 'Height',
6916 description: '<p>height of the box</p>\n',
6917 type: 'Number',
6918 optional: true
6919 },
6920 {
6921 name: 'depth',
6922 description: '<p>depth of the box</p>\n',
6923 type: 'Number',
6924 optional: true
6925 },
6926 {
6927 name: 'detailX',
6928 description:
6929 '<p>Optional number of triangle\n subdivisions in x-dimension</p>\n',
6930 type: 'Integer',
6931 optional: true
6932 },
6933 {
6934 name: 'detailY',
6935 description:
6936 '<p>Optional number of triangle\n subdivisions in y-dimension</p>\n',
6937 type: 'Integer',
6938 optional: true
6939 }
6940 ],
6941 class: 'p5',
6942 module: 'Shape'
6943 },
6944 sphere: {
6945 name: 'sphere',
6946 params: [
6947 {
6948 name: 'radius',
6949 description: '<p>radius of circle</p>\n',
6950 type: 'Number',
6951 optional: true
6952 },
6953 {
6954 name: 'detailX',
6955 description: '<p>optional number of subdivisions in x-dimension</p>\n',
6956 type: 'Integer',
6957 optional: true
6958 },
6959 {
6960 name: 'detailY',
6961 description: '<p>optional number of subdivisions in y-dimension</p>\n',
6962 type: 'Integer',
6963 optional: true
6964 }
6965 ],
6966 class: 'p5',
6967 module: 'Shape'
6968 },
6969 cylinder: {
6970 name: 'cylinder',
6971 params: [
6972 {
6973 name: 'radius',
6974 description: '<p>radius of the surface</p>\n',
6975 type: 'Number',
6976 optional: true
6977 },
6978 {
6979 name: 'height',
6980 description: '<p>height of the cylinder</p>\n',
6981 type: 'Number',
6982 optional: true
6983 },
6984 {
6985 name: 'detailX',
6986 description:
6987 '<p>number of subdivisions in x-dimension;\n default is 24</p>\n',
6988 type: 'Integer',
6989 optional: true
6990 },
6991 {
6992 name: 'detailY',
6993 description:
6994 '<p>number of subdivisions in y-dimension;\n default is 1</p>\n',
6995 type: 'Integer',
6996 optional: true
6997 },
6998 {
6999 name: 'bottomCap',
7000 description: '<p>whether to draw the bottom of the cylinder</p>\n',
7001 type: 'Boolean',
7002 optional: true
7003 },
7004 {
7005 name: 'topCap',
7006 description: '<p>whether to draw the top of the cylinder</p>\n',
7007 type: 'Boolean',
7008 optional: true
7009 }
7010 ],
7011 class: 'p5',
7012 module: 'Shape'
7013 },
7014 cone: {
7015 name: 'cone',
7016 params: [
7017 {
7018 name: 'radius',
7019 description: '<p>radius of the bottom surface</p>\n',
7020 type: 'Number',
7021 optional: true
7022 },
7023 {
7024 name: 'height',
7025 description: '<p>height of the cone</p>\n',
7026 type: 'Number',
7027 optional: true
7028 },
7029 {
7030 name: 'detailX',
7031 description:
7032 '<p>number of segments,\n the more segments the smoother geometry\n default is 24</p>\n',
7033 type: 'Integer',
7034 optional: true
7035 },
7036 {
7037 name: 'detailY',
7038 description:
7039 '<p>number of segments,\n the more segments the smoother geometry\n default is 1</p>\n',
7040 type: 'Integer',
7041 optional: true
7042 },
7043 {
7044 name: 'cap',
7045 description: '<p>whether to draw the base of the cone</p>\n',
7046 type: 'Boolean',
7047 optional: true
7048 }
7049 ],
7050 class: 'p5',
7051 module: 'Shape'
7052 },
7053 ellipsoid: {
7054 name: 'ellipsoid',
7055 params: [
7056 {
7057 name: 'radiusx',
7058 description: '<p>x-radius of ellipsoid</p>\n',
7059 type: 'Number',
7060 optional: true
7061 },
7062 {
7063 name: 'radiusy',
7064 description: '<p>y-radius of ellipsoid</p>\n',
7065 type: 'Number',
7066 optional: true
7067 },
7068 {
7069 name: 'radiusz',
7070 description: '<p>z-radius of ellipsoid</p>\n',
7071 type: 'Number',
7072 optional: true
7073 },
7074 {
7075 name: 'detailX',
7076 description:
7077 '<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',
7078 type: 'Integer',
7079 optional: true
7080 },
7081 {
7082 name: 'detailY',
7083 description:
7084 '<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',
7085 type: 'Integer',
7086 optional: true
7087 }
7088 ],
7089 class: 'p5',
7090 module: 'Shape'
7091 },
7092 torus: {
7093 name: 'torus',
7094 params: [
7095 {
7096 name: 'radius',
7097 description: '<p>radius of the whole ring</p>\n',
7098 type: 'Number',
7099 optional: true
7100 },
7101 {
7102 name: 'tubeRadius',
7103 description: '<p>radius of the tube</p>\n',
7104 type: 'Number',
7105 optional: true
7106 },
7107 {
7108 name: 'detailX',
7109 description:
7110 '<p>number of segments in x-dimension,\n the more segments the smoother geometry\n default is 24</p>\n',
7111 type: 'Integer',
7112 optional: true
7113 },
7114 {
7115 name: 'detailY',
7116 description:
7117 '<p>number of segments in y-dimension,\n the more segments the smoother geometry\n default is 16</p>\n',
7118 type: 'Integer',
7119 optional: true
7120 }
7121 ],
7122 class: 'p5',
7123 module: 'Shape'
7124 },
7125 orbitControl: {
7126 name: 'orbitControl',
7127 params: [
7128 {
7129 name: 'sensitivityX',
7130 description: '<p>sensitivity to mouse movement along X axis</p>\n',
7131 type: 'Number',
7132 optional: true
7133 },
7134 {
7135 name: 'sensitivityY',
7136 description: '<p>sensitivity to mouse movement along Y axis</p>\n',
7137 type: 'Number',
7138 optional: true
7139 },
7140 {
7141 name: 'sensitivityZ',
7142 description: '<p>sensitivity to scroll movement along Z axis</p>\n',
7143 type: 'Number',
7144 optional: true
7145 }
7146 ],
7147 class: 'p5',
7148 module: 'Lights, Camera'
7149 },
7150 debugMode: {
7151 name: 'debugMode',
7152 class: 'p5',
7153 module: 'Lights, Camera',
7154 overloads: [
7155 {
7156 params: []
7157 },
7158 {
7159 params: [
7160 {
7161 name: 'mode',
7162 description: '<p>either GRID or AXES</p>\n',
7163 type: 'Constant'
7164 }
7165 ]
7166 },
7167 {
7168 params: [
7169 {
7170 name: 'mode',
7171 description: '',
7172 type: 'Constant'
7173 },
7174 {
7175 name: 'gridSize',
7176 description: '<p>size of one side of the grid</p>\n',
7177 type: 'Number',
7178 optional: true
7179 },
7180 {
7181 name: 'gridDivisions',
7182 description: '<p>number of divisions in the grid</p>\n',
7183 type: 'Number',
7184 optional: true
7185 },
7186 {
7187 name: 'xOff',
7188 description: '<p>X axis offset from origin (0,0,0)</p>\n',
7189 type: 'Number',
7190 optional: true
7191 },
7192 {
7193 name: 'yOff',
7194 description: '<p>Y axis offset from origin (0,0,0)</p>\n',
7195 type: 'Number',
7196 optional: true
7197 },
7198 {
7199 name: 'zOff',
7200 description: '<p>Z axis offset from origin (0,0,0)</p>\n',
7201 type: 'Number',
7202 optional: true
7203 }
7204 ]
7205 },
7206 {
7207 params: [
7208 {
7209 name: 'mode',
7210 description: '',
7211 type: 'Constant'
7212 },
7213 {
7214 name: 'axesSize',
7215 description: '<p>size of axes icon</p>\n',
7216 type: 'Number',
7217 optional: true
7218 },
7219 {
7220 name: 'xOff',
7221 description: '',
7222 type: 'Number',
7223 optional: true
7224 },
7225 {
7226 name: 'yOff',
7227 description: '',
7228 type: 'Number',
7229 optional: true
7230 },
7231 {
7232 name: 'zOff',
7233 description: '',
7234 type: 'Number',
7235 optional: true
7236 }
7237 ]
7238 },
7239 {
7240 params: [
7241 {
7242 name: 'gridSize',
7243 description: '',
7244 type: 'Number',
7245 optional: true
7246 },
7247 {
7248 name: 'gridDivisions',
7249 description: '',
7250 type: 'Number',
7251 optional: true
7252 },
7253 {
7254 name: 'gridXOff',
7255 description: '',
7256 type: 'Number',
7257 optional: true
7258 },
7259 {
7260 name: 'gridYOff',
7261 description: '',
7262 type: 'Number',
7263 optional: true
7264 },
7265 {
7266 name: 'gridZOff',
7267 description: '',
7268 type: 'Number',
7269 optional: true
7270 },
7271 {
7272 name: 'axesSize',
7273 description: '',
7274 type: 'Number',
7275 optional: true
7276 },
7277 {
7278 name: 'axesXOff',
7279 description: '',
7280 type: 'Number',
7281 optional: true
7282 },
7283 {
7284 name: 'axesYOff',
7285 description: '',
7286 type: 'Number',
7287 optional: true
7288 },
7289 {
7290 name: 'axesZOff',
7291 description: '',
7292 type: 'Number',
7293 optional: true
7294 }
7295 ]
7296 }
7297 ]
7298 },
7299 noDebugMode: {
7300 name: 'noDebugMode',
7301 class: 'p5',
7302 module: 'Lights, Camera'
7303 },
7304 ambientLight: {
7305 name: 'ambientLight',
7306 class: 'p5',
7307 module: 'Lights, Camera',
7308 overloads: [
7309 {
7310 params: [
7311 {
7312 name: 'v1',
7313 description:
7314 '<p>red or hue value relative to\n the current color range</p>\n',
7315 type: 'Number'
7316 },
7317 {
7318 name: 'v2',
7319 description:
7320 '<p>green or saturation value\n relative to the current color range</p>\n',
7321 type: 'Number'
7322 },
7323 {
7324 name: 'v3',
7325 description:
7326 '<p>blue or brightness value\n relative to the current color range</p>\n',
7327 type: 'Number'
7328 },
7329 {
7330 name: 'alpha',
7331 description: '<p>the alpha value</p>\n',
7332 type: 'Number',
7333 optional: true
7334 }
7335 ],
7336 chainable: 1
7337 },
7338 {
7339 params: [
7340 {
7341 name: 'value',
7342 description: '<p>a color string</p>\n',
7343 type: 'String'
7344 }
7345 ],
7346 chainable: 1
7347 },
7348 {
7349 params: [
7350 {
7351 name: 'gray',
7352 description: '<p>a gray value</p>\n',
7353 type: 'Number'
7354 },
7355 {
7356 name: 'alpha',
7357 description: '',
7358 type: 'Number',
7359 optional: true
7360 }
7361 ],
7362 chainable: 1
7363 },
7364 {
7365 params: [
7366 {
7367 name: 'values',
7368 description:
7369 '<p>an array containing the red,green,blue &\n and alpha components of the color</p>\n',
7370 type: 'Number[]'
7371 }
7372 ],
7373 chainable: 1
7374 },
7375 {
7376 params: [
7377 {
7378 name: 'color',
7379 description: '<p>the ambient light color</p>\n',
7380 type: 'p5.Color'
7381 }
7382 ],
7383 chainable: 1
7384 }
7385 ]
7386 },
7387 specularColor: {
7388 name: 'specularColor',
7389 class: 'p5',
7390 module: 'Lights, Camera',
7391 overloads: [
7392 {
7393 params: [
7394 {
7395 name: 'v1',
7396 description:
7397 '<p>red or hue value relative to\n the current color range</p>\n',
7398 type: 'Number'
7399 },
7400 {
7401 name: 'v2',
7402 description:
7403 '<p>green or saturation value\n relative to the current color range</p>\n',
7404 type: 'Number'
7405 },
7406 {
7407 name: 'v3',
7408 description:
7409 '<p>blue or brightness value\n relative to the current color range</p>\n',
7410 type: 'Number'
7411 }
7412 ],
7413 chainable: 1
7414 },
7415 {
7416 params: [
7417 {
7418 name: 'value',
7419 description: '<p>a color string</p>\n',
7420 type: 'String'
7421 }
7422 ],
7423 chainable: 1
7424 },
7425 {
7426 params: [
7427 {
7428 name: 'gray',
7429 description: '<p>a gray value</p>\n',
7430 type: 'Number'
7431 }
7432 ],
7433 chainable: 1
7434 },
7435 {
7436 params: [
7437 {
7438 name: 'values',
7439 description:
7440 '<p>an array containing the red,green,blue &\n and alpha components of the color</p>\n',
7441 type: 'Number[]'
7442 }
7443 ],
7444 chainable: 1
7445 },
7446 {
7447 params: [
7448 {
7449 name: 'color',
7450 description: '<p>the ambient light color</p>\n',
7451 type: 'p5.Color'
7452 }
7453 ],
7454 chainable: 1
7455 }
7456 ]
7457 },
7458 directionalLight: {
7459 name: 'directionalLight',
7460 class: 'p5',
7461 module: 'Lights, Camera',
7462 overloads: [
7463 {
7464 params: [
7465 {
7466 name: 'v1',
7467 description:
7468 '<p>red or hue value (depending on the current\ncolor mode),</p>\n',
7469 type: 'Number'
7470 },
7471 {
7472 name: 'v2',
7473 description: '<p>green or saturation value</p>\n',
7474 type: 'Number'
7475 },
7476 {
7477 name: 'v3',
7478 description: '<p>blue or brightness value</p>\n',
7479 type: 'Number'
7480 },
7481 {
7482 name: 'position',
7483 description: '<p>the direction of the light</p>\n',
7484 type: 'p5.Vector'
7485 }
7486 ],
7487 chainable: 1
7488 },
7489 {
7490 params: [
7491 {
7492 name: 'color',
7493 description:
7494 '<p>color Array, CSS color string,\n or <a href="#/p5.Color">p5.Color</a> value</p>\n',
7495 type: 'Number[]|String|p5.Color'
7496 },
7497 {
7498 name: 'x',
7499 description: '<p>x axis direction</p>\n',
7500 type: 'Number'
7501 },
7502 {
7503 name: 'y',
7504 description: '<p>y axis direction</p>\n',
7505 type: 'Number'
7506 },
7507 {
7508 name: 'z',
7509 description: '<p>z axis direction</p>\n',
7510 type: 'Number'
7511 }
7512 ],
7513 chainable: 1
7514 },
7515 {
7516 params: [
7517 {
7518 name: 'color',
7519 description: '',
7520 type: 'Number[]|String|p5.Color'
7521 },
7522 {
7523 name: 'position',
7524 description: '',
7525 type: 'p5.Vector'
7526 }
7527 ],
7528 chainable: 1
7529 },
7530 {
7531 params: [
7532 {
7533 name: 'v1',
7534 description: '',
7535 type: 'Number'
7536 },
7537 {
7538 name: 'v2',
7539 description: '',
7540 type: 'Number'
7541 },
7542 {
7543 name: 'v3',
7544 description: '',
7545 type: 'Number'
7546 },
7547 {
7548 name: 'x',
7549 description: '',
7550 type: 'Number'
7551 },
7552 {
7553 name: 'y',
7554 description: '',
7555 type: 'Number'
7556 },
7557 {
7558 name: 'z',
7559 description: '',
7560 type: 'Number'
7561 }
7562 ],
7563 chainable: 1
7564 }
7565 ]
7566 },
7567 pointLight: {
7568 name: 'pointLight',
7569 class: 'p5',
7570 module: 'Lights, Camera',
7571 overloads: [
7572 {
7573 params: [
7574 {
7575 name: 'v1',
7576 description:
7577 '<p>red or hue value (depending on the current\ncolor mode),</p>\n',
7578 type: 'Number'
7579 },
7580 {
7581 name: 'v2',
7582 description: '<p>green or saturation value</p>\n',
7583 type: 'Number'
7584 },
7585 {
7586 name: 'v3',
7587 description: '<p>blue or brightness value</p>\n',
7588 type: 'Number'
7589 },
7590 {
7591 name: 'x',
7592 description: '<p>x axis position</p>\n',
7593 type: 'Number'
7594 },
7595 {
7596 name: 'y',
7597 description: '<p>y axis position</p>\n',
7598 type: 'Number'
7599 },
7600 {
7601 name: 'z',
7602 description: '<p>z axis position</p>\n',
7603 type: 'Number'
7604 }
7605 ],
7606 chainable: 1
7607 },
7608 {
7609 params: [
7610 {
7611 name: 'v1',
7612 description: '',
7613 type: 'Number'
7614 },
7615 {
7616 name: 'v2',
7617 description: '',
7618 type: 'Number'
7619 },
7620 {
7621 name: 'v3',
7622 description: '',
7623 type: 'Number'
7624 },
7625 {
7626 name: 'position',
7627 description: '<p>the position of the light</p>\n',
7628 type: 'p5.Vector'
7629 }
7630 ],
7631 chainable: 1
7632 },
7633 {
7634 params: [
7635 {
7636 name: 'color',
7637 description:
7638 '<p>color Array, CSS color string,\nor <a href="#/p5.Color">p5.Color</a> value</p>\n',
7639 type: 'Number[]|String|p5.Color'
7640 },
7641 {
7642 name: 'x',
7643 description: '',
7644 type: 'Number'
7645 },
7646 {
7647 name: 'y',
7648 description: '',
7649 type: 'Number'
7650 },
7651 {
7652 name: 'z',
7653 description: '',
7654 type: 'Number'
7655 }
7656 ],
7657 chainable: 1
7658 },
7659 {
7660 params: [
7661 {
7662 name: 'color',
7663 description: '',
7664 type: 'Number[]|String|p5.Color'
7665 },
7666 {
7667 name: 'position',
7668 description: '',
7669 type: 'p5.Vector'
7670 }
7671 ],
7672 chainable: 1
7673 }
7674 ]
7675 },
7676 lights: {
7677 name: 'lights',
7678 class: 'p5',
7679 module: 'Lights, Camera'
7680 },
7681 lightFalloff: {
7682 name: 'lightFalloff',
7683 params: [
7684 {
7685 name: 'constant',
7686 description: '<p>constant value for determining falloff</p>\n',
7687 type: 'Number'
7688 },
7689 {
7690 name: 'linear',
7691 description: '<p>linear value for determining falloff</p>\n',
7692 type: 'Number'
7693 },
7694 {
7695 name: 'quadratic',
7696 description: '<p>quadratic value for determining falloff</p>\n',
7697 type: 'Number'
7698 }
7699 ],
7700 class: 'p5',
7701 module: 'Lights, Camera'
7702 },
7703 spotLight: {
7704 name: 'spotLight',
7705 class: 'p5',
7706 module: 'Lights, Camera',
7707 overloads: [
7708 {
7709 params: [
7710 {
7711 name: 'v1',
7712 description:
7713 '<p>red or hue value (depending on the current\ncolor mode),</p>\n',
7714 type: 'Number'
7715 },
7716 {
7717 name: 'v2',
7718 description: '<p>green or saturation value</p>\n',
7719 type: 'Number'
7720 },
7721 {
7722 name: 'v3',
7723 description: '<p>blue or brightness value</p>\n',
7724 type: 'Number'
7725 },
7726 {
7727 name: 'x',
7728 description: '<p>x axis position</p>\n',
7729 type: 'Number'
7730 },
7731 {
7732 name: 'y',
7733 description: '<p>y axis position</p>\n',
7734 type: 'Number'
7735 },
7736 {
7737 name: 'z',
7738 description: '<p>z axis position</p>\n',
7739 type: 'Number'
7740 },
7741 {
7742 name: 'rx',
7743 description: '<p>x axis direction of light</p>\n',
7744 type: 'Number'
7745 },
7746 {
7747 name: 'ry',
7748 description: '<p>y axis direction of light</p>\n',
7749 type: 'Number'
7750 },
7751 {
7752 name: 'rz',
7753 description: '<p>z axis direction of light</p>\n',
7754 type: 'Number'
7755 },
7756 {
7757 name: 'angle',
7758 description:
7759 '<p>optional parameter for angle. Defaults to PI/3</p>\n',
7760 type: 'Number',
7761 optional: true
7762 },
7763 {
7764 name: 'conc',
7765 description:
7766 '<p>optional parameter for concentration. Defaults to 100</p>\n',
7767 type: 'Number',
7768 optional: true
7769 }
7770 ],
7771 chainable: 1
7772 },
7773 {
7774 params: [
7775 {
7776 name: 'color',
7777 description:
7778 '<p>color Array, CSS color string,\nor <a href="#/p5.Color">p5.Color</a> value</p>\n',
7779 type: 'Number[]|String|p5.Color'
7780 },
7781 {
7782 name: 'position',
7783 description: '<p>the position of the light</p>\n',
7784 type: 'p5.Vector'
7785 },
7786 {
7787 name: 'direction',
7788 description: '<p>the direction of the light</p>\n',
7789 type: 'p5.Vector'
7790 },
7791 {
7792 name: 'angle',
7793 description: '',
7794 type: 'Number',
7795 optional: true
7796 },
7797 {
7798 name: 'conc',
7799 description: '',
7800 type: 'Number',
7801 optional: true
7802 }
7803 ]
7804 },
7805 {
7806 params: [
7807 {
7808 name: 'v1',
7809 description: '',
7810 type: 'Number'
7811 },
7812 {
7813 name: 'v2',
7814 description: '',
7815 type: 'Number'
7816 },
7817 {
7818 name: 'v3',
7819 description: '',
7820 type: 'Number'
7821 },
7822 {
7823 name: 'position',
7824 description: '',
7825 type: 'p5.Vector'
7826 },
7827 {
7828 name: 'direction',
7829 description: '',
7830 type: 'p5.Vector'
7831 },
7832 {
7833 name: 'angle',
7834 description: '',
7835 type: 'Number',
7836 optional: true
7837 },
7838 {
7839 name: 'conc',
7840 description: '',
7841 type: 'Number',
7842 optional: true
7843 }
7844 ]
7845 },
7846 {
7847 params: [
7848 {
7849 name: 'color',
7850 description: '',
7851 type: 'Number[]|String|p5.Color'
7852 },
7853 {
7854 name: 'x',
7855 description: '',
7856 type: 'Number'
7857 },
7858 {
7859 name: 'y',
7860 description: '',
7861 type: 'Number'
7862 },
7863 {
7864 name: 'z',
7865 description: '',
7866 type: 'Number'
7867 },
7868 {
7869 name: 'direction',
7870 description: '',
7871 type: 'p5.Vector'
7872 },
7873 {
7874 name: 'angle',
7875 description: '',
7876 type: 'Number',
7877 optional: true
7878 },
7879 {
7880 name: 'conc',
7881 description: '',
7882 type: 'Number',
7883 optional: true
7884 }
7885 ]
7886 },
7887 {
7888 params: [
7889 {
7890 name: 'color',
7891 description: '',
7892 type: 'Number[]|String|p5.Color'
7893 },
7894 {
7895 name: 'position',
7896 description: '',
7897 type: 'p5.Vector'
7898 },
7899 {
7900 name: 'rx',
7901 description: '',
7902 type: 'Number'
7903 },
7904 {
7905 name: 'ry',
7906 description: '',
7907 type: 'Number'
7908 },
7909 {
7910 name: 'rz',
7911 description: '',
7912 type: 'Number'
7913 },
7914 {
7915 name: 'angle',
7916 description: '',
7917 type: 'Number',
7918 optional: true
7919 },
7920 {
7921 name: 'conc',
7922 description: '',
7923 type: 'Number',
7924 optional: true
7925 }
7926 ]
7927 },
7928 {
7929 params: [
7930 {
7931 name: 'v1',
7932 description: '',
7933 type: 'Number'
7934 },
7935 {
7936 name: 'v2',
7937 description: '',
7938 type: 'Number'
7939 },
7940 {
7941 name: 'v3',
7942 description: '',
7943 type: 'Number'
7944 },
7945 {
7946 name: 'x',
7947 description: '',
7948 type: 'Number'
7949 },
7950 {
7951 name: 'y',
7952 description: '',
7953 type: 'Number'
7954 },
7955 {
7956 name: 'z',
7957 description: '',
7958 type: 'Number'
7959 },
7960 {
7961 name: 'direction',
7962 description: '',
7963 type: 'p5.Vector'
7964 },
7965 {
7966 name: 'angle',
7967 description: '',
7968 type: 'Number',
7969 optional: true
7970 },
7971 {
7972 name: 'conc',
7973 description: '',
7974 type: 'Number',
7975 optional: true
7976 }
7977 ]
7978 },
7979 {
7980 params: [
7981 {
7982 name: 'v1',
7983 description: '',
7984 type: 'Number'
7985 },
7986 {
7987 name: 'v2',
7988 description: '',
7989 type: 'Number'
7990 },
7991 {
7992 name: 'v3',
7993 description: '',
7994 type: 'Number'
7995 },
7996 {
7997 name: 'position',
7998 description: '',
7999 type: 'p5.Vector'
8000 },
8001 {
8002 name: 'rx',
8003 description: '',
8004 type: 'Number'
8005 },
8006 {
8007 name: 'ry',
8008 description: '',
8009 type: 'Number'
8010 },
8011 {
8012 name: 'rz',
8013 description: '',
8014 type: 'Number'
8015 },
8016 {
8017 name: 'angle',
8018 description: '',
8019 type: 'Number',
8020 optional: true
8021 },
8022 {
8023 name: 'conc',
8024 description: '',
8025 type: 'Number',
8026 optional: true
8027 }
8028 ]
8029 },
8030 {
8031 params: [
8032 {
8033 name: 'color',
8034 description: '',
8035 type: 'Number[]|String|p5.Color'
8036 },
8037 {
8038 name: 'x',
8039 description: '',
8040 type: 'Number'
8041 },
8042 {
8043 name: 'y',
8044 description: '',
8045 type: 'Number'
8046 },
8047 {
8048 name: 'z',
8049 description: '',
8050 type: 'Number'
8051 },
8052 {
8053 name: 'rx',
8054 description: '',
8055 type: 'Number'
8056 },
8057 {
8058 name: 'ry',
8059 description: '',
8060 type: 'Number'
8061 },
8062 {
8063 name: 'rz',
8064 description: '',
8065 type: 'Number'
8066 },
8067 {
8068 name: 'angle',
8069 description: '',
8070 type: 'Number',
8071 optional: true
8072 },
8073 {
8074 name: 'conc',
8075 description: '',
8076 type: 'Number',
8077 optional: true
8078 }
8079 ]
8080 }
8081 ]
8082 },
8083 noLights: {
8084 name: 'noLights',
8085 class: 'p5',
8086 module: 'Lights, Camera'
8087 },
8088 loadModel: {
8089 name: 'loadModel',
8090 class: 'p5',
8091 module: 'Shape',
8092 overloads: [
8093 {
8094 params: [
8095 {
8096 name: 'path',
8097 description: '<p>Path of the model to be loaded</p>\n',
8098 type: 'String'
8099 },
8100 {
8101 name: 'normalize',
8102 description:
8103 '<p>If true, scale the model to a\n standardized size when loading</p>\n',
8104 type: 'Boolean'
8105 },
8106 {
8107 name: 'successCallback',
8108 description:
8109 '<p>Function to be called\n once the model is loaded. Will be passed\n the 3D model object.</p>\n',
8110 type: 'function(p5.Geometry)',
8111 optional: true
8112 },
8113 {
8114 name: 'failureCallback',
8115 description:
8116 '<p>called with event error if\n the model fails to load.</p>\n',
8117 type: 'Function(Event)',
8118 optional: true
8119 },
8120 {
8121 name: 'fileType',
8122 description:
8123 '<p>The file extension of the model\n (<code>.stl</code>, <code>.obj</code>).</p>\n',
8124 type: 'String',
8125 optional: true
8126 }
8127 ]
8128 },
8129 {
8130 params: [
8131 {
8132 name: 'path',
8133 description: '',
8134 type: 'String'
8135 },
8136 {
8137 name: 'successCallback',
8138 description: '',
8139 type: 'function(p5.Geometry)',
8140 optional: true
8141 },
8142 {
8143 name: 'failureCallback',
8144 description: '',
8145 type: 'Function(Event)',
8146 optional: true
8147 },
8148 {
8149 name: 'fileType',
8150 description: '',
8151 type: 'String',
8152 optional: true
8153 }
8154 ]
8155 }
8156 ]
8157 },
8158 model: {
8159 name: 'model',
8160 params: [
8161 {
8162 name: 'model',
8163 description: '<p>Loaded 3d model to be rendered</p>\n',
8164 type: 'p5.Geometry'
8165 }
8166 ],
8167 class: 'p5',
8168 module: 'Shape'
8169 },
8170 loadShader: {
8171 name: 'loadShader',
8172 params: [
8173 {
8174 name: 'vertFilename',
8175 description:
8176 '<p>path to file containing vertex shader\nsource code</p>\n',
8177 type: 'String'
8178 },
8179 {
8180 name: 'fragFilename',
8181 description:
8182 '<p>path to file containing fragment shader\nsource code</p>\n',
8183 type: 'String'
8184 },
8185 {
8186 name: 'callback',
8187 description:
8188 '<p>callback to be executed after loadShader\ncompletes. On success, the Shader object is passed as the first argument.</p>\n',
8189 type: 'Function',
8190 optional: true
8191 },
8192 {
8193 name: 'errorCallback',
8194 description:
8195 '<p>callback to be executed when an error\noccurs inside loadShader. On error, the error is passed as the first\nargument.</p>\n',
8196 type: 'Function',
8197 optional: true
8198 }
8199 ],
8200 class: 'p5',
8201 module: 'Lights, Camera'
8202 },
8203 createShader: {
8204 name: 'createShader',
8205 params: [
8206 {
8207 name: 'vertSrc',
8208 description: '<p>source code for the vertex shader</p>\n',
8209 type: 'String'
8210 },
8211 {
8212 name: 'fragSrc',
8213 description: '<p>source code for the fragment shader</p>\n',
8214 type: 'String'
8215 }
8216 ],
8217 class: 'p5',
8218 module: 'Lights, Camera'
8219 },
8220 shader: {
8221 name: 'shader',
8222 params: [
8223 {
8224 name: 's',
8225 description:
8226 '<p>the desired <a href="#/p5.Shader">p5.Shader</a> to use for rendering\nshapes.</p>\n',
8227 type: 'p5.Shader',
8228 optional: true
8229 }
8230 ],
8231 class: 'p5',
8232 module: 'Lights, Camera'
8233 },
8234 resetShader: {
8235 name: 'resetShader',
8236 class: 'p5',
8237 module: 'Lights, Camera'
8238 },
8239 normalMaterial: {
8240 name: 'normalMaterial',
8241 class: 'p5',
8242 module: 'Lights, Camera'
8243 },
8244 texture: {
8245 name: 'texture',
8246 params: [
8247 {
8248 name: 'tex',
8249 description:
8250 '<p>2-dimensional graphics\n to render as texture</p>\n',
8251 type: 'p5.Image|p5.MediaElement|p5.Graphics'
8252 }
8253 ],
8254 class: 'p5',
8255 module: 'Lights, Camera'
8256 },
8257 textureMode: {
8258 name: 'textureMode',
8259 params: [
8260 {
8261 name: 'mode',
8262 description: '<p>either IMAGE or NORMAL</p>\n',
8263 type: 'Constant'
8264 }
8265 ],
8266 class: 'p5',
8267 module: 'Lights, Camera'
8268 },
8269 textureWrap: {
8270 name: 'textureWrap',
8271 params: [
8272 {
8273 name: 'wrapX',
8274 description: '<p>either CLAMP, REPEAT, or MIRROR</p>\n',
8275 type: 'Constant'
8276 },
8277 {
8278 name: 'wrapY',
8279 description: '<p>either CLAMP, REPEAT, or MIRROR</p>\n',
8280 type: 'Constant',
8281 optional: true
8282 }
8283 ],
8284 class: 'p5',
8285 module: 'Lights, Camera'
8286 },
8287 ambientMaterial: {
8288 name: 'ambientMaterial',
8289 class: 'p5',
8290 module: 'Lights, Camera',
8291 overloads: [
8292 {
8293 params: [
8294 {
8295 name: 'v1',
8296 description:
8297 '<p>gray value, red or hue value\n (depending on the current color mode),</p>\n',
8298 type: 'Number'
8299 },
8300 {
8301 name: 'v2',
8302 description: '<p>green or saturation value</p>\n',
8303 type: 'Number',
8304 optional: true
8305 },
8306 {
8307 name: 'v3',
8308 description: '<p>blue or brightness value</p>\n',
8309 type: 'Number',
8310 optional: true
8311 }
8312 ],
8313 chainable: 1
8314 },
8315 {
8316 params: [
8317 {
8318 name: 'color',
8319 description: '<p>color, color Array, or CSS color string</p>\n',
8320 type: 'Number[]|String|p5.Color'
8321 }
8322 ],
8323 chainable: 1
8324 }
8325 ]
8326 },
8327 emissiveMaterial: {
8328 name: 'emissiveMaterial',
8329 class: 'p5',
8330 module: 'Lights, Camera',
8331 overloads: [
8332 {
8333 params: [
8334 {
8335 name: 'v1',
8336 description:
8337 '<p>gray value, red or hue value\n (depending on the current color mode),</p>\n',
8338 type: 'Number'
8339 },
8340 {
8341 name: 'v2',
8342 description: '<p>green or saturation value</p>\n',
8343 type: 'Number',
8344 optional: true
8345 },
8346 {
8347 name: 'v3',
8348 description: '<p>blue or brightness value</p>\n',
8349 type: 'Number',
8350 optional: true
8351 },
8352 {
8353 name: 'a',
8354 description: '<p>opacity</p>\n',
8355 type: 'Number',
8356 optional: true
8357 }
8358 ],
8359 chainable: 1
8360 },
8361 {
8362 params: [
8363 {
8364 name: 'color',
8365 description: '<p>color, color Array, or CSS color string</p>\n',
8366 type: 'Number[]|String|p5.Color'
8367 }
8368 ],
8369 chainable: 1
8370 }
8371 ]
8372 },
8373 specularMaterial: {
8374 name: 'specularMaterial',
8375 class: 'p5',
8376 module: 'Lights, Camera',
8377 overloads: [
8378 {
8379 params: [
8380 {
8381 name: 'gray',
8382 description:
8383 '<p>number specifying value between white and black.</p>\n',
8384 type: 'Number'
8385 },
8386 {
8387 name: 'alpha',
8388 description:
8389 '<p>alpha value relative to current color range\n (default is 0-255)</p>\n',
8390 type: 'Number',
8391 optional: true
8392 }
8393 ],
8394 chainable: 1
8395 },
8396 {
8397 params: [
8398 {
8399 name: 'v1',
8400 description:
8401 '<p>red or hue value relative to\n the current color range</p>\n',
8402 type: 'Number'
8403 },
8404 {
8405 name: 'v2',
8406 description:
8407 '<p>green or saturation value\n relative to the current color range</p>\n',
8408 type: 'Number'
8409 },
8410 {
8411 name: 'v3',
8412 description:
8413 '<p>blue or brightness value\n relative to the current color range</p>\n',
8414 type: 'Number'
8415 },
8416 {
8417 name: 'alpha',
8418 description: '',
8419 type: 'Number',
8420 optional: true
8421 }
8422 ],
8423 chainable: 1
8424 },
8425 {
8426 params: [
8427 {
8428 name: 'color',
8429 description: '<p>color Array, or CSS color string</p>\n',
8430 type: 'Number[]|String|p5.Color'
8431 }
8432 ],
8433 chainable: 1
8434 }
8435 ]
8436 },
8437 shininess: {
8438 name: 'shininess',
8439 params: [
8440 {
8441 name: 'shine',
8442 description:
8443 '<p>Degree of Shininess.\n Defaults to 1.</p>\n',
8444 type: 'Number'
8445 }
8446 ],
8447 class: 'p5',
8448 module: 'Lights, Camera'
8449 },
8450 camera: {
8451 name: 'camera',
8452 params: [
8453 {
8454 name: 'x',
8455 description: '<p>camera position value on x axis</p>\n',
8456 type: 'Number',
8457 optional: true
8458 },
8459 {
8460 name: 'y',
8461 description: '<p>camera position value on y axis</p>\n',
8462 type: 'Number',
8463 optional: true
8464 },
8465 {
8466 name: 'z',
8467 description: '<p>camera position value on z axis</p>\n',
8468 type: 'Number',
8469 optional: true
8470 },
8471 {
8472 name: 'centerX',
8473 description: '<p>x coordinate representing center of the sketch</p>\n',
8474 type: 'Number',
8475 optional: true
8476 },
8477 {
8478 name: 'centerY',
8479 description: '<p>y coordinate representing center of the sketch</p>\n',
8480 type: 'Number',
8481 optional: true
8482 },
8483 {
8484 name: 'centerZ',
8485 description: '<p>z coordinate representing center of the sketch</p>\n',
8486 type: 'Number',
8487 optional: true
8488 },
8489 {
8490 name: 'upX',
8491 description: "<p>x component of direction 'up' from camera</p>\n",
8492 type: 'Number',
8493 optional: true
8494 },
8495 {
8496 name: 'upY',
8497 description: "<p>y component of direction 'up' from camera</p>\n",
8498 type: 'Number',
8499 optional: true
8500 },
8501 {
8502 name: 'upZ',
8503 description: "<p>z component of direction 'up' from camera</p>\n",
8504 type: 'Number',
8505 optional: true
8506 }
8507 ],
8508 class: 'p5',
8509 module: 'Lights, Camera'
8510 },
8511 perspective: {
8512 name: 'perspective',
8513 params: [
8514 {
8515 name: 'fovy',
8516 description:
8517 '<p>camera frustum vertical field of view,\n from bottom to top of view, in <a href="#/p5/angleMode">angleMode</a> units</p>\n',
8518 type: 'Number',
8519 optional: true
8520 },
8521 {
8522 name: 'aspect',
8523 description: '<p>camera frustum aspect ratio</p>\n',
8524 type: 'Number',
8525 optional: true
8526 },
8527 {
8528 name: 'near',
8529 description: '<p>frustum near plane length</p>\n',
8530 type: 'Number',
8531 optional: true
8532 },
8533 {
8534 name: 'far',
8535 description: '<p>frustum far plane length</p>\n',
8536 type: 'Number',
8537 optional: true
8538 }
8539 ],
8540 class: 'p5',
8541 module: 'Lights, Camera'
8542 },
8543 ortho: {
8544 name: 'ortho',
8545 params: [
8546 {
8547 name: 'left',
8548 description: '<p>camera frustum left plane</p>\n',
8549 type: 'Number',
8550 optional: true
8551 },
8552 {
8553 name: 'right',
8554 description: '<p>camera frustum right plane</p>\n',
8555 type: 'Number',
8556 optional: true
8557 },
8558 {
8559 name: 'bottom',
8560 description: '<p>camera frustum bottom plane</p>\n',
8561 type: 'Number',
8562 optional: true
8563 },
8564 {
8565 name: 'top',
8566 description: '<p>camera frustum top plane</p>\n',
8567 type: 'Number',
8568 optional: true
8569 },
8570 {
8571 name: 'near',
8572 description: '<p>camera frustum near plane</p>\n',
8573 type: 'Number',
8574 optional: true
8575 },
8576 {
8577 name: 'far',
8578 description: '<p>camera frustum far plane</p>\n',
8579 type: 'Number',
8580 optional: true
8581 }
8582 ],
8583 class: 'p5',
8584 module: 'Lights, Camera'
8585 },
8586 frustum: {
8587 name: 'frustum',
8588 params: [
8589 {
8590 name: 'left',
8591 description: '<p>camera frustum left plane</p>\n',
8592 type: 'Number',
8593 optional: true
8594 },
8595 {
8596 name: 'right',
8597 description: '<p>camera frustum right plane</p>\n',
8598 type: 'Number',
8599 optional: true
8600 },
8601 {
8602 name: 'bottom',
8603 description: '<p>camera frustum bottom plane</p>\n',
8604 type: 'Number',
8605 optional: true
8606 },
8607 {
8608 name: 'top',
8609 description: '<p>camera frustum top plane</p>\n',
8610 type: 'Number',
8611 optional: true
8612 },
8613 {
8614 name: 'near',
8615 description: '<p>camera frustum near plane</p>\n',
8616 type: 'Number',
8617 optional: true
8618 },
8619 {
8620 name: 'far',
8621 description: '<p>camera frustum far plane</p>\n',
8622 type: 'Number',
8623 optional: true
8624 }
8625 ],
8626 class: 'p5',
8627 module: 'Lights, Camera'
8628 },
8629 createCamera: {
8630 name: 'createCamera',
8631 class: 'p5',
8632 module: 'Lights, Camera'
8633 },
8634 setCamera: {
8635 name: 'setCamera',
8636 params: [
8637 {
8638 name: 'cam',
8639 description: '<p>p5.Camera object</p>\n',
8640 type: 'p5.Camera'
8641 }
8642 ],
8643 class: 'p5',
8644 module: 'Lights, Camera'
8645 },
8646 setAttributes: {
8647 name: 'setAttributes',
8648 class: 'p5',
8649 module: 'Rendering',
8650 overloads: [
8651 {
8652 params: [
8653 {
8654 name: 'key',
8655 description: '<p>Name of attribute</p>\n',
8656 type: 'String'
8657 },
8658 {
8659 name: 'value',
8660 description: '<p>New value of named attribute</p>\n',
8661 type: 'Boolean'
8662 }
8663 ]
8664 },
8665 {
8666 params: [
8667 {
8668 name: 'obj',
8669 description: '<p>object with key-value pairs</p>\n',
8670 type: 'Object'
8671 }
8672 ]
8673 }
8674 ]
8675 },
8676 sampleRate: {
8677 name: 'sampleRate',
8678 class: 'p5',
8679 module: 'p5.sound'
8680 },
8681 freqToMidi: {
8682 name: 'freqToMidi',
8683 params: [
8684 {
8685 name: 'frequency',
8686 description:
8687 '<p>A freqeuncy, for example, the "A"\n above Middle C is 440Hz</p>\n',
8688 type: 'Number'
8689 }
8690 ],
8691 class: 'p5',
8692 module: 'p5.sound'
8693 },
8694 midiToFreq: {
8695 name: 'midiToFreq',
8696 params: [
8697 {
8698 name: 'midiNote',
8699 description: '<p>The number of a MIDI note</p>\n',
8700 type: 'Number'
8701 }
8702 ],
8703 class: 'p5',
8704 module: 'p5.sound'
8705 },
8706 soundFormats: {
8707 name: 'soundFormats',
8708 params: [
8709 {
8710 name: 'formats',
8711 description: "<p>i.e. 'mp3', 'wav', 'ogg'</p>\n",
8712 type: 'String',
8713 optional: true,
8714 multiple: true
8715 }
8716 ],
8717 class: 'p5',
8718 module: 'p5.sound'
8719 },
8720 getAudioContext: {
8721 name: 'getAudioContext',
8722 class: 'p5',
8723 module: 'p5.sound'
8724 },
8725 userStartAudio: {
8726 params: [
8727 {
8728 name: 'element(s)',
8729 description:
8730 '<p>This argument can be an Element,\n Selector String, NodeList, p5.Element,\n jQuery Element, or an Array of any of those.</p>\n',
8731 type: 'Element|Array',
8732 optional: true
8733 },
8734 {
8735 name: 'callback',
8736 description:
8737 '<p>Callback to invoke when the AudioContext\n has started</p>\n',
8738 type: 'Function',
8739 optional: true
8740 }
8741 ],
8742 name: 'userStartAudio',
8743 class: 'p5',
8744 module: 'p5.sound'
8745 },
8746 loadSound: {
8747 name: 'loadSound',
8748 params: [
8749 {
8750 name: 'path',
8751 description:
8752 "<p>Path to the sound file, or an array with\n paths to soundfiles in multiple formats\n i.e. ['sound.ogg', 'sound.mp3'].\n Alternately, accepts an object: either\n from the HTML5 File API, or a p5.File.</p>\n",
8753 type: 'String|Array'
8754 },
8755 {
8756 name: 'successCallback',
8757 description: '<p>Name of a function to call once file loads</p>\n',
8758 type: 'Function',
8759 optional: true
8760 },
8761 {
8762 name: 'errorCallback',
8763 description:
8764 '<p>Name of a function to call if there is\n an error loading the file.</p>\n',
8765 type: 'Function',
8766 optional: true
8767 },
8768 {
8769 name: 'whileLoading',
8770 description:
8771 '<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',
8772 type: 'Function',
8773 optional: true
8774 }
8775 ],
8776 class: 'p5',
8777 module: 'p5.sound'
8778 },
8779 createConvolver: {
8780 name: 'createConvolver',
8781 params: [
8782 {
8783 name: 'path',
8784 description: '<p>path to a sound file</p>\n',
8785 type: 'String'
8786 },
8787 {
8788 name: 'callback',
8789 description:
8790 '<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',
8791 type: 'Function',
8792 optional: true
8793 },
8794 {
8795 name: 'errorCallback',
8796 description:
8797 '<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',
8798 type: 'Function',
8799 optional: true
8800 }
8801 ],
8802 class: 'p5',
8803 module: 'p5.sound'
8804 },
8805 setBPM: {
8806 name: 'setBPM',
8807 params: [
8808 {
8809 name: 'BPM',
8810 description: '<p>Beats Per Minute</p>\n',
8811 type: 'Number'
8812 },
8813 {
8814 name: 'rampTime',
8815 description: '<p>Seconds from now</p>\n',
8816 type: 'Number'
8817 }
8818 ],
8819 class: 'p5',
8820 module: 'p5.sound'
8821 },
8822 saveSound: {
8823 name: 'saveSound',
8824 params: [
8825 {
8826 name: 'soundFile',
8827 description: '<p>p5.SoundFile that you wish to save</p>\n',
8828 type: 'p5.SoundFile'
8829 },
8830 {
8831 name: 'fileName',
8832 description: '<p>name of the resulting .wav file.</p>\n',
8833 type: 'String'
8834 }
8835 ],
8836 class: 'p5',
8837 module: 'p5.sound'
8838 }
8839 },
8840 'p5.Color': {
8841 toString: {
8842 name: 'toString',
8843 params: [
8844 {
8845 name: 'format',
8846 description:
8847 "<p>How the color string will be formatted.\nLeaving this empty formats the string as rgba(r, g, b, a).\n'#rgb' '#rgba' '#rrggbb' and '#rrggbbaa' format as hexadecimal color codes.\n'rgb' 'hsb' and 'hsl' return the color formatted in the specified color mode.\n'rgba' 'hsba' and 'hsla' are the same as above but with alpha channels.\n'rgb%' 'hsb%' 'hsl%' 'rgba%' 'hsba%' and 'hsla%' format as percentages.</p>\n",
8848 type: 'String',
8849 optional: true
8850 }
8851 ],
8852 class: 'p5.Color',
8853 module: 'Color'
8854 },
8855 setRed: {
8856 name: 'setRed',
8857 params: [
8858 {
8859 name: 'red',
8860 description: '<p>the new red value</p>\n',
8861 type: 'Number'
8862 }
8863 ],
8864 class: 'p5.Color',
8865 module: 'Color'
8866 },
8867 setGreen: {
8868 name: 'setGreen',
8869 params: [
8870 {
8871 name: 'green',
8872 description: '<p>the new green value</p>\n',
8873 type: 'Number'
8874 }
8875 ],
8876 class: 'p5.Color',
8877 module: 'Color'
8878 },
8879 setBlue: {
8880 name: 'setBlue',
8881 params: [
8882 {
8883 name: 'blue',
8884 description: '<p>the new blue value</p>\n',
8885 type: 'Number'
8886 }
8887 ],
8888 class: 'p5.Color',
8889 module: 'Color'
8890 },
8891 setAlpha: {
8892 name: 'setAlpha',
8893 params: [
8894 {
8895 name: 'alpha',
8896 description: '<p>the new alpha value</p>\n',
8897 type: 'Number'
8898 }
8899 ],
8900 class: 'p5.Color',
8901 module: 'Color'
8902 }
8903 },
8904 'p5.Element': {
8905 elt: {
8906 name: 'elt',
8907 class: 'p5.Element',
8908 module: 'DOM'
8909 },
8910 parent: {
8911 name: 'parent',
8912 class: 'p5.Element',
8913 module: 'DOM',
8914 overloads: [
8915 {
8916 params: [
8917 {
8918 name: 'parent',
8919 description:
8920 '<p>the ID, DOM node, or <a href="#/p5.Element">p5.Element</a>\n of desired parent element</p>\n',
8921 type: 'String|p5.Element|Object'
8922 }
8923 ],
8924 chainable: 1
8925 },
8926 {
8927 params: []
8928 }
8929 ]
8930 },
8931 id: {
8932 name: 'id',
8933 class: 'p5.Element',
8934 module: 'DOM',
8935 overloads: [
8936 {
8937 params: [
8938 {
8939 name: 'id',
8940 description: '<p>ID of the element</p>\n',
8941 type: 'String'
8942 }
8943 ],
8944 chainable: 1
8945 },
8946 {
8947 params: []
8948 }
8949 ]
8950 },
8951 class: {
8952 name: 'class',
8953 class: 'p5.Element',
8954 module: 'DOM',
8955 overloads: [
8956 {
8957 params: [
8958 {
8959 name: 'class',
8960 description: '<p>class to add</p>\n',
8961 type: 'String'
8962 }
8963 ],
8964 chainable: 1
8965 },
8966 {
8967 params: []
8968 }
8969 ]
8970 },
8971 mousePressed: {
8972 name: 'mousePressed',
8973 params: [
8974 {
8975 name: 'fxn',
8976 description:
8977 '<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',
8978 type: 'Function|Boolean'
8979 }
8980 ],
8981 class: 'p5.Element',
8982 module: 'DOM'
8983 },
8984 doubleClicked: {
8985 name: 'doubleClicked',
8986 params: [
8987 {
8988 name: 'fxn',
8989 description:
8990 '<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',
8991 type: 'Function|Boolean'
8992 }
8993 ],
8994 class: 'p5.Element',
8995 module: 'DOM'
8996 },
8997 mouseWheel: {
8998 name: 'mouseWheel',
8999 params: [
9000 {
9001 name: 'fxn',
9002 description:
9003 '<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',
9004 type: 'Function|Boolean'
9005 }
9006 ],
9007 class: 'p5.Element',
9008 module: 'DOM'
9009 },
9010 mouseReleased: {
9011 name: 'mouseReleased',
9012 params: [
9013 {
9014 name: 'fxn',
9015 description:
9016 '<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',
9017 type: 'Function|Boolean'
9018 }
9019 ],
9020 class: 'p5.Element',
9021 module: 'DOM'
9022 },
9023 mouseClicked: {
9024 name: 'mouseClicked',
9025 params: [
9026 {
9027 name: 'fxn',
9028 description:
9029 '<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',
9030 type: 'Function|Boolean'
9031 }
9032 ],
9033 class: 'p5.Element',
9034 module: 'DOM'
9035 },
9036 mouseMoved: {
9037 name: 'mouseMoved',
9038 params: [
9039 {
9040 name: 'fxn',
9041 description:
9042 '<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',
9043 type: 'Function|Boolean'
9044 }
9045 ],
9046 class: 'p5.Element',
9047 module: 'DOM'
9048 },
9049 mouseOver: {
9050 name: 'mouseOver',
9051 params: [
9052 {
9053 name: 'fxn',
9054 description:
9055 '<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',
9056 type: 'Function|Boolean'
9057 }
9058 ],
9059 class: 'p5.Element',
9060 module: 'DOM'
9061 },
9062 mouseOut: {
9063 name: 'mouseOut',
9064 params: [
9065 {
9066 name: 'fxn',
9067 description:
9068 '<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',
9069 type: 'Function|Boolean'
9070 }
9071 ],
9072 class: 'p5.Element',
9073 module: 'DOM'
9074 },
9075 touchStarted: {
9076 name: 'touchStarted',
9077 params: [
9078 {
9079 name: 'fxn',
9080 description:
9081 '<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',
9082 type: 'Function|Boolean'
9083 }
9084 ],
9085 class: 'p5.Element',
9086 module: 'DOM'
9087 },
9088 touchMoved: {
9089 name: 'touchMoved',
9090 params: [
9091 {
9092 name: 'fxn',
9093 description:
9094 '<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',
9095 type: 'Function|Boolean'
9096 }
9097 ],
9098 class: 'p5.Element',
9099 module: 'DOM'
9100 },
9101 touchEnded: {
9102 name: 'touchEnded',
9103 params: [
9104 {
9105 name: 'fxn',
9106 description:
9107 '<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',
9108 type: 'Function|Boolean'
9109 }
9110 ],
9111 class: 'p5.Element',
9112 module: 'DOM'
9113 },
9114 dragOver: {
9115 name: 'dragOver',
9116 params: [
9117 {
9118 name: 'fxn',
9119 description:
9120 '<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',
9121 type: 'Function|Boolean'
9122 }
9123 ],
9124 class: 'p5.Element',
9125 module: 'DOM'
9126 },
9127 dragLeave: {
9128 name: 'dragLeave',
9129 params: [
9130 {
9131 name: 'fxn',
9132 description:
9133 '<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',
9134 type: 'Function|Boolean'
9135 }
9136 ],
9137 class: 'p5.Element',
9138 module: 'DOM'
9139 },
9140 addClass: {
9141 name: 'addClass',
9142 params: [
9143 {
9144 name: 'class',
9145 description: '<p>name of class to add</p>\n',
9146 type: 'String'
9147 }
9148 ],
9149 class: 'p5.Element',
9150 module: 'DOM'
9151 },
9152 removeClass: {
9153 name: 'removeClass',
9154 params: [
9155 {
9156 name: 'class',
9157 description: '<p>name of class to remove</p>\n',
9158 type: 'String'
9159 }
9160 ],
9161 class: 'p5.Element',
9162 module: 'DOM'
9163 },
9164 hasClass: {
9165 name: 'hasClass',
9166 params: [
9167 {
9168 name: 'c',
9169 description: '<p>class name of class to check</p>\n',
9170 type: 'String'
9171 }
9172 ],
9173 class: 'p5.Element',
9174 module: 'DOM'
9175 },
9176 toggleClass: {
9177 name: 'toggleClass',
9178 params: [
9179 {
9180 name: 'c',
9181 description: '<p>class name to toggle</p>\n',
9182 type: 'String'
9183 }
9184 ],
9185 class: 'p5.Element',
9186 module: 'DOM'
9187 },
9188 child: {
9189 name: 'child',
9190 class: 'p5.Element',
9191 module: 'DOM',
9192 overloads: [
9193 {
9194 params: []
9195 },
9196 {
9197 params: [
9198 {
9199 name: 'child',
9200 description:
9201 '<p>the ID, DOM node, or <a href="#/p5.Element">p5.Element</a>\n to add to the current element</p>\n',
9202 type: 'String|p5.Element',
9203 optional: true
9204 }
9205 ],
9206 chainable: 1
9207 }
9208 ]
9209 },
9210 center: {
9211 name: 'center',
9212 params: [
9213 {
9214 name: 'align',
9215 description:
9216 "<p>passing 'vertical', 'horizontal' aligns element accordingly</p>\n",
9217 type: 'String',
9218 optional: true
9219 }
9220 ],
9221 class: 'p5.Element',
9222 module: 'DOM'
9223 },
9224 html: {
9225 name: 'html',
9226 class: 'p5.Element',
9227 module: 'DOM',
9228 overloads: [
9229 {
9230 params: []
9231 },
9232 {
9233 params: [
9234 {
9235 name: 'html',
9236 description: '<p>the HTML to be placed inside the element</p>\n',
9237 type: 'String',
9238 optional: true
9239 },
9240 {
9241 name: 'append',
9242 description: '<p>whether to append HTML to existing</p>\n',
9243 type: 'Boolean',
9244 optional: true
9245 }
9246 ],
9247 chainable: 1
9248 }
9249 ]
9250 },
9251 position: {
9252 name: 'position',
9253 class: 'p5.Element',
9254 module: 'DOM',
9255 overloads: [
9256 {
9257 params: []
9258 },
9259 {
9260 params: [
9261 {
9262 name: 'x',
9263 description:
9264 '<p>x-position relative to upper left of window (optional)</p>\n',
9265 type: 'Number',
9266 optional: true
9267 },
9268 {
9269 name: 'y',
9270 description:
9271 '<p>y-position relative to upper left of window (optional)</p>\n',
9272 type: 'Number',
9273 optional: true
9274 },
9275 {
9276 name: 'positionType',
9277 description:
9278 '<p>it can be static, fixed, relative, sticky, initial or inherit (optional)</p>\n',
9279 type: 'String'
9280 }
9281 ],
9282 chainable: 1
9283 }
9284 ]
9285 },
9286 style: {
9287 name: 'style',
9288 class: 'p5.Element',
9289 module: 'DOM',
9290 overloads: [
9291 {
9292 params: [
9293 {
9294 name: 'property',
9295 description: '<p>property to be set</p>\n',
9296 type: 'String'
9297 }
9298 ]
9299 },
9300 {
9301 params: [
9302 {
9303 name: 'property',
9304 description: '',
9305 type: 'String'
9306 },
9307 {
9308 name: 'value',
9309 description: '<p>value to assign to property</p>\n',
9310 type: 'String|p5.Color'
9311 }
9312 ],
9313 chainable: 1
9314 }
9315 ]
9316 },
9317 attribute: {
9318 name: 'attribute',
9319 class: 'p5.Element',
9320 module: 'DOM',
9321 overloads: [
9322 {
9323 params: []
9324 },
9325 {
9326 params: [
9327 {
9328 name: 'attr',
9329 description: '<p>attribute to set</p>\n',
9330 type: 'String'
9331 },
9332 {
9333 name: 'value',
9334 description: '<p>value to assign to attribute</p>\n',
9335 type: 'String'
9336 }
9337 ],
9338 chainable: 1
9339 }
9340 ]
9341 },
9342 removeAttribute: {
9343 name: 'removeAttribute',
9344 params: [
9345 {
9346 name: 'attr',
9347 description: '<p>attribute to remove</p>\n',
9348 type: 'String'
9349 }
9350 ],
9351 class: 'p5.Element',
9352 module: 'DOM'
9353 },
9354 value: {
9355 name: 'value',
9356 class: 'p5.Element',
9357 module: 'DOM',
9358 overloads: [
9359 {
9360 params: []
9361 },
9362 {
9363 params: [
9364 {
9365 name: 'value',
9366 description: '',
9367 type: 'String|Number'
9368 }
9369 ],
9370 chainable: 1
9371 }
9372 ]
9373 },
9374 show: {
9375 name: 'show',
9376 class: 'p5.Element',
9377 module: 'DOM'
9378 },
9379 hide: {
9380 name: 'hide',
9381 class: 'p5.Element',
9382 module: 'DOM'
9383 },
9384 size: {
9385 name: 'size',
9386 class: 'p5.Element',
9387 module: 'DOM',
9388 overloads: [
9389 {
9390 params: []
9391 },
9392 {
9393 params: [
9394 {
9395 name: 'w',
9396 description:
9397 '<p>width of the element, either AUTO, or a number</p>\n',
9398 type: 'Number|Constant'
9399 },
9400 {
9401 name: 'h',
9402 description:
9403 '<p>height of the element, either AUTO, or a number</p>\n',
9404 type: 'Number|Constant',
9405 optional: true
9406 }
9407 ],
9408 chainable: 1
9409 }
9410 ]
9411 },
9412 remove: {
9413 name: 'remove',
9414 class: 'p5.Element',
9415 module: 'DOM'
9416 },
9417 drop: {
9418 name: 'drop',
9419 params: [
9420 {
9421 name: 'callback',
9422 description:
9423 '<p>callback to receive loaded file, called for each file dropped.</p>\n',
9424 type: 'Function'
9425 },
9426 {
9427 name: 'fxn',
9428 description:
9429 '<p>callback triggered once when files are dropped with the drop event.</p>\n',
9430 type: 'Function',
9431 optional: true
9432 }
9433 ],
9434 class: 'p5.Element',
9435 module: 'DOM'
9436 }
9437 },
9438 'p5.Graphics': {
9439 reset: {
9440 name: 'reset',
9441 class: 'p5.Graphics',
9442 module: 'Rendering'
9443 },
9444 remove: {
9445 name: 'remove',
9446 class: 'p5.Graphics',
9447 module: 'Rendering'
9448 }
9449 },
9450 JSON: {
9451 stringify: {
9452 name: 'stringify',
9453 params: [
9454 {
9455 name: 'object',
9456 description:
9457 '<p>:Javascript object that you would like to convert to JSON</p>\n',
9458 type: 'Object'
9459 }
9460 ],
9461 class: 'JSON',
9462 module: 'Foundation'
9463 }
9464 },
9465 console: {
9466 log: {
9467 name: 'log',
9468 params: [
9469 {
9470 name: 'message',
9471 description:
9472 '<p>:Message that you would like to print to the console</p>\n',
9473 type: 'String|Expression|Object'
9474 }
9475 ],
9476 class: 'console',
9477 module: 'Foundation'
9478 }
9479 },
9480 'p5.TypedDict': {
9481 size: {
9482 name: 'size',
9483 class: 'p5.TypedDict',
9484 module: 'Data'
9485 },
9486 hasKey: {
9487 name: 'hasKey',
9488 params: [
9489 {
9490 name: 'key',
9491 description: '<p>that you want to look up</p>\n',
9492 type: 'Number|String'
9493 }
9494 ],
9495 class: 'p5.TypedDict',
9496 module: 'Data'
9497 },
9498 get: {
9499 name: 'get',
9500 params: [
9501 {
9502 name: 'the',
9503 description: '<p>key you want to access</p>\n',
9504 type: 'Number|String'
9505 }
9506 ],
9507 class: 'p5.TypedDict',
9508 module: 'Data'
9509 },
9510 set: {
9511 name: 'set',
9512 params: [
9513 {
9514 name: 'key',
9515 description: '',
9516 type: 'Number|String'
9517 },
9518 {
9519 name: 'value',
9520 description: '',
9521 type: 'Number|String'
9522 }
9523 ],
9524 class: 'p5.TypedDict',
9525 module: 'Data'
9526 },
9527 create: {
9528 name: 'create',
9529 class: 'p5.TypedDict',
9530 module: 'Data',
9531 overloads: [
9532 {
9533 params: [
9534 {
9535 name: 'key',
9536 description: '',
9537 type: 'Number|String'
9538 },
9539 {
9540 name: 'value',
9541 description: '',
9542 type: 'Number|String'
9543 }
9544 ]
9545 },
9546 {
9547 params: [
9548 {
9549 name: 'obj',
9550 description: '<p>key/value pair</p>\n',
9551 type: 'Object'
9552 }
9553 ]
9554 }
9555 ]
9556 },
9557 clear: {
9558 name: 'clear',
9559 class: 'p5.TypedDict',
9560 module: 'Data'
9561 },
9562 remove: {
9563 name: 'remove',
9564 params: [
9565 {
9566 name: 'key',
9567 description: '<p>for the pair to remove</p>\n',
9568 type: 'Number|String'
9569 }
9570 ],
9571 class: 'p5.TypedDict',
9572 module: 'Data'
9573 },
9574 print: {
9575 name: 'print',
9576 class: 'p5.TypedDict',
9577 module: 'Data'
9578 },
9579 saveTable: {
9580 name: 'saveTable',
9581 class: 'p5.TypedDict',
9582 module: 'Data'
9583 },
9584 saveJSON: {
9585 name: 'saveJSON',
9586 class: 'p5.TypedDict',
9587 module: 'Data'
9588 }
9589 },
9590 'p5.NumberDict': {
9591 add: {
9592 name: 'add',
9593 params: [
9594 {
9595 name: 'Key',
9596 description: '<p>for the value you wish to add to</p>\n',
9597 type: 'Number'
9598 },
9599 {
9600 name: 'Number',
9601 description: '<p>to add to the value</p>\n',
9602 type: 'Number'
9603 }
9604 ],
9605 class: 'p5.NumberDict',
9606 module: 'Data'
9607 },
9608 sub: {
9609 name: 'sub',
9610 params: [
9611 {
9612 name: 'Key',
9613 description: '<p>for the value you wish to subtract from</p>\n',
9614 type: 'Number'
9615 },
9616 {
9617 name: 'Number',
9618 description: '<p>to subtract from the value</p>\n',
9619 type: 'Number'
9620 }
9621 ],
9622 class: 'p5.NumberDict',
9623 module: 'Data'
9624 },
9625 mult: {
9626 name: 'mult',
9627 params: [
9628 {
9629 name: 'Key',
9630 description: '<p>for value you wish to multiply</p>\n',
9631 type: 'Number'
9632 },
9633 {
9634 name: 'Amount',
9635 description: '<p>to multiply the value by</p>\n',
9636 type: 'Number'
9637 }
9638 ],
9639 class: 'p5.NumberDict',
9640 module: 'Data'
9641 },
9642 div: {
9643 name: 'div',
9644 params: [
9645 {
9646 name: 'Key',
9647 description: '<p>for value you wish to divide</p>\n',
9648 type: 'Number'
9649 },
9650 {
9651 name: 'Amount',
9652 description: '<p>to divide the value by</p>\n',
9653 type: 'Number'
9654 }
9655 ],
9656 class: 'p5.NumberDict',
9657 module: 'Data'
9658 },
9659 minValue: {
9660 name: 'minValue',
9661 class: 'p5.NumberDict',
9662 module: 'Data'
9663 },
9664 maxValue: {
9665 name: 'maxValue',
9666 class: 'p5.NumberDict',
9667 module: 'Data'
9668 },
9669 minKey: {
9670 name: 'minKey',
9671 class: 'p5.NumberDict',
9672 module: 'Data'
9673 },
9674 maxKey: {
9675 name: 'maxKey',
9676 class: 'p5.NumberDict',
9677 module: 'Data'
9678 }
9679 },
9680 'p5.MediaElement': {
9681 src: {
9682 name: 'src',
9683 class: 'p5.MediaElement',
9684 module: 'DOM'
9685 },
9686 play: {
9687 name: 'play',
9688 class: 'p5.MediaElement',
9689 module: 'DOM'
9690 },
9691 stop: {
9692 name: 'stop',
9693 class: 'p5.MediaElement',
9694 module: 'DOM'
9695 },
9696 pause: {
9697 name: 'pause',
9698 class: 'p5.MediaElement',
9699 module: 'DOM'
9700 },
9701 loop: {
9702 name: 'loop',
9703 class: 'p5.MediaElement',
9704 module: 'DOM'
9705 },
9706 noLoop: {
9707 name: 'noLoop',
9708 class: 'p5.MediaElement',
9709 module: 'DOM'
9710 },
9711 autoplay: {
9712 name: 'autoplay',
9713 params: [
9714 {
9715 name: 'shouldAutoplay',
9716 description: '<p>whether the element should autoplay</p>\n',
9717 type: 'Boolean'
9718 }
9719 ],
9720 class: 'p5.MediaElement',
9721 module: 'DOM'
9722 },
9723 volume: {
9724 name: 'volume',
9725 class: 'p5.MediaElement',
9726 module: 'DOM',
9727 overloads: [
9728 {
9729 params: []
9730 },
9731 {
9732 params: [
9733 {
9734 name: 'val',
9735 description: '<p>volume between 0.0 and 1.0</p>\n',
9736 type: 'Number'
9737 }
9738 ],
9739 chainable: 1
9740 }
9741 ]
9742 },
9743 speed: {
9744 name: 'speed',
9745 class: 'p5.MediaElement',
9746 module: 'DOM',
9747 overloads: [
9748 {
9749 params: []
9750 },
9751 {
9752 params: [
9753 {
9754 name: 'speed',
9755 description: '<p>speed multiplier for element playback</p>\n',
9756 type: 'Number'
9757 }
9758 ],
9759 chainable: 1
9760 }
9761 ]
9762 },
9763 time: {
9764 name: 'time',
9765 class: 'p5.MediaElement',
9766 module: 'DOM',
9767 overloads: [
9768 {
9769 params: []
9770 },
9771 {
9772 params: [
9773 {
9774 name: 'time',
9775 description: '<p>time to jump to (in seconds)</p>\n',
9776 type: 'Number'
9777 }
9778 ],
9779 chainable: 1
9780 }
9781 ]
9782 },
9783 duration: {
9784 name: 'duration',
9785 class: 'p5.MediaElement',
9786 module: 'DOM'
9787 },
9788 onended: {
9789 name: 'onended',
9790 params: [
9791 {
9792 name: 'callback',
9793 description:
9794 '<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',
9795 type: 'Function'
9796 }
9797 ],
9798 class: 'p5.MediaElement',
9799 module: 'DOM'
9800 },
9801 connect: {
9802 name: 'connect',
9803 params: [
9804 {
9805 name: 'audioNode',
9806 description:
9807 '<p>AudioNode from the Web Audio API,\nor an object from the p5.sound library</p>\n',
9808 type: 'AudioNode|Object'
9809 }
9810 ],
9811 class: 'p5.MediaElement',
9812 module: 'DOM'
9813 },
9814 disconnect: {
9815 name: 'disconnect',
9816 class: 'p5.MediaElement',
9817 module: 'DOM'
9818 },
9819 showControls: {
9820 name: 'showControls',
9821 class: 'p5.MediaElement',
9822 module: 'DOM'
9823 },
9824 hideControls: {
9825 name: 'hideControls',
9826 class: 'p5.MediaElement',
9827 module: 'DOM'
9828 },
9829 addCue: {
9830 name: 'addCue',
9831 params: [
9832 {
9833 name: 'time',
9834 description:
9835 "<p>Time in seconds, relative to this media\n element'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",
9836 type: 'Number'
9837 },
9838 {
9839 name: 'callback',
9840 description:
9841 '<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',
9842 type: 'Function'
9843 },
9844 {
9845 name: 'value',
9846 description:
9847 '<p>An object to be passed as the\n second parameter to the\n callback function.</p>\n',
9848 type: 'Object',
9849 optional: true
9850 }
9851 ],
9852 class: 'p5.MediaElement',
9853 module: 'DOM'
9854 },
9855 removeCue: {
9856 name: 'removeCue',
9857 params: [
9858 {
9859 name: 'id',
9860 description: '<p>ID of the cue, as returned by addCue</p>\n',
9861 type: 'Number'
9862 }
9863 ],
9864 class: 'p5.MediaElement',
9865 module: 'DOM'
9866 },
9867 clearCues: {
9868 name: 'clearCues',
9869 params: [
9870 {
9871 name: 'id',
9872 description: '<p>ID of the cue, as returned by addCue</p>\n',
9873 type: 'Number'
9874 }
9875 ],
9876 class: 'p5.MediaElement',
9877 module: 'DOM'
9878 }
9879 },
9880 'p5.File': {
9881 file: {
9882 name: 'file',
9883 class: 'p5.File',
9884 module: 'DOM'
9885 },
9886 type: {
9887 name: 'type',
9888 class: 'p5.File',
9889 module: 'DOM'
9890 },
9891 subtype: {
9892 name: 'subtype',
9893 class: 'p5.File',
9894 module: 'DOM'
9895 },
9896 name: {
9897 name: 'name',
9898 class: 'p5.File',
9899 module: 'DOM'
9900 },
9901 size: {
9902 name: 'size',
9903 class: 'p5.File',
9904 module: 'DOM'
9905 },
9906 data: {
9907 name: 'data',
9908 class: 'p5.File',
9909 module: 'DOM'
9910 }
9911 },
9912 'p5.Image': {
9913 width: {
9914 name: 'width',
9915 class: 'p5.Image',
9916 module: 'Image'
9917 },
9918 height: {
9919 name: 'height',
9920 class: 'p5.Image',
9921 module: 'Image'
9922 },
9923 pixels: {
9924 name: 'pixels',
9925 class: 'p5.Image',
9926 module: 'Image'
9927 },
9928 loadPixels: {
9929 name: 'loadPixels',
9930 class: 'p5.Image',
9931 module: 'Image'
9932 },
9933 updatePixels: {
9934 name: 'updatePixels',
9935 class: 'p5.Image',
9936 module: 'Image',
9937 overloads: [
9938 {
9939 params: [
9940 {
9941 name: 'x',
9942 description:
9943 '<p>x-offset of the target update area for the\n underlying canvas</p>\n',
9944 type: 'Integer'
9945 },
9946 {
9947 name: 'y',
9948 description:
9949 '<p>y-offset of the target update area for the\n underlying canvas</p>\n',
9950 type: 'Integer'
9951 },
9952 {
9953 name: 'w',
9954 description:
9955 '<p>height of the target update area for the\n underlying canvas</p>\n',
9956 type: 'Integer'
9957 },
9958 {
9959 name: 'h',
9960 description:
9961 '<p>height of the target update area for the\n underlying canvas</p>\n',
9962 type: 'Integer'
9963 }
9964 ]
9965 },
9966 {
9967 params: []
9968 }
9969 ]
9970 },
9971 get: {
9972 name: 'get',
9973 class: 'p5.Image',
9974 module: 'Image',
9975 overloads: [
9976 {
9977 params: [
9978 {
9979 name: 'x',
9980 description: '<p>x-coordinate of the pixel</p>\n',
9981 type: 'Number'
9982 },
9983 {
9984 name: 'y',
9985 description: '<p>y-coordinate of the pixel</p>\n',
9986 type: 'Number'
9987 },
9988 {
9989 name: 'w',
9990 description: '<p>width</p>\n',
9991 type: 'Number'
9992 },
9993 {
9994 name: 'h',
9995 description: '<p>height</p>\n',
9996 type: 'Number'
9997 }
9998 ]
9999 },
10000 {
10001 params: []
10002 },
10003 {
10004 params: [
10005 {
10006 name: 'x',
10007 description: '',
10008 type: 'Number'
10009 },
10010 {
10011 name: 'y',
10012 description: '',
10013 type: 'Number'
10014 }
10015 ]
10016 }
10017 ]
10018 },
10019 set: {
10020 name: 'set',
10021 params: [
10022 {
10023 name: 'x',
10024 description: '<p>x-coordinate of the pixel</p>\n',
10025 type: 'Number'
10026 },
10027 {
10028 name: 'y',
10029 description: '<p>y-coordinate of the pixel</p>\n',
10030 type: 'Number'
10031 },
10032 {
10033 name: 'a',
10034 description:
10035 '<p>grayscale value | pixel array |\n a <a href="#/p5.Color">p5.Color</a> | image to copy</p>\n',
10036 type: 'Number|Number[]|Object'
10037 }
10038 ],
10039 class: 'p5.Image',
10040 module: 'Image'
10041 },
10042 resize: {
10043 name: 'resize',
10044 params: [
10045 {
10046 name: 'width',
10047 description: '<p>the resized image width</p>\n',
10048 type: 'Number'
10049 },
10050 {
10051 name: 'height',
10052 description: '<p>the resized image height</p>\n',
10053 type: 'Number'
10054 }
10055 ],
10056 class: 'p5.Image',
10057 module: 'Image'
10058 },
10059 copy: {
10060 name: 'copy',
10061 class: 'p5.Image',
10062 module: 'Image',
10063 overloads: [
10064 {
10065 params: [
10066 {
10067 name: 'srcImage',
10068 description: '<p>source image</p>\n',
10069 type: 'p5.Image|p5.Element'
10070 },
10071 {
10072 name: 'sx',
10073 description:
10074 "<p>X coordinate of the source's upper left corner</p>\n",
10075 type: 'Integer'
10076 },
10077 {
10078 name: 'sy',
10079 description:
10080 "<p>Y coordinate of the source's upper left corner</p>\n",
10081 type: 'Integer'
10082 },
10083 {
10084 name: 'sw',
10085 description: '<p>source image width</p>\n',
10086 type: 'Integer'
10087 },
10088 {
10089 name: 'sh',
10090 description: '<p>source image height</p>\n',
10091 type: 'Integer'
10092 },
10093 {
10094 name: 'dx',
10095 description:
10096 "<p>X coordinate of the destination's upper left corner</p>\n",
10097 type: 'Integer'
10098 },
10099 {
10100 name: 'dy',
10101 description:
10102 "<p>Y coordinate of the destination's upper left corner</p>\n",
10103 type: 'Integer'
10104 },
10105 {
10106 name: 'dw',
10107 description: '<p>destination image width</p>\n',
10108 type: 'Integer'
10109 },
10110 {
10111 name: 'dh',
10112 description: '<p>destination image height</p>\n',
10113 type: 'Integer'
10114 }
10115 ]
10116 },
10117 {
10118 params: [
10119 {
10120 name: 'sx',
10121 description: '',
10122 type: 'Integer'
10123 },
10124 {
10125 name: 'sy',
10126 description: '',
10127 type: 'Integer'
10128 },
10129 {
10130 name: 'sw',
10131 description: '',
10132 type: 'Integer'
10133 },
10134 {
10135 name: 'sh',
10136 description: '',
10137 type: 'Integer'
10138 },
10139 {
10140 name: 'dx',
10141 description: '',
10142 type: 'Integer'
10143 },
10144 {
10145 name: 'dy',
10146 description: '',
10147 type: 'Integer'
10148 },
10149 {
10150 name: 'dw',
10151 description: '',
10152 type: 'Integer'
10153 },
10154 {
10155 name: 'dh',
10156 description: '',
10157 type: 'Integer'
10158 }
10159 ]
10160 }
10161 ]
10162 },
10163 mask: {
10164 name: 'mask',
10165 params: [
10166 {
10167 name: 'srcImage',
10168 description: '<p>source image</p>\n',
10169 type: 'p5.Image'
10170 }
10171 ],
10172 class: 'p5.Image',
10173 module: 'Image'
10174 },
10175 filter: {
10176 name: 'filter',
10177 params: [
10178 {
10179 name: 'filterType',
10180 description:
10181 '<p>either THRESHOLD, GRAY, OPAQUE, INVERT,\n POSTERIZE, BLUR, ERODE, DILATE or BLUR.\n See Filters.js for docs on\n each available filter</p>\n',
10182 type: 'Constant'
10183 },
10184 {
10185 name: 'filterParam',
10186 description:
10187 '<p>an optional parameter unique\n to each filter, see above</p>\n',
10188 type: 'Number',
10189 optional: true
10190 }
10191 ],
10192 class: 'p5.Image',
10193 module: 'Image'
10194 },
10195 blend: {
10196 name: 'blend',
10197 class: 'p5.Image',
10198 module: 'Image',
10199 overloads: [
10200 {
10201 params: [
10202 {
10203 name: 'srcImage',
10204 description: '<p>source image</p>\n',
10205 type: 'p5.Image'
10206 },
10207 {
10208 name: 'sx',
10209 description:
10210 "<p>X coordinate of the source's upper left corner</p>\n",
10211 type: 'Integer'
10212 },
10213 {
10214 name: 'sy',
10215 description:
10216 "<p>Y coordinate of the source's upper left corner</p>\n",
10217 type: 'Integer'
10218 },
10219 {
10220 name: 'sw',
10221 description: '<p>source image width</p>\n',
10222 type: 'Integer'
10223 },
10224 {
10225 name: 'sh',
10226 description: '<p>source image height</p>\n',
10227 type: 'Integer'
10228 },
10229 {
10230 name: 'dx',
10231 description:
10232 "<p>X coordinate of the destination's upper left corner</p>\n",
10233 type: 'Integer'
10234 },
10235 {
10236 name: 'dy',
10237 description:
10238 "<p>Y coordinate of the destination's upper left corner</p>\n",
10239 type: 'Integer'
10240 },
10241 {
10242 name: 'dw',
10243 description: '<p>destination image width</p>\n',
10244 type: 'Integer'
10245 },
10246 {
10247 name: 'dh',
10248 description: '<p>destination image height</p>\n',
10249 type: 'Integer'
10250 },
10251 {
10252 name: 'blendMode',
10253 description:
10254 '<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',
10255 type: 'Constant'
10256 }
10257 ]
10258 },
10259 {
10260 params: [
10261 {
10262 name: 'sx',
10263 description: '',
10264 type: 'Integer'
10265 },
10266 {
10267 name: 'sy',
10268 description: '',
10269 type: 'Integer'
10270 },
10271 {
10272 name: 'sw',
10273 description: '',
10274 type: 'Integer'
10275 },
10276 {
10277 name: 'sh',
10278 description: '',
10279 type: 'Integer'
10280 },
10281 {
10282 name: 'dx',
10283 description: '',
10284 type: 'Integer'
10285 },
10286 {
10287 name: 'dy',
10288 description: '',
10289 type: 'Integer'
10290 },
10291 {
10292 name: 'dw',
10293 description: '',
10294 type: 'Integer'
10295 },
10296 {
10297 name: 'dh',
10298 description: '',
10299 type: 'Integer'
10300 },
10301 {
10302 name: 'blendMode',
10303 description: '',
10304 type: 'Constant'
10305 }
10306 ]
10307 }
10308 ]
10309 },
10310 save: {
10311 name: 'save',
10312 params: [
10313 {
10314 name: 'filename',
10315 description: '<p>give your file a name</p>\n',
10316 type: 'String'
10317 },
10318 {
10319 name: 'extension',
10320 description: "<p>'png' or 'jpg'</p>\n",
10321 type: 'String'
10322 }
10323 ],
10324 class: 'p5.Image',
10325 module: 'Image'
10326 },
10327 reset: {
10328 name: 'reset',
10329 class: 'p5.Image',
10330 module: 'Image'
10331 },
10332 getCurrentFrame: {
10333 name: 'getCurrentFrame',
10334 class: 'p5.Image',
10335 module: 'Image'
10336 },
10337 setFrame: {
10338 name: 'setFrame',
10339 params: [
10340 {
10341 name: 'index',
10342 description:
10343 '<p>the index for the frame that should be displayed</p>\n',
10344 type: 'Number'
10345 }
10346 ],
10347 class: 'p5.Image',
10348 module: 'Image'
10349 },
10350 numFrames: {
10351 name: 'numFrames',
10352 class: 'p5.Image',
10353 module: 'Image'
10354 },
10355 play: {
10356 name: 'play',
10357 class: 'p5.Image',
10358 module: 'Image'
10359 },
10360 pause: {
10361 name: 'pause',
10362 class: 'p5.Image',
10363 module: 'Image'
10364 },
10365 delay: {
10366 name: 'delay',
10367 params: [
10368 {
10369 name: 'd',
10370 description:
10371 '<p>the amount in milliseconds to delay between switching frames</p>\n',
10372 type: 'Number'
10373 },
10374 {
10375 name: 'index',
10376 description:
10377 '<p>the index of the frame that should have the new delay value {optional}</p>\n',
10378 type: 'Number',
10379 optional: true
10380 }
10381 ],
10382 class: 'p5.Image',
10383 module: 'Image'
10384 }
10385 },
10386 'p5.PrintWriter': {
10387 write: {
10388 name: 'write',
10389 params: [
10390 {
10391 name: 'data',
10392 description: '<p>all data to be written by the PrintWriter</p>\n',
10393 type: 'Array'
10394 }
10395 ],
10396 class: 'p5.PrintWriter',
10397 module: 'IO'
10398 },
10399 print: {
10400 name: 'print',
10401 params: [
10402 {
10403 name: 'data',
10404 description: '<p>all data to be printed by the PrintWriter</p>\n',
10405 type: 'Array'
10406 }
10407 ],
10408 class: 'p5.PrintWriter',
10409 module: 'IO'
10410 },
10411 clear: {
10412 name: 'clear',
10413 class: 'p5.PrintWriter',
10414 module: 'IO'
10415 },
10416 close: {
10417 name: 'close',
10418 class: 'p5.PrintWriter',
10419 module: 'IO'
10420 }
10421 },
10422 'p5.Table': {
10423 columns: {
10424 name: 'columns',
10425 class: 'p5.Table',
10426 module: 'IO'
10427 },
10428 rows: {
10429 name: 'rows',
10430 class: 'p5.Table',
10431 module: 'IO'
10432 },
10433 addRow: {
10434 name: 'addRow',
10435 params: [
10436 {
10437 name: 'row',
10438 description: '<p>row to be added to the table</p>\n',
10439 type: 'p5.TableRow',
10440 optional: true
10441 }
10442 ],
10443 class: 'p5.Table',
10444 module: 'IO'
10445 },
10446 removeRow: {
10447 name: 'removeRow',
10448 params: [
10449 {
10450 name: 'id',
10451 description: '<p>ID number of the row to remove</p>\n',
10452 type: 'Integer'
10453 }
10454 ],
10455 class: 'p5.Table',
10456 module: 'IO'
10457 },
10458 getRow: {
10459 name: 'getRow',
10460 params: [
10461 {
10462 name: 'rowID',
10463 description: '<p>ID number of the row to get</p>\n',
10464 type: 'Integer'
10465 }
10466 ],
10467 class: 'p5.Table',
10468 module: 'IO'
10469 },
10470 getRows: {
10471 name: 'getRows',
10472 class: 'p5.Table',
10473 module: 'IO'
10474 },
10475 findRow: {
10476 name: 'findRow',
10477 params: [
10478 {
10479 name: 'value',
10480 description: '<p>The value to match</p>\n',
10481 type: 'String'
10482 },
10483 {
10484 name: 'column',
10485 description:
10486 '<p>ID number or title of the\n column to search</p>\n',
10487 type: 'Integer|String'
10488 }
10489 ],
10490 class: 'p5.Table',
10491 module: 'IO'
10492 },
10493 findRows: {
10494 name: 'findRows',
10495 params: [
10496 {
10497 name: 'value',
10498 description: '<p>The value to match</p>\n',
10499 type: 'String'
10500 },
10501 {
10502 name: 'column',
10503 description:
10504 '<p>ID number or title of the\n column to search</p>\n',
10505 type: 'Integer|String'
10506 }
10507 ],
10508 class: 'p5.Table',
10509 module: 'IO'
10510 },
10511 matchRow: {
10512 name: 'matchRow',
10513 params: [
10514 {
10515 name: 'regexp',
10516 description: '<p>The regular expression to match</p>\n',
10517 type: 'String|RegExp'
10518 },
10519 {
10520 name: 'column',
10521 description:
10522 '<p>The column ID (number) or\n title (string)</p>\n',
10523 type: 'String|Integer'
10524 }
10525 ],
10526 class: 'p5.Table',
10527 module: 'IO'
10528 },
10529 matchRows: {
10530 name: 'matchRows',
10531 params: [
10532 {
10533 name: 'regexp',
10534 description: '<p>The regular expression to match</p>\n',
10535 type: 'String'
10536 },
10537 {
10538 name: 'column',
10539 description:
10540 '<p>The column ID (number) or\n title (string)</p>\n',
10541 type: 'String|Integer',
10542 optional: true
10543 }
10544 ],
10545 class: 'p5.Table',
10546 module: 'IO'
10547 },
10548 getColumn: {
10549 name: 'getColumn',
10550 params: [
10551 {
10552 name: 'column',
10553 description: '<p>String or Number of the column to return</p>\n',
10554 type: 'String|Number'
10555 }
10556 ],
10557 class: 'p5.Table',
10558 module: 'IO'
10559 },
10560 clearRows: {
10561 name: 'clearRows',
10562 class: 'p5.Table',
10563 module: 'IO'
10564 },
10565 addColumn: {
10566 name: 'addColumn',
10567 params: [
10568 {
10569 name: 'title',
10570 description: '<p>title of the given column</p>\n',
10571 type: 'String',
10572 optional: true
10573 }
10574 ],
10575 class: 'p5.Table',
10576 module: 'IO'
10577 },
10578 getColumnCount: {
10579 name: 'getColumnCount',
10580 class: 'p5.Table',
10581 module: 'IO'
10582 },
10583 getRowCount: {
10584 name: 'getRowCount',
10585 class: 'p5.Table',
10586 module: 'IO'
10587 },
10588 removeTokens: {
10589 name: 'removeTokens',
10590 params: [
10591 {
10592 name: 'chars',
10593 description: '<p>String listing characters to be removed</p>\n',
10594 type: 'String'
10595 },
10596 {
10597 name: 'column',
10598 description:
10599 '<p>Column ID (number)\n or name (string)</p>\n',
10600 type: 'String|Integer',
10601 optional: true
10602 }
10603 ],
10604 class: 'p5.Table',
10605 module: 'IO'
10606 },
10607 trim: {
10608 name: 'trim',
10609 params: [
10610 {
10611 name: 'column',
10612 description:
10613 '<p>Column ID (number)\n or name (string)</p>\n',
10614 type: 'String|Integer',
10615 optional: true
10616 }
10617 ],
10618 class: 'p5.Table',
10619 module: 'IO'
10620 },
10621 removeColumn: {
10622 name: 'removeColumn',
10623 params: [
10624 {
10625 name: 'column',
10626 description: '<p>columnName (string) or ID (number)</p>\n',
10627 type: 'String|Integer'
10628 }
10629 ],
10630 class: 'p5.Table',
10631 module: 'IO'
10632 },
10633 set: {
10634 name: 'set',
10635 params: [
10636 {
10637 name: 'row',
10638 description: '<p>row ID</p>\n',
10639 type: 'Integer'
10640 },
10641 {
10642 name: 'column',
10643 description:
10644 '<p>column ID (Number)\n or title (String)</p>\n',
10645 type: 'String|Integer'
10646 },
10647 {
10648 name: 'value',
10649 description: '<p>value to assign</p>\n',
10650 type: 'String|Number'
10651 }
10652 ],
10653 class: 'p5.Table',
10654 module: 'IO'
10655 },
10656 setNum: {
10657 name: 'setNum',
10658 params: [
10659 {
10660 name: 'row',
10661 description: '<p>row ID</p>\n',
10662 type: 'Integer'
10663 },
10664 {
10665 name: 'column',
10666 description:
10667 '<p>column ID (Number)\n or title (String)</p>\n',
10668 type: 'String|Integer'
10669 },
10670 {
10671 name: 'value',
10672 description: '<p>value to assign</p>\n',
10673 type: 'Number'
10674 }
10675 ],
10676 class: 'p5.Table',
10677 module: 'IO'
10678 },
10679 setString: {
10680 name: 'setString',
10681 params: [
10682 {
10683 name: 'row',
10684 description: '<p>row ID</p>\n',
10685 type: 'Integer'
10686 },
10687 {
10688 name: 'column',
10689 description:
10690 '<p>column ID (Number)\n or title (String)</p>\n',
10691 type: 'String|Integer'
10692 },
10693 {
10694 name: 'value',
10695 description: '<p>value to assign</p>\n',
10696 type: 'String'
10697 }
10698 ],
10699 class: 'p5.Table',
10700 module: 'IO'
10701 },
10702 get: {
10703 name: 'get',
10704 params: [
10705 {
10706 name: 'row',
10707 description: '<p>row ID</p>\n',
10708 type: 'Integer'
10709 },
10710 {
10711 name: 'column',
10712 description:
10713 '<p>columnName (string) or\n ID (number)</p>\n',
10714 type: 'String|Integer'
10715 }
10716 ],
10717 class: 'p5.Table',
10718 module: 'IO'
10719 },
10720 getNum: {
10721 name: 'getNum',
10722 params: [
10723 {
10724 name: 'row',
10725 description: '<p>row ID</p>\n',
10726 type: 'Integer'
10727 },
10728 {
10729 name: 'column',
10730 description:
10731 '<p>columnName (string) or\n ID (number)</p>\n',
10732 type: 'String|Integer'
10733 }
10734 ],
10735 class: 'p5.Table',
10736 module: 'IO'
10737 },
10738 getString: {
10739 name: 'getString',
10740 params: [
10741 {
10742 name: 'row',
10743 description: '<p>row ID</p>\n',
10744 type: 'Integer'
10745 },
10746 {
10747 name: 'column',
10748 description:
10749 '<p>columnName (string) or\n ID (number)</p>\n',
10750 type: 'String|Integer'
10751 }
10752 ],
10753 class: 'p5.Table',
10754 module: 'IO'
10755 },
10756 getObject: {
10757 name: 'getObject',
10758 params: [
10759 {
10760 name: 'headerColumn',
10761 description:
10762 '<p>Name of the column which should be used to\n title each row object (optional)</p>\n',
10763 type: 'String',
10764 optional: true
10765 }
10766 ],
10767 class: 'p5.Table',
10768 module: 'IO'
10769 },
10770 getArray: {
10771 name: 'getArray',
10772 class: 'p5.Table',
10773 module: 'IO'
10774 }
10775 },
10776 'p5.TableRow': {
10777 set: {
10778 name: 'set',
10779 params: [
10780 {
10781 name: 'column',
10782 description:
10783 '<p>Column ID (Number)\n or Title (String)</p>\n',
10784 type: 'String|Integer'
10785 },
10786 {
10787 name: 'value',
10788 description: '<p>The value to be stored</p>\n',
10789 type: 'String|Number'
10790 }
10791 ],
10792 class: 'p5.TableRow',
10793 module: 'IO'
10794 },
10795 setNum: {
10796 name: 'setNum',
10797 params: [
10798 {
10799 name: 'column',
10800 description:
10801 '<p>Column ID (Number)\n or Title (String)</p>\n',
10802 type: 'String|Integer'
10803 },
10804 {
10805 name: 'value',
10806 description:
10807 '<p>The value to be stored\n as a Float</p>\n',
10808 type: 'Number|String'
10809 }
10810 ],
10811 class: 'p5.TableRow',
10812 module: 'IO'
10813 },
10814 setString: {
10815 name: 'setString',
10816 params: [
10817 {
10818 name: 'column',
10819 description:
10820 '<p>Column ID (Number)\n or Title (String)</p>\n',
10821 type: 'String|Integer'
10822 },
10823 {
10824 name: 'value',
10825 description:
10826 '<p>The value to be stored\n as a String</p>\n',
10827 type: 'String|Number|Boolean|Object'
10828 }
10829 ],
10830 class: 'p5.TableRow',
10831 module: 'IO'
10832 },
10833 get: {
10834 name: 'get',
10835 params: [
10836 {
10837 name: 'column',
10838 description:
10839 '<p>columnName (string) or\n ID (number)</p>\n',
10840 type: 'String|Integer'
10841 }
10842 ],
10843 class: 'p5.TableRow',
10844 module: 'IO'
10845 },
10846 getNum: {
10847 name: 'getNum',
10848 params: [
10849 {
10850 name: 'column',
10851 description:
10852 '<p>columnName (string) or\n ID (number)</p>\n',
10853 type: 'String|Integer'
10854 }
10855 ],
10856 class: 'p5.TableRow',
10857 module: 'IO'
10858 },
10859 getString: {
10860 name: 'getString',
10861 params: [
10862 {
10863 name: 'column',
10864 description:
10865 '<p>columnName (string) or\n ID (number)</p>\n',
10866 type: 'String|Integer'
10867 }
10868 ],
10869 class: 'p5.TableRow',
10870 module: 'IO'
10871 }
10872 },
10873 'p5.XML': {
10874 getParent: {
10875 name: 'getParent',
10876 class: 'p5.XML',
10877 module: 'IO'
10878 },
10879 getName: {
10880 name: 'getName',
10881 class: 'p5.XML',
10882 module: 'IO'
10883 },
10884 setName: {
10885 name: 'setName',
10886 params: [
10887 {
10888 name: 'the',
10889 description: '<p>new name of the node</p>\n',
10890 type: 'String'
10891 }
10892 ],
10893 class: 'p5.XML',
10894 module: 'IO'
10895 },
10896 hasChildren: {
10897 name: 'hasChildren',
10898 class: 'p5.XML',
10899 module: 'IO'
10900 },
10901 listChildren: {
10902 name: 'listChildren',
10903 class: 'p5.XML',
10904 module: 'IO'
10905 },
10906 getChildren: {
10907 name: 'getChildren',
10908 params: [
10909 {
10910 name: 'name',
10911 description: '<p>element name</p>\n',
10912 type: 'String',
10913 optional: true
10914 }
10915 ],
10916 class: 'p5.XML',
10917 module: 'IO'
10918 },
10919 getChild: {
10920 name: 'getChild',
10921 params: [
10922 {
10923 name: 'name',
10924 description: '<p>element name or index</p>\n',
10925 type: 'String|Integer'
10926 }
10927 ],
10928 class: 'p5.XML',
10929 module: 'IO'
10930 },
10931 addChild: {
10932 name: 'addChild',
10933 params: [
10934 {
10935 name: 'node',
10936 description:
10937 '<p>a <a href="#/p5.XML">p5.XML</a> Object which will be the child to be added</p>\n',
10938 type: 'p5.XML'
10939 }
10940 ],
10941 class: 'p5.XML',
10942 module: 'IO'
10943 },
10944 removeChild: {
10945 name: 'removeChild',
10946 params: [
10947 {
10948 name: 'name',
10949 description: '<p>element name or index</p>\n',
10950 type: 'String|Integer'
10951 }
10952 ],
10953 class: 'p5.XML',
10954 module: 'IO'
10955 },
10956 getAttributeCount: {
10957 name: 'getAttributeCount',
10958 class: 'p5.XML',
10959 module: 'IO'
10960 },
10961 listAttributes: {
10962 name: 'listAttributes',
10963 class: 'p5.XML',
10964 module: 'IO'
10965 },
10966 hasAttribute: {
10967 name: 'hasAttribute',
10968 params: [
10969 {
10970 name: 'the',
10971 description: '<p>attribute to be checked</p>\n',
10972 type: 'String'
10973 }
10974 ],
10975 class: 'p5.XML',
10976 module: 'IO'
10977 },
10978 getNum: {
10979 name: 'getNum',
10980 params: [
10981 {
10982 name: 'name',
10983 description: '<p>the non-null full name of the attribute</p>\n',
10984 type: 'String'
10985 },
10986 {
10987 name: 'defaultValue',
10988 description: '<p>the default value of the attribute</p>\n',
10989 type: 'Number',
10990 optional: true
10991 }
10992 ],
10993 class: 'p5.XML',
10994 module: 'IO'
10995 },
10996 getString: {
10997 name: 'getString',
10998 params: [
10999 {
11000 name: 'name',
11001 description: '<p>the non-null full name of the attribute</p>\n',
11002 type: 'String'
11003 },
11004 {
11005 name: 'defaultValue',
11006 description: '<p>the default value of the attribute</p>\n',
11007 type: 'Number',
11008 optional: true
11009 }
11010 ],
11011 class: 'p5.XML',
11012 module: 'IO'
11013 },
11014 setAttribute: {
11015 name: 'setAttribute',
11016 params: [
11017 {
11018 name: 'name',
11019 description: '<p>the full name of the attribute</p>\n',
11020 type: 'String'
11021 },
11022 {
11023 name: 'value',
11024 description: '<p>the value of the attribute</p>\n',
11025 type: 'Number|String|Boolean'
11026 }
11027 ],
11028 class: 'p5.XML',
11029 module: 'IO'
11030 },
11031 getContent: {
11032 name: 'getContent',
11033 params: [
11034 {
11035 name: 'defaultValue',
11036 description: '<p>value returned if no content is found</p>\n',
11037 type: 'String',
11038 optional: true
11039 }
11040 ],
11041 class: 'p5.XML',
11042 module: 'IO'
11043 },
11044 setContent: {
11045 name: 'setContent',
11046 params: [
11047 {
11048 name: 'text',
11049 description: '<p>the new content</p>\n',
11050 type: 'String'
11051 }
11052 ],
11053 class: 'p5.XML',
11054 module: 'IO'
11055 },
11056 serialize: {
11057 name: 'serialize',
11058 class: 'p5.XML',
11059 module: 'IO'
11060 }
11061 },
11062 'p5.Vector': {
11063 x: {
11064 name: 'x',
11065 class: 'p5.Vector',
11066 module: 'Math'
11067 },
11068 y: {
11069 name: 'y',
11070 class: 'p5.Vector',
11071 module: 'Math'
11072 },
11073 z: {
11074 name: 'z',
11075 class: 'p5.Vector',
11076 module: 'Math'
11077 },
11078 toString: {
11079 name: 'toString',
11080 class: 'p5.Vector',
11081 module: 'Math'
11082 },
11083 set: {
11084 name: 'set',
11085 class: 'p5.Vector',
11086 module: 'Math',
11087 overloads: [
11088 {
11089 params: [
11090 {
11091 name: 'x',
11092 description: '<p>the x component of the vector</p>\n',
11093 type: 'Number',
11094 optional: true
11095 },
11096 {
11097 name: 'y',
11098 description: '<p>the y component of the vector</p>\n',
11099 type: 'Number',
11100 optional: true
11101 },
11102 {
11103 name: 'z',
11104 description: '<p>the z component of the vector</p>\n',
11105 type: 'Number',
11106 optional: true
11107 }
11108 ],
11109 chainable: 1
11110 },
11111 {
11112 params: [
11113 {
11114 name: 'value',
11115 description: '<p>the vector to set</p>\n',
11116 type: 'p5.Vector|Number[]'
11117 }
11118 ],
11119 chainable: 1
11120 }
11121 ]
11122 },
11123 copy: {
11124 name: 'copy',
11125 class: 'p5.Vector',
11126 module: 'Math'
11127 },
11128 add: {
11129 name: 'add',
11130 class: 'p5.Vector',
11131 module: 'Math',
11132 overloads: [
11133 {
11134 params: [
11135 {
11136 name: 'x',
11137 description: '<p>the x component of the vector to be added</p>\n',
11138 type: 'Number'
11139 },
11140 {
11141 name: 'y',
11142 description: '<p>the y component of the vector to be added</p>\n',
11143 type: 'Number',
11144 optional: true
11145 },
11146 {
11147 name: 'z',
11148 description: '<p>the z component of the vector to be added</p>\n',
11149 type: 'Number',
11150 optional: true
11151 }
11152 ],
11153 chainable: 1
11154 },
11155 {
11156 params: [
11157 {
11158 name: 'value',
11159 description: '<p>the vector to add</p>\n',
11160 type: 'p5.Vector|Number[]'
11161 }
11162 ],
11163 chainable: 1
11164 },
11165 {
11166 params: [
11167 {
11168 name: 'v1',
11169 description:
11170 '<p>a <a href="#/p5.Vector">p5.Vector</a> to add</p>\n',
11171 type: 'p5.Vector'
11172 },
11173 {
11174 name: 'v2',
11175 description:
11176 '<p>a <a href="#/p5.Vector">p5.Vector</a> to add</p>\n',
11177 type: 'p5.Vector'
11178 },
11179 {
11180 name: 'target',
11181 description: '<p>the vector to receive the result (Optional)</p>\n',
11182 type: 'p5.Vector',
11183 optional: true
11184 }
11185 ],
11186 static: 1
11187 }
11188 ]
11189 },
11190 rem: {
11191 name: 'rem',
11192 class: 'p5.Vector',
11193 module: 'Math',
11194 overloads: [
11195 {
11196 params: [
11197 {
11198 name: 'x',
11199 description: '<p>the x component of divisor vector</p>\n',
11200 type: 'Number'
11201 },
11202 {
11203 name: 'y',
11204 description: '<p>the y component of divisor vector</p>\n',
11205 type: 'Number'
11206 },
11207 {
11208 name: 'z',
11209 description: '<p>the z component of divisor vector</p>\n',
11210 type: 'Number'
11211 }
11212 ],
11213 chainable: 1
11214 },
11215 {
11216 params: [
11217 {
11218 name: 'value',
11219 description: '<p>divisor vector</p>\n',
11220 type: 'p5.Vector | Number[]'
11221 }
11222 ],
11223 chainable: 1
11224 },
11225 {
11226 params: [
11227 {
11228 name: 'v1',
11229 description:
11230 '<p>dividend <a href="#/p5.Vector">p5.Vector</a></p>\n',
11231 type: 'p5.Vector'
11232 },
11233 {
11234 name: 'v2',
11235 description: '<p>divisor <a href="#/p5.Vector">p5.Vector</a></p>\n',
11236 type: 'p5.Vector'
11237 }
11238 ],
11239 static: 1
11240 },
11241 {
11242 params: [
11243 {
11244 name: 'v1',
11245 description: '',
11246 type: 'p5.Vector'
11247 },
11248 {
11249 name: 'v2',
11250 description: '',
11251 type: 'p5.Vector'
11252 }
11253 ],
11254 static: 1
11255 }
11256 ]
11257 },
11258 sub: {
11259 name: 'sub',
11260 class: 'p5.Vector',
11261 module: 'Math',
11262 overloads: [
11263 {
11264 params: [
11265 {
11266 name: 'x',
11267 description: '<p>the x component of the vector to subtract</p>\n',
11268 type: 'Number'
11269 },
11270 {
11271 name: 'y',
11272 description: '<p>the y component of the vector to subtract</p>\n',
11273 type: 'Number',
11274 optional: true
11275 },
11276 {
11277 name: 'z',
11278 description: '<p>the z component of the vector to subtract</p>\n',
11279 type: 'Number',
11280 optional: true
11281 }
11282 ],
11283 chainable: 1
11284 },
11285 {
11286 params: [
11287 {
11288 name: 'value',
11289 description: '<p>the vector to subtract</p>\n',
11290 type: 'p5.Vector|Number[]'
11291 }
11292 ],
11293 chainable: 1
11294 },
11295 {
11296 params: [
11297 {
11298 name: 'v1',
11299 description:
11300 '<p>a <a href="#/p5.Vector">p5.Vector</a> to subtract from</p>\n',
11301 type: 'p5.Vector'
11302 },
11303 {
11304 name: 'v2',
11305 description:
11306 '<p>a <a href="#/p5.Vector">p5.Vector</a> to subtract</p>\n',
11307 type: 'p5.Vector'
11308 },
11309 {
11310 name: 'target',
11311 description: '<p>the vector to receive the result (Optional)</p>\n',
11312 type: 'p5.Vector',
11313 optional: true
11314 }
11315 ],
11316 static: 1
11317 }
11318 ]
11319 },
11320 mult: {
11321 name: 'mult',
11322 class: 'p5.Vector',
11323 module: 'Math',
11324 overloads: [
11325 {
11326 params: [
11327 {
11328 name: 'n',
11329 description: '<p>The number to multiply with the vector</p>\n',
11330 type: 'Number'
11331 }
11332 ],
11333 chainable: 1
11334 },
11335 {
11336 params: [
11337 {
11338 name: 'x',
11339 description:
11340 '<p>The number to multiply with the x component of the vector</p>\n',
11341 type: 'Number'
11342 },
11343 {
11344 name: 'y',
11345 description:
11346 '<p>The number to multiply with the y component of the vector</p>\n',
11347 type: 'Number'
11348 },
11349 {
11350 name: 'z',
11351 description:
11352 '<p>The number to multiply with the z component of the vector</p>\n',
11353 type: 'Number',
11354 optional: true
11355 }
11356 ],
11357 chainable: 1
11358 },
11359 {
11360 params: [
11361 {
11362 name: 'arr',
11363 description:
11364 '<p>The array to multiply with the components of the vector</p>\n',
11365 type: 'Number[]'
11366 }
11367 ],
11368 chainable: 1
11369 },
11370 {
11371 params: [
11372 {
11373 name: 'v',
11374 description:
11375 '<p>The vector to multiply with the components of the original vector</p>\n',
11376 type: 'p5.Vector'
11377 }
11378 ],
11379 chainable: 1
11380 },
11381 {
11382 params: [
11383 {
11384 name: 'x',
11385 description: '',
11386 type: 'Number'
11387 },
11388 {
11389 name: 'y',
11390 description: '',
11391 type: 'Number'
11392 },
11393 {
11394 name: 'z',
11395 description: '',
11396 type: 'Number',
11397 optional: true
11398 }
11399 ],
11400 static: 1
11401 },
11402 {
11403 params: [
11404 {
11405 name: 'v',
11406 description: '',
11407 type: 'p5.Vector'
11408 },
11409 {
11410 name: 'n',
11411 description: '',
11412 type: 'Number'
11413 },
11414 {
11415 name: 'target',
11416 description: '<p>the vector to receive the result (Optional)</p>\n',
11417 type: 'p5.Vector',
11418 optional: true
11419 }
11420 ],
11421 static: 1
11422 },
11423 {
11424 params: [
11425 {
11426 name: 'v0',
11427 description: '',
11428 type: 'p5.Vector'
11429 },
11430 {
11431 name: 'v1',
11432 description: '',
11433 type: 'p5.Vector'
11434 },
11435 {
11436 name: 'target',
11437 description: '',
11438 type: 'p5.Vector',
11439 optional: true
11440 }
11441 ],
11442 static: 1
11443 },
11444 {
11445 params: [
11446 {
11447 name: 'v0',
11448 description: '',
11449 type: 'p5.Vector'
11450 },
11451 {
11452 name: 'arr',
11453 description: '',
11454 type: 'Number[]'
11455 },
11456 {
11457 name: 'target',
11458 description: '',
11459 type: 'p5.Vector',
11460 optional: true
11461 }
11462 ],
11463 static: 1
11464 }
11465 ]
11466 },
11467 div: {
11468 name: 'div',
11469 class: 'p5.Vector',
11470 module: 'Math',
11471 overloads: [
11472 {
11473 params: [
11474 {
11475 name: 'n',
11476 description: '<p>The number to divide the vector by</p>\n',
11477 type: 'Number'
11478 }
11479 ],
11480 chainable: 1
11481 },
11482 {
11483 params: [
11484 {
11485 name: 'x',
11486 description:
11487 '<p>The number to divide with the x component of the vector</p>\n',
11488 type: 'Number'
11489 },
11490 {
11491 name: 'y',
11492 description:
11493 '<p>The number to divide with the y component of the vector</p>\n',
11494 type: 'Number'
11495 },
11496 {
11497 name: 'z',
11498 description:
11499 '<p>The number to divide with the z component of the vector</p>\n',
11500 type: 'Number',
11501 optional: true
11502 }
11503 ],
11504 chainable: 1
11505 },
11506 {
11507 params: [
11508 {
11509 name: 'arr',
11510 description:
11511 '<p>The array to divide the components of the vector by</p>\n',
11512 type: 'Number[]'
11513 }
11514 ],
11515 chainable: 1
11516 },
11517 {
11518 params: [
11519 {
11520 name: 'v',
11521 description:
11522 '<p>The vector to divide the components of the original vector by</p>\n',
11523 type: 'p5.Vector'
11524 }
11525 ],
11526 chainable: 1
11527 },
11528 {
11529 params: [
11530 {
11531 name: 'x',
11532 description: '',
11533 type: 'Number'
11534 },
11535 {
11536 name: 'y',
11537 description: '',
11538 type: 'Number'
11539 },
11540 {
11541 name: 'z',
11542 description: '',
11543 type: 'Number',
11544 optional: true
11545 }
11546 ],
11547 static: 1
11548 },
11549 {
11550 params: [
11551 {
11552 name: 'v',
11553 description: '',
11554 type: 'p5.Vector'
11555 },
11556 {
11557 name: 'n',
11558 description: '',
11559 type: 'Number'
11560 },
11561 {
11562 name: 'target',
11563 description: '<p>the vector to receive the result (Optional)</p>\n',
11564 type: 'p5.Vector',
11565 optional: true
11566 }
11567 ],
11568 static: 1
11569 },
11570 {
11571 params: [
11572 {
11573 name: 'v0',
11574 description: '',
11575 type: 'p5.Vector'
11576 },
11577 {
11578 name: 'v1',
11579 description: '',
11580 type: 'p5.Vector'
11581 },
11582 {
11583 name: 'target',
11584 description: '',
11585 type: 'p5.Vector',
11586 optional: true
11587 }
11588 ],
11589 static: 1
11590 },
11591 {
11592 params: [
11593 {
11594 name: 'v0',
11595 description: '',
11596 type: 'p5.Vector'
11597 },
11598 {
11599 name: 'arr',
11600 description: '',
11601 type: 'Number[]'
11602 },
11603 {
11604 name: 'target',
11605 description: '',
11606 type: 'p5.Vector',
11607 optional: true
11608 }
11609 ],
11610 static: 1
11611 }
11612 ]
11613 },
11614 mag: {
11615 name: 'mag',
11616 class: 'p5.Vector',
11617 module: 'Math',
11618 overloads: [
11619 {
11620 params: []
11621 },
11622 {
11623 params: [
11624 {
11625 name: 'vecT',
11626 description: '<p>the vector to return the magnitude of</p>\n',
11627 type: 'p5.Vector'
11628 }
11629 ],
11630 static: 1
11631 }
11632 ]
11633 },
11634 magSq: {
11635 name: 'magSq',
11636 class: 'p5.Vector',
11637 module: 'Math'
11638 },
11639 dot: {
11640 name: 'dot',
11641 class: 'p5.Vector',
11642 module: 'Math',
11643 overloads: [
11644 {
11645 params: [
11646 {
11647 name: 'x',
11648 description: '<p>x component of the vector</p>\n',
11649 type: 'Number'
11650 },
11651 {
11652 name: 'y',
11653 description: '<p>y component of the vector</p>\n',
11654 type: 'Number',
11655 optional: true
11656 },
11657 {
11658 name: 'z',
11659 description: '<p>z component of the vector</p>\n',
11660 type: 'Number',
11661 optional: true
11662 }
11663 ]
11664 },
11665 {
11666 params: [
11667 {
11668 name: 'value',
11669 description:
11670 '<p>value component of the vector or a <a href="#/p5.Vector">p5.Vector</a></p>\n',
11671 type: 'p5.Vector'
11672 }
11673 ]
11674 },
11675 {
11676 params: [
11677 {
11678 name: 'v1',
11679 description:
11680 '<p>the first <a href="#/p5.Vector">p5.Vector</a></p>\n',
11681 type: 'p5.Vector'
11682 },
11683 {
11684 name: 'v2',
11685 description:
11686 '<p>the second <a href="#/p5.Vector">p5.Vector</a></p>\n',
11687 type: 'p5.Vector'
11688 }
11689 ],
11690 static: 1
11691 }
11692 ]
11693 },
11694 cross: {
11695 name: 'cross',
11696 class: 'p5.Vector',
11697 module: 'Math',
11698 overloads: [
11699 {
11700 params: [
11701 {
11702 name: 'v',
11703 description:
11704 '<p><a href="#/p5.Vector">p5.Vector</a> to be crossed</p>\n',
11705 type: 'p5.Vector'
11706 }
11707 ]
11708 },
11709 {
11710 params: [
11711 {
11712 name: 'v1',
11713 description:
11714 '<p>the first <a href="#/p5.Vector">p5.Vector</a></p>\n',
11715 type: 'p5.Vector'
11716 },
11717 {
11718 name: 'v2',
11719 description:
11720 '<p>the second <a href="#/p5.Vector">p5.Vector</a></p>\n',
11721 type: 'p5.Vector'
11722 }
11723 ],
11724 static: 1
11725 }
11726 ]
11727 },
11728 dist: {
11729 name: 'dist',
11730 class: 'p5.Vector',
11731 module: 'Math',
11732 overloads: [
11733 {
11734 params: [
11735 {
11736 name: 'v',
11737 description:
11738 '<p>the x, y, and z coordinates of a <a href="#/p5.Vector">p5.Vector</a></p>\n',
11739 type: 'p5.Vector'
11740 }
11741 ]
11742 },
11743 {
11744 params: [
11745 {
11746 name: 'v1',
11747 description:
11748 '<p>the first <a href="#/p5.Vector">p5.Vector</a></p>\n',
11749 type: 'p5.Vector'
11750 },
11751 {
11752 name: 'v2',
11753 description:
11754 '<p>the second <a href="#/p5.Vector">p5.Vector</a></p>\n',
11755 type: 'p5.Vector'
11756 }
11757 ],
11758 static: 1
11759 }
11760 ]
11761 },
11762 normalize: {
11763 name: 'normalize',
11764 class: 'p5.Vector',
11765 module: 'Math'
11766 },
11767 limit: {
11768 name: 'limit',
11769 params: [
11770 {
11771 name: 'max',
11772 description: '<p>the maximum magnitude for the vector</p>\n',
11773 type: 'Number'
11774 }
11775 ],
11776 class: 'p5.Vector',
11777 module: 'Math'
11778 },
11779 setMag: {
11780 name: 'setMag',
11781 params: [
11782 {
11783 name: 'len',
11784 description: '<p>the new length for this vector</p>\n',
11785 type: 'Number'
11786 }
11787 ],
11788 class: 'p5.Vector',
11789 module: 'Math'
11790 },
11791 heading: {
11792 name: 'heading',
11793 class: 'p5.Vector',
11794 module: 'Math'
11795 },
11796 rotate: {
11797 name: 'rotate',
11798 params: [
11799 {
11800 name: 'angle',
11801 description: '<p>the angle of rotation</p>\n',
11802 type: 'Number'
11803 }
11804 ],
11805 class: 'p5.Vector',
11806 module: 'Math'
11807 },
11808 angleBetween: {
11809 name: 'angleBetween',
11810 params: [
11811 {
11812 name: 'value',
11813 description:
11814 '<p>the x, y, and z components of a <a href="#/p5.Vector">p5.Vector</a></p>\n',
11815 type: 'p5.Vector'
11816 }
11817 ],
11818 class: 'p5.Vector',
11819 module: 'Math'
11820 },
11821 lerp: {
11822 name: 'lerp',
11823 class: 'p5.Vector',
11824 module: 'Math',
11825 overloads: [
11826 {
11827 params: [
11828 {
11829 name: 'x',
11830 description: '<p>the x component</p>\n',
11831 type: 'Number'
11832 },
11833 {
11834 name: 'y',
11835 description: '<p>the y component</p>\n',
11836 type: 'Number'
11837 },
11838 {
11839 name: 'z',
11840 description: '<p>the z component</p>\n',
11841 type: 'Number'
11842 },
11843 {
11844 name: 'amt',
11845 description:
11846 '<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',
11847 type: 'Number'
11848 }
11849 ],
11850 chainable: 1
11851 },
11852 {
11853 params: [
11854 {
11855 name: 'v',
11856 description:
11857 '<p>the <a href="#/p5.Vector">p5.Vector</a> to lerp to</p>\n',
11858 type: 'p5.Vector'
11859 },
11860 {
11861 name: 'amt',
11862 description: '',
11863 type: 'Number'
11864 }
11865 ],
11866 chainable: 1
11867 },
11868 {
11869 params: [
11870 {
11871 name: 'v1',
11872 description: '',
11873 type: 'p5.Vector'
11874 },
11875 {
11876 name: 'v2',
11877 description: '',
11878 type: 'p5.Vector'
11879 },
11880 {
11881 name: 'amt',
11882 description: '',
11883 type: 'Number'
11884 },
11885 {
11886 name: 'target',
11887 description: '<p>the vector to receive the result (Optional)</p>\n',
11888 type: 'p5.Vector',
11889 optional: true
11890 }
11891 ],
11892 static: 1
11893 }
11894 ]
11895 },
11896 reflect: {
11897 name: 'reflect',
11898 params: [
11899 {
11900 name: 'surfaceNormal',
11901 description:
11902 '<p>the <a href="#/p5.Vector">p5.Vector</a> to reflect about, will be normalized by this method</p>\n',
11903 type: 'p5.Vector'
11904 }
11905 ],
11906 class: 'p5.Vector',
11907 module: 'Math'
11908 },
11909 array: {
11910 name: 'array',
11911 class: 'p5.Vector',
11912 module: 'Math'
11913 },
11914 equals: {
11915 name: 'equals',
11916 class: 'p5.Vector',
11917 module: 'Math',
11918 overloads: [
11919 {
11920 params: [
11921 {
11922 name: 'x',
11923 description: '<p>the x component of the vector</p>\n',
11924 type: 'Number',
11925 optional: true
11926 },
11927 {
11928 name: 'y',
11929 description: '<p>the y component of the vector</p>\n',
11930 type: 'Number',
11931 optional: true
11932 },
11933 {
11934 name: 'z',
11935 description: '<p>the z component of the vector</p>\n',
11936 type: 'Number',
11937 optional: true
11938 }
11939 ]
11940 },
11941 {
11942 params: [
11943 {
11944 name: 'value',
11945 description: '<p>the vector to compare</p>\n',
11946 type: 'p5.Vector|Array'
11947 }
11948 ]
11949 }
11950 ]
11951 },
11952 fromAngle: {
11953 name: 'fromAngle',
11954 params: [
11955 {
11956 name: 'angle',
11957 description:
11958 '<p>the desired angle, in radians (unaffected by <a href="#/p5/angleMode">angleMode</a>)</p>\n',
11959 type: 'Number'
11960 },
11961 {
11962 name: 'length',
11963 description: '<p>the length of the new vector (defaults to 1)</p>\n',
11964 type: 'Number',
11965 optional: true
11966 }
11967 ],
11968 class: 'p5.Vector',
11969 module: 'Math'
11970 },
11971 fromAngles: {
11972 name: 'fromAngles',
11973 params: [
11974 {
11975 name: 'theta',
11976 description: '<p>the polar angle, in radians (zero is up)</p>\n',
11977 type: 'Number'
11978 },
11979 {
11980 name: 'phi',
11981 description:
11982 '<p>the azimuthal angle, in radians\n (zero is out of the screen)</p>\n',
11983 type: 'Number'
11984 },
11985 {
11986 name: 'length',
11987 description: '<p>the length of the new vector (defaults to 1)</p>\n',
11988 type: 'Number',
11989 optional: true
11990 }
11991 ],
11992 class: 'p5.Vector',
11993 module: 'Math'
11994 },
11995 random2D: {
11996 name: 'random2D',
11997 class: 'p5.Vector',
11998 module: 'Math'
11999 },
12000 random3D: {
12001 name: 'random3D',
12002 class: 'p5.Vector',
12003 module: 'Math'
12004 }
12005 },
12006 'p5.Font': {
12007 font: {
12008 name: 'font',
12009 class: 'p5.Font',
12010 module: 'Typography'
12011 },
12012 textBounds: {
12013 name: 'textBounds',
12014 params: [
12015 {
12016 name: 'line',
12017 description: '<p>a line of text</p>\n',
12018 type: 'String'
12019 },
12020 {
12021 name: 'x',
12022 description: '<p>x-position</p>\n',
12023 type: 'Number'
12024 },
12025 {
12026 name: 'y',
12027 description: '<p>y-position</p>\n',
12028 type: 'Number'
12029 },
12030 {
12031 name: 'fontSize',
12032 description: '<p>font size to use (optional) Default is 12.</p>\n',
12033 type: 'Number',
12034 optional: true
12035 },
12036 {
12037 name: 'options',
12038 description:
12039 "<p>opentype options (optional)\n opentype fonts contains alignment and baseline options.\n Default is 'LEFT' and 'alphabetic'</p>\n",
12040 type: 'Object',
12041 optional: true
12042 }
12043 ],
12044 class: 'p5.Font',
12045 module: 'Typography'
12046 },
12047 textToPoints: {
12048 name: 'textToPoints',
12049 params: [
12050 {
12051 name: 'txt',
12052 description: '<p>a line of text</p>\n',
12053 type: 'String'
12054 },
12055 {
12056 name: 'x',
12057 description: '<p>x-position</p>\n',
12058 type: 'Number'
12059 },
12060 {
12061 name: 'y',
12062 description: '<p>y-position</p>\n',
12063 type: 'Number'
12064 },
12065 {
12066 name: 'fontSize',
12067 description: '<p>font size to use (optional)</p>\n',
12068 type: 'Number'
12069 },
12070 {
12071 name: 'options',
12072 description:
12073 '<p>an (optional) object that can contain:</p>\n<p><br>sampleFactor - the ratio of path-length to number of samples\n(default=.1); 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',
12074 type: 'Object',
12075 optional: true
12076 }
12077 ],
12078 class: 'p5.Font',
12079 module: 'Typography'
12080 }
12081 },
12082 'p5.Camera': {
12083 perspective: {
12084 name: 'perspective',
12085 class: 'p5.Camera',
12086 module: 'Lights, Camera'
12087 },
12088 ortho: {
12089 name: 'ortho',
12090 class: 'p5.Camera',
12091 module: 'Lights, Camera'
12092 },
12093 frustum: {
12094 name: 'frustum',
12095 class: 'p5.Camera',
12096 module: 'Lights, Camera'
12097 },
12098 pan: {
12099 name: 'pan',
12100 params: [
12101 {
12102 name: 'angle',
12103 description:
12104 '<p>amount to rotate camera in current\n<a href="#/p5/angleMode">angleMode</a> units.\nGreater than 0 values rotate counterclockwise (to the left).</p>\n',
12105 type: 'Number'
12106 }
12107 ],
12108 class: 'p5.Camera',
12109 module: 'Lights, Camera'
12110 },
12111 tilt: {
12112 name: 'tilt',
12113 params: [
12114 {
12115 name: 'angle',
12116 description:
12117 '<p>amount to rotate camera in current\n<a href="#/p5/angleMode">angleMode</a> units.\nGreater than 0 values rotate counterclockwise (to the left).</p>\n',
12118 type: 'Number'
12119 }
12120 ],
12121 class: 'p5.Camera',
12122 module: 'Lights, Camera'
12123 },
12124 lookAt: {
12125 name: 'lookAt',
12126 params: [
12127 {
12128 name: 'x',
12129 description: '<p>x position of a point in world space</p>\n',
12130 type: 'Number'
12131 },
12132 {
12133 name: 'y',
12134 description: '<p>y position of a point in world space</p>\n',
12135 type: 'Number'
12136 },
12137 {
12138 name: 'z',
12139 description: '<p>z position of a point in world space</p>\n',
12140 type: 'Number'
12141 }
12142 ],
12143 class: 'p5.Camera',
12144 module: 'Lights, Camera'
12145 },
12146 camera: {
12147 name: 'camera',
12148 class: 'p5.Camera',
12149 module: 'Lights, Camera'
12150 },
12151 move: {
12152 name: 'move',
12153 params: [
12154 {
12155 name: 'x',
12156 description: "<p>amount to move along camera's left-right axis</p>\n",
12157 type: 'Number'
12158 },
12159 {
12160 name: 'y',
12161 description: "<p>amount to move along camera's up-down axis</p>\n",
12162 type: 'Number'
12163 },
12164 {
12165 name: 'z',
12166 description:
12167 "<p>amount to move along camera's forward-backward axis</p>\n",
12168 type: 'Number'
12169 }
12170 ],
12171 class: 'p5.Camera',
12172 module: 'Lights, Camera'
12173 },
12174 setPosition: {
12175 name: 'setPosition',
12176 params: [
12177 {
12178 name: 'x',
12179 description: '<p>x position of a point in world space</p>\n',
12180 type: 'Number'
12181 },
12182 {
12183 name: 'y',
12184 description: '<p>y position of a point in world space</p>\n',
12185 type: 'Number'
12186 },
12187 {
12188 name: 'z',
12189 description: '<p>z position of a point in world space</p>\n',
12190 type: 'Number'
12191 }
12192 ],
12193 class: 'p5.Camera',
12194 module: 'Lights, Camera'
12195 }
12196 },
12197 'p5.Geometry': {
12198 computeFaces: {
12199 name: 'computeFaces',
12200 class: 'p5.Geometry',
12201 module: 'Lights, Camera'
12202 },
12203 computeNormals: {
12204 name: 'computeNormals',
12205 class: 'p5.Geometry',
12206 module: 'Lights, Camera'
12207 },
12208 averageNormals: {
12209 name: 'averageNormals',
12210 class: 'p5.Geometry',
12211 module: 'Lights, Camera'
12212 },
12213 averagePoleNormals: {
12214 name: 'averagePoleNormals',
12215 class: 'p5.Geometry',
12216 module: 'Lights, Camera'
12217 },
12218 normalize: {
12219 name: 'normalize',
12220 class: 'p5.Geometry',
12221 module: 'Lights, Camera'
12222 }
12223 },
12224 'p5.Shader': {
12225 setUniform: {
12226 name: 'setUniform',
12227 params: [
12228 {
12229 name: 'uniformName',
12230 description: '<p>the name of the uniform in the\nshader program</p>\n',
12231 type: 'String'
12232 },
12233 {
12234 name: 'data',
12235 description:
12236 '<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',
12237 type: 'Object|Number|Boolean|Number[]'
12238 }
12239 ],
12240 class: 'p5.Shader',
12241 module: 'Lights, Camera'
12242 }
12243 },
12244 'p5.sound': {
12245 getMasterVolume: {
12246 name: 'getMasterVolume',
12247 class: 'p5.sound',
12248 module: 'p5.sound'
12249 },
12250 masterVolume: {
12251 name: 'masterVolume',
12252 params: [
12253 {
12254 name: 'volume',
12255 description:
12256 '<p>Volume (amplitude) between 0.0\n and 1.0 or modulating signal/oscillator</p>\n',
12257 type: 'Number|Object'
12258 },
12259 {
12260 name: 'rampTime',
12261 description: '<p>Fade for t seconds</p>\n',
12262 type: 'Number',
12263 optional: true
12264 },
12265 {
12266 name: 'timeFromNow',
12267 description:
12268 '<p>Schedule this event to happen at\n t seconds in the future</p>\n',
12269 type: 'Number',
12270 optional: true
12271 }
12272 ],
12273 class: 'p5.sound',
12274 module: 'p5.sound'
12275 },
12276 soundOut: {
12277 name: 'soundOut',
12278 class: 'p5.sound',
12279 module: 'p5.sound'
12280 }
12281 },
12282 'p5.Effect': {
12283 amp: {
12284 name: 'amp',
12285 params: [
12286 {
12287 name: 'vol',
12288 description: '<p>amplitude between 0 and 1.0</p>\n',
12289 type: 'Number',
12290 optional: true
12291 },
12292 {
12293 name: 'rampTime',
12294 description: '<p>create a fade that lasts until rampTime</p>\n',
12295 type: 'Number',
12296 optional: true
12297 },
12298 {
12299 name: 'tFromNow',
12300 description:
12301 '<p>schedule this event to happen in tFromNow seconds</p>\n',
12302 type: 'Number',
12303 optional: true
12304 }
12305 ],
12306 class: 'p5.Effect',
12307 module: 'p5.sound'
12308 },
12309 chain: {
12310 name: 'chain',
12311 params: [
12312 {
12313 name: 'arguments',
12314 description: '<p>Chain together multiple sound objects</p>\n',
12315 type: 'Object',
12316 optional: true
12317 }
12318 ],
12319 class: 'p5.Effect',
12320 module: 'p5.sound'
12321 },
12322 drywet: {
12323 name: 'drywet',
12324 params: [
12325 {
12326 name: 'fade',
12327 description: '<p>The desired drywet value (0 - 1.0)</p>\n',
12328 type: 'Number',
12329 optional: true
12330 }
12331 ],
12332 class: 'p5.Effect',
12333 module: 'p5.sound'
12334 },
12335 connect: {
12336 name: 'connect',
12337 params: [
12338 {
12339 name: 'unit',
12340 description: '',
12341 type: 'Object'
12342 }
12343 ],
12344 class: 'p5.Effect',
12345 module: 'p5.sound'
12346 },
12347 disconnect: {
12348 name: 'disconnect',
12349 class: 'p5.Effect',
12350 module: 'p5.sound'
12351 }
12352 },
12353 'p5.Filter': {
12354 biquadFilter: {
12355 name: 'biquadFilter',
12356 class: 'p5.Filter',
12357 module: 'p5.sound'
12358 },
12359 process: {
12360 name: 'process',
12361 params: [
12362 {
12363 name: 'Signal',
12364 description: '<p>An object that outputs audio</p>\n',
12365 type: 'Object'
12366 },
12367 {
12368 name: 'freq',
12369 description: '<p>Frequency in Hz, from 10 to 22050</p>\n',
12370 type: 'Number',
12371 optional: true
12372 },
12373 {
12374 name: 'res',
12375 description:
12376 '<p>Resonance/Width of the filter frequency\n from 0.001 to 1000</p>\n',
12377 type: 'Number',
12378 optional: true
12379 }
12380 ],
12381 class: 'p5.Filter',
12382 module: 'p5.sound'
12383 },
12384 set: {
12385 name: 'set',
12386 params: [
12387 {
12388 name: 'freq',
12389 description: '<p>Frequency in Hz, from 10 to 22050</p>\n',
12390 type: 'Number',
12391 optional: true
12392 },
12393 {
12394 name: 'res',
12395 description: '<p>Resonance (Q) from 0.001 to 1000</p>\n',
12396 type: 'Number',
12397 optional: true
12398 },
12399 {
12400 name: 'timeFromNow',
12401 description:
12402 '<p>schedule this event to happen\n seconds from now</p>\n',
12403 type: 'Number',
12404 optional: true
12405 }
12406 ],
12407 class: 'p5.Filter',
12408 module: 'p5.sound'
12409 },
12410 freq: {
12411 name: 'freq',
12412 params: [
12413 {
12414 name: 'freq',
12415 description: '<p>Filter Frequency</p>\n',
12416 type: 'Number'
12417 },
12418 {
12419 name: 'timeFromNow',
12420 description:
12421 '<p>schedule this event to happen\n seconds from now</p>\n',
12422 type: 'Number',
12423 optional: true
12424 }
12425 ],
12426 class: 'p5.Filter',
12427 module: 'p5.sound'
12428 },
12429 res: {
12430 name: 'res',
12431 params: [
12432 {
12433 name: 'res',
12434 description:
12435 '<p>Resonance/Width of filter freq\n from 0.001 to 1000</p>\n',
12436 type: 'Number'
12437 },
12438 {
12439 name: 'timeFromNow',
12440 description:
12441 '<p>schedule this event to happen\n seconds from now</p>\n',
12442 type: 'Number',
12443 optional: true
12444 }
12445 ],
12446 class: 'p5.Filter',
12447 module: 'p5.sound'
12448 },
12449 gain: {
12450 name: 'gain',
12451 params: [
12452 {
12453 name: 'gain',
12454 description: '',
12455 type: 'Number'
12456 }
12457 ],
12458 class: 'p5.Filter',
12459 module: 'p5.sound'
12460 },
12461 toggle: {
12462 name: 'toggle',
12463 class: 'p5.Filter',
12464 module: 'p5.sound'
12465 },
12466 setType: {
12467 name: 'setType',
12468 params: [
12469 {
12470 name: 't',
12471 description: '',
12472 type: 'String'
12473 }
12474 ],
12475 class: 'p5.Filter',
12476 module: 'p5.sound'
12477 }
12478 },
12479 'p5.Oscillator': {
12480 start: {
12481 name: 'start',
12482 params: [
12483 {
12484 name: 'time',
12485 description: '<p>startTime in seconds from now.</p>\n',
12486 type: 'Number',
12487 optional: true
12488 },
12489 {
12490 name: 'frequency',
12491 description: '<p>frequency in Hz.</p>\n',
12492 type: 'Number',
12493 optional: true
12494 }
12495 ],
12496 class: 'p5.Oscillator',
12497 module: 'p5.sound'
12498 },
12499 stop: {
12500 name: 'stop',
12501 params: [
12502 {
12503 name: 'secondsFromNow',
12504 description: '<p>Time, in seconds from now.</p>\n',
12505 type: 'Number'
12506 }
12507 ],
12508 class: 'p5.Oscillator',
12509 module: 'p5.sound'
12510 },
12511 amp: {
12512 name: 'amp',
12513 params: [
12514 {
12515 name: 'vol',
12516 description:
12517 '<p>between 0 and 1.0\n or a modulating signal/oscillator</p>\n',
12518 type: 'Number|Object'
12519 },
12520 {
12521 name: 'rampTime',
12522 description: '<p>create a fade that lasts rampTime</p>\n',
12523 type: 'Number',
12524 optional: true
12525 },
12526 {
12527 name: 'timeFromNow',
12528 description:
12529 '<p>schedule this event to happen\n seconds from now</p>\n',
12530 type: 'Number',
12531 optional: true
12532 }
12533 ],
12534 class: 'p5.Oscillator',
12535 module: 'p5.sound'
12536 },
12537 freq: {
12538 name: 'freq',
12539 params: [
12540 {
12541 name: 'Frequency',
12542 description:
12543 '<p>Frequency in Hz\n or modulating signal/oscillator</p>\n',
12544 type: 'Number|Object'
12545 },
12546 {
12547 name: 'rampTime',
12548 description: '<p>Ramp time (in seconds)</p>\n',
12549 type: 'Number',
12550 optional: true
12551 },
12552 {
12553 name: 'timeFromNow',
12554 description:
12555 '<p>Schedule this event to happen\n at x seconds from now</p>\n',
12556 type: 'Number',
12557 optional: true
12558 }
12559 ],
12560 class: 'p5.Oscillator',
12561 module: 'p5.sound'
12562 },
12563 setType: {
12564 name: 'setType',
12565 params: [
12566 {
12567 name: 'type',
12568 description: "<p>'sine', 'triangle', 'sawtooth' or 'square'.</p>\n",
12569 type: 'String'
12570 }
12571 ],
12572 class: 'p5.Oscillator',
12573 module: 'p5.sound'
12574 },
12575 connect: {
12576 name: 'connect',
12577 params: [
12578 {
12579 name: 'unit',
12580 description: '<p>A p5.sound or Web Audio object</p>\n',
12581 type: 'Object'
12582 }
12583 ],
12584 class: 'p5.Oscillator',
12585 module: 'p5.sound'
12586 },
12587 disconnect: {
12588 name: 'disconnect',
12589 class: 'p5.Oscillator',
12590 module: 'p5.sound'
12591 },
12592 pan: {
12593 name: 'pan',
12594 params: [
12595 {
12596 name: 'panning',
12597 description: '<p>Number between -1 and 1</p>\n',
12598 type: 'Number'
12599 },
12600 {
12601 name: 'timeFromNow',
12602 description:
12603 '<p>schedule this event to happen\n seconds from now</p>\n',
12604 type: 'Number'
12605 }
12606 ],
12607 class: 'p5.Oscillator',
12608 module: 'p5.sound'
12609 },
12610 phase: {
12611 name: 'phase',
12612 params: [
12613 {
12614 name: 'phase',
12615 description: '<p>float between 0.0 and 1.0</p>\n',
12616 type: 'Number'
12617 }
12618 ],
12619 class: 'p5.Oscillator',
12620 module: 'p5.sound'
12621 },
12622 add: {
12623 name: 'add',
12624 params: [
12625 {
12626 name: 'number',
12627 description: '<p>Constant number to add</p>\n',
12628 type: 'Number'
12629 }
12630 ],
12631 class: 'p5.Oscillator',
12632 module: 'p5.sound'
12633 },
12634 mult: {
12635 name: 'mult',
12636 params: [
12637 {
12638 name: 'number',
12639 description: '<p>Constant number to multiply</p>\n',
12640 type: 'Number'
12641 }
12642 ],
12643 class: 'p5.Oscillator',
12644 module: 'p5.sound'
12645 },
12646 scale: {
12647 name: 'scale',
12648 params: [
12649 {
12650 name: 'inMin',
12651 description: '<p>input range minumum</p>\n',
12652 type: 'Number'
12653 },
12654 {
12655 name: 'inMax',
12656 description: '<p>input range maximum</p>\n',
12657 type: 'Number'
12658 },
12659 {
12660 name: 'outMin',
12661 description: '<p>input range minumum</p>\n',
12662 type: 'Number'
12663 },
12664 {
12665 name: 'outMax',
12666 description: '<p>input range maximum</p>\n',
12667 type: 'Number'
12668 }
12669 ],
12670 class: 'p5.Oscillator',
12671 module: 'p5.sound'
12672 }
12673 },
12674 'p5.MonoSynth': {
12675 play: {
12676 name: 'play',
12677 params: [
12678 {
12679 name: 'note',
12680 description:
12681 '<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 ("C4", "Eb3"...etc")\n See <a href = "https://github.com/Tonejs/Tone.js/wiki/Instruments">\n Tone</a>. Defaults to 440 hz.</p>\n',
12682 type: 'String | Number'
12683 },
12684 {
12685 name: 'velocity',
12686 description:
12687 '<p>velocity of the note to play (ranging from 0 to 1)</p>\n',
12688 type: 'Number',
12689 optional: true
12690 },
12691 {
12692 name: 'secondsFromNow',
12693 description: '<p>time from now (in seconds) at which to play</p>\n',
12694 type: 'Number',
12695 optional: true
12696 },
12697 {
12698 name: 'sustainTime',
12699 description:
12700 '<p>time to sustain before releasing the envelope. Defaults to 0.15 seconds.</p>\n',
12701 type: 'Number',
12702 optional: true
12703 }
12704 ],
12705 class: 'p5.MonoSynth',
12706 module: 'p5.sound'
12707 },
12708 triggerAttack: {
12709 params: [
12710 {
12711 name: 'note',
12712 description:
12713 '<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 ("C4", "Eb3"...etc")\n See <a href = "https://github.com/Tonejs/Tone.js/wiki/Instruments">\n Tone</a>. Defaults to 440 hz</p>\n',
12714 type: 'String | Number'
12715 },
12716 {
12717 name: 'velocity',
12718 description:
12719 '<p>velocity of the note to play (ranging from 0 to 1)</p>\n',
12720 type: 'Number',
12721 optional: true
12722 },
12723 {
12724 name: 'secondsFromNow',
12725 description: '<p>time from now (in seconds) at which to play</p>\n',
12726 type: 'Number',
12727 optional: true
12728 }
12729 ],
12730 name: 'triggerAttack',
12731 class: 'p5.MonoSynth',
12732 module: 'p5.sound'
12733 },
12734 triggerRelease: {
12735 params: [
12736 {
12737 name: 'secondsFromNow',
12738 description: '<p>time to trigger the release</p>\n',
12739 type: 'Number'
12740 }
12741 ],
12742 name: 'triggerRelease',
12743 class: 'p5.MonoSynth',
12744 module: 'p5.sound'
12745 },
12746 setADSR: {
12747 name: 'setADSR',
12748 params: [
12749 {
12750 name: 'attackTime',
12751 description:
12752 '<p>Time (in seconds before envelope\n reaches Attack Level</p>\n',
12753 type: 'Number'
12754 },
12755 {
12756 name: 'decayTime',
12757 description:
12758 '<p>Time (in seconds) before envelope\n reaches Decay/Sustain Level</p>\n',
12759 type: 'Number',
12760 optional: true
12761 },
12762 {
12763 name: 'susRatio',
12764 description:
12765 '<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',
12766 type: 'Number',
12767 optional: true
12768 },
12769 {
12770 name: 'releaseTime',
12771 description: '<p>Time in seconds from now (defaults to 0)</p>\n',
12772 type: 'Number',
12773 optional: true
12774 }
12775 ],
12776 class: 'p5.MonoSynth',
12777 module: 'p5.sound'
12778 },
12779 attack: {
12780 name: 'attack',
12781 class: 'p5.MonoSynth',
12782 module: 'p5.sound'
12783 },
12784 decay: {
12785 name: 'decay',
12786 class: 'p5.MonoSynth',
12787 module: 'p5.sound'
12788 },
12789 sustain: {
12790 name: 'sustain',
12791 class: 'p5.MonoSynth',
12792 module: 'p5.sound'
12793 },
12794 release: {
12795 name: 'release',
12796 class: 'p5.MonoSynth',
12797 module: 'p5.sound'
12798 },
12799 amp: {
12800 name: 'amp',
12801 params: [
12802 {
12803 name: 'vol',
12804 description: '<p>desired volume</p>\n',
12805 type: 'Number'
12806 },
12807 {
12808 name: 'rampTime',
12809 description: '<p>Time to reach new volume</p>\n',
12810 type: 'Number',
12811 optional: true
12812 }
12813 ],
12814 class: 'p5.MonoSynth',
12815 module: 'p5.sound'
12816 },
12817 connect: {
12818 name: 'connect',
12819 params: [
12820 {
12821 name: 'unit',
12822 description: '<p>A p5.sound or Web Audio object</p>\n',
12823 type: 'Object'
12824 }
12825 ],
12826 class: 'p5.MonoSynth',
12827 module: 'p5.sound'
12828 },
12829 disconnect: {
12830 name: 'disconnect',
12831 class: 'p5.MonoSynth',
12832 module: 'p5.sound'
12833 },
12834 dispose: {
12835 name: 'dispose',
12836 class: 'p5.MonoSynth',
12837 module: 'p5.sound'
12838 }
12839 },
12840 'p5.AudioVoice': {
12841 connect: {
12842 name: 'connect',
12843 params: [
12844 {
12845 name: 'unit',
12846 description: '',
12847 type: 'Object'
12848 }
12849 ],
12850 class: 'p5.AudioVoice',
12851 module: 'p5.sound'
12852 },
12853 disconnect: {
12854 name: 'disconnect',
12855 class: 'p5.AudioVoice',
12856 module: 'p5.sound'
12857 }
12858 },
12859 'p5.PolySynth': {
12860 notes: {
12861 name: 'notes',
12862 class: 'p5.PolySynth',
12863 module: 'p5.sound'
12864 },
12865 polyvalue: {
12866 name: 'polyvalue',
12867 class: 'p5.PolySynth',
12868 module: 'p5.sound'
12869 },
12870 AudioVoice: {
12871 name: 'AudioVoice',
12872 class: 'p5.PolySynth',
12873 module: 'p5.sound'
12874 },
12875 play: {
12876 name: 'play',
12877 params: [
12878 {
12879 name: 'note',
12880 description:
12881 '<p>midi note to play (ranging from 0 to 127 - 60 being a middle C)</p>\n',
12882 type: 'Number',
12883 optional: true
12884 },
12885 {
12886 name: 'velocity',
12887 description:
12888 '<p>velocity of the note to play (ranging from 0 to 1)</p>\n',
12889 type: 'Number',
12890 optional: true
12891 },
12892 {
12893 name: 'secondsFromNow',
12894 description: '<p>time from now (in seconds) at which to play</p>\n',
12895 type: 'Number',
12896 optional: true
12897 },
12898 {
12899 name: 'sustainTime',
12900 description: '<p>time to sustain before releasing the envelope</p>\n',
12901 type: 'Number',
12902 optional: true
12903 }
12904 ],
12905 class: 'p5.PolySynth',
12906 module: 'p5.sound'
12907 },
12908 noteADSR: {
12909 name: 'noteADSR',
12910 params: [
12911 {
12912 name: 'note',
12913 description: '<p>Midi note on which ADSR should be set.</p>\n',
12914 type: 'Number',
12915 optional: true
12916 },
12917 {
12918 name: 'attackTime',
12919 description:
12920 '<p>Time (in seconds before envelope\n reaches Attack Level</p>\n',
12921 type: 'Number',
12922 optional: true
12923 },
12924 {
12925 name: 'decayTime',
12926 description:
12927 '<p>Time (in seconds) before envelope\n reaches Decay/Sustain Level</p>\n',
12928 type: 'Number',
12929 optional: true
12930 },
12931 {
12932 name: 'susRatio',
12933 description:
12934 '<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',
12935 type: 'Number',
12936 optional: true
12937 },
12938 {
12939 name: 'releaseTime',
12940 description: '<p>Time in seconds from now (defaults to 0)</p>\n',
12941 type: 'Number',
12942 optional: true
12943 }
12944 ],
12945 class: 'p5.PolySynth',
12946 module: 'p5.sound'
12947 },
12948 setADSR: {
12949 name: 'setADSR',
12950 params: [
12951 {
12952 name: 'attackTime',
12953 description:
12954 '<p>Time (in seconds before envelope\n reaches Attack Level</p>\n',
12955 type: 'Number',
12956 optional: true
12957 },
12958 {
12959 name: 'decayTime',
12960 description:
12961 '<p>Time (in seconds) before envelope\n reaches Decay/Sustain Level</p>\n',
12962 type: 'Number',
12963 optional: true
12964 },
12965 {
12966 name: 'susRatio',
12967 description:
12968 '<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',
12969 type: 'Number',
12970 optional: true
12971 },
12972 {
12973 name: 'releaseTime',
12974 description: '<p>Time in seconds from now (defaults to 0)</p>\n',
12975 type: 'Number',
12976 optional: true
12977 }
12978 ],
12979 class: 'p5.PolySynth',
12980 module: 'p5.sound'
12981 },
12982 noteAttack: {
12983 name: 'noteAttack',
12984 params: [
12985 {
12986 name: 'note',
12987 description: '<p>midi note on which attack should be triggered.</p>\n',
12988 type: 'Number',
12989 optional: true
12990 },
12991 {
12992 name: 'velocity',
12993 description:
12994 '<p>velocity of the note to play (ranging from 0 to 1)/</p>\n',
12995 type: 'Number',
12996 optional: true
12997 },
12998 {
12999 name: 'secondsFromNow',
13000 description: '<p>time from now (in seconds)</p>\n',
13001 type: 'Number',
13002 optional: true
13003 }
13004 ],
13005 class: 'p5.PolySynth',
13006 module: 'p5.sound'
13007 },
13008 noteRelease: {
13009 name: 'noteRelease',
13010 params: [
13011 {
13012 name: 'note',
13013 description:
13014 '<p>midi note on which attack should be triggered.\n If no value is provided, all notes will be released.</p>\n',
13015 type: 'Number',
13016 optional: true
13017 },
13018 {
13019 name: 'secondsFromNow',
13020 description: '<p>time to trigger the release</p>\n',
13021 type: 'Number',
13022 optional: true
13023 }
13024 ],
13025 class: 'p5.PolySynth',
13026 module: 'p5.sound'
13027 },
13028 connect: {
13029 name: 'connect',
13030 params: [
13031 {
13032 name: 'unit',
13033 description: '<p>A p5.sound or Web Audio object</p>\n',
13034 type: 'Object'
13035 }
13036 ],
13037 class: 'p5.PolySynth',
13038 module: 'p5.sound'
13039 },
13040 disconnect: {
13041 name: 'disconnect',
13042 class: 'p5.PolySynth',
13043 module: 'p5.sound'
13044 },
13045 dispose: {
13046 name: 'dispose',
13047 class: 'p5.PolySynth',
13048 module: 'p5.sound'
13049 }
13050 },
13051 'p5.SoundFile': {
13052 isLoaded: {
13053 name: 'isLoaded',
13054 class: 'p5.SoundFile',
13055 module: 'p5.sound'
13056 },
13057 play: {
13058 name: 'play',
13059 params: [
13060 {
13061 name: 'startTime',
13062 description:
13063 '<p>(optional) schedule playback to start (in seconds from now).</p>\n',
13064 type: 'Number',
13065 optional: true
13066 },
13067 {
13068 name: 'rate',
13069 description: '<p>(optional) playback rate</p>\n',
13070 type: 'Number',
13071 optional: true
13072 },
13073 {
13074 name: 'amp',
13075 description:
13076 '<p>(optional) amplitude (volume)\n of playback</p>\n',
13077 type: 'Number',
13078 optional: true
13079 },
13080 {
13081 name: 'cueStart',
13082 description: '<p>(optional) cue start time in seconds</p>\n',
13083 type: 'Number',
13084 optional: true
13085 },
13086 {
13087 name: 'duration',
13088 description: '<p>(optional) duration of playback in seconds</p>\n',
13089 type: 'Number',
13090 optional: true
13091 }
13092 ],
13093 class: 'p5.SoundFile',
13094 module: 'p5.sound'
13095 },
13096 playMode: {
13097 name: 'playMode',
13098 params: [
13099 {
13100 name: 'str',
13101 description: "<p>'restart' or 'sustain' or 'untilDone'</p>\n",
13102 type: 'String'
13103 }
13104 ],
13105 class: 'p5.SoundFile',
13106 module: 'p5.sound'
13107 },
13108 pause: {
13109 name: 'pause',
13110 params: [
13111 {
13112 name: 'startTime',
13113 description:
13114 '<p>(optional) schedule event to occur\n seconds from now</p>\n',
13115 type: 'Number',
13116 optional: true
13117 }
13118 ],
13119 class: 'p5.SoundFile',
13120 module: 'p5.sound'
13121 },
13122 loop: {
13123 name: 'loop',
13124 params: [
13125 {
13126 name: 'startTime',
13127 description:
13128 '<p>(optional) schedule event to occur\n seconds from now</p>\n',
13129 type: 'Number',
13130 optional: true
13131 },
13132 {
13133 name: 'rate',
13134 description: '<p>(optional) playback rate</p>\n',
13135 type: 'Number',
13136 optional: true
13137 },
13138 {
13139 name: 'amp',
13140 description: '<p>(optional) playback volume</p>\n',
13141 type: 'Number',
13142 optional: true
13143 },
13144 {
13145 name: 'cueLoopStart',
13146 description: '<p>(optional) startTime in seconds</p>\n',
13147 type: 'Number',
13148 optional: true
13149 },
13150 {
13151 name: 'duration',
13152 description: '<p>(optional) loop duration in seconds</p>\n',
13153 type: 'Number',
13154 optional: true
13155 }
13156 ],
13157 class: 'p5.SoundFile',
13158 module: 'p5.sound'
13159 },
13160 setLoop: {
13161 name: 'setLoop',
13162 params: [
13163 {
13164 name: 'Boolean',
13165 description: '<p>set looping to true or false</p>\n',
13166 type: 'Boolean'
13167 }
13168 ],
13169 class: 'p5.SoundFile',
13170 module: 'p5.sound'
13171 },
13172 isLooping: {
13173 name: 'isLooping',
13174 class: 'p5.SoundFile',
13175 module: 'p5.sound'
13176 },
13177 isPlaying: {
13178 name: 'isPlaying',
13179 class: 'p5.SoundFile',
13180 module: 'p5.sound'
13181 },
13182 isPaused: {
13183 name: 'isPaused',
13184 class: 'p5.SoundFile',
13185 module: 'p5.sound'
13186 },
13187 stop: {
13188 name: 'stop',
13189 params: [
13190 {
13191 name: 'startTime',
13192 description:
13193 '<p>(optional) schedule event to occur\n in seconds from now</p>\n',
13194 type: 'Number',
13195 optional: true
13196 }
13197 ],
13198 class: 'p5.SoundFile',
13199 module: 'p5.sound'
13200 },
13201 setVolume: {
13202 name: 'setVolume',
13203 params: [
13204 {
13205 name: 'volume',
13206 description:
13207 '<p>Volume (amplitude) between 0.0\n and 1.0 or modulating signal/oscillator</p>\n',
13208 type: 'Number|Object'
13209 },
13210 {
13211 name: 'rampTime',
13212 description: '<p>Fade for t seconds</p>\n',
13213 type: 'Number',
13214 optional: true
13215 },
13216 {
13217 name: 'timeFromNow',
13218 description:
13219 '<p>Schedule this event to happen at\n t seconds in the future</p>\n',
13220 type: 'Number',
13221 optional: true
13222 }
13223 ],
13224 class: 'p5.SoundFile',
13225 module: 'p5.sound'
13226 },
13227 pan: {
13228 name: 'pan',
13229 params: [
13230 {
13231 name: 'panValue',
13232 description: '<p>Set the stereo panner</p>\n',
13233 type: 'Number',
13234 optional: true
13235 },
13236 {
13237 name: 'timeFromNow',
13238 description:
13239 '<p>schedule this event to happen\n seconds from now</p>\n',
13240 type: 'Number',
13241 optional: true
13242 }
13243 ],
13244 class: 'p5.SoundFile',
13245 module: 'p5.sound'
13246 },
13247 getPan: {
13248 name: 'getPan',
13249 class: 'p5.SoundFile',
13250 module: 'p5.sound'
13251 },
13252 rate: {
13253 name: 'rate',
13254 params: [
13255 {
13256 name: 'playbackRate',
13257 description:
13258 '<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',
13259 type: 'Number',
13260 optional: true
13261 }
13262 ],
13263 class: 'p5.SoundFile',
13264 module: 'p5.sound'
13265 },
13266 duration: {
13267 name: 'duration',
13268 class: 'p5.SoundFile',
13269 module: 'p5.sound'
13270 },
13271 currentTime: {
13272 name: 'currentTime',
13273 class: 'p5.SoundFile',
13274 module: 'p5.sound'
13275 },
13276 jump: {
13277 name: 'jump',
13278 params: [
13279 {
13280 name: 'cueTime',
13281 description: '<p>cueTime of the soundFile in seconds.</p>\n',
13282 type: 'Number'
13283 },
13284 {
13285 name: 'duration',
13286 description: '<p>duration in seconds.</p>\n',
13287 type: 'Number'
13288 }
13289 ],
13290 class: 'p5.SoundFile',
13291 module: 'p5.sound'
13292 },
13293 channels: {
13294 name: 'channels',
13295 class: 'p5.SoundFile',
13296 module: 'p5.sound'
13297 },
13298 sampleRate: {
13299 name: 'sampleRate',
13300 class: 'p5.SoundFile',
13301 module: 'p5.sound'
13302 },
13303 frames: {
13304 name: 'frames',
13305 class: 'p5.SoundFile',
13306 module: 'p5.sound'
13307 },
13308 getPeaks: {
13309 name: 'getPeaks',
13310 params: [
13311 {
13312 name: 'length',
13313 description:
13314 '<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',
13315 type: 'Number',
13316 optional: true
13317 }
13318 ],
13319 class: 'p5.SoundFile',
13320 module: 'p5.sound'
13321 },
13322 reverseBuffer: {
13323 name: 'reverseBuffer',
13324 class: 'p5.SoundFile',
13325 module: 'p5.sound'
13326 },
13327 onended: {
13328 name: 'onended',
13329 params: [
13330 {
13331 name: 'callback',
13332 description:
13333 '<p>function to call when the\n soundfile has ended.</p>\n',
13334 type: 'Function'
13335 }
13336 ],
13337 class: 'p5.SoundFile',
13338 module: 'p5.sound'
13339 },
13340 connect: {
13341 name: 'connect',
13342 params: [
13343 {
13344 name: 'object',
13345 description: '<p>Audio object that accepts an input</p>\n',
13346 type: 'Object',
13347 optional: true
13348 }
13349 ],
13350 class: 'p5.SoundFile',
13351 module: 'p5.sound'
13352 },
13353 disconnect: {
13354 name: 'disconnect',
13355 class: 'p5.SoundFile',
13356 module: 'p5.sound'
13357 },
13358 setPath: {
13359 name: 'setPath',
13360 params: [
13361 {
13362 name: 'path',
13363 description: '<p>path to audio file</p>\n',
13364 type: 'String'
13365 },
13366 {
13367 name: 'callback',
13368 description: '<p>Callback</p>\n',
13369 type: 'Function'
13370 }
13371 ],
13372 class: 'p5.SoundFile',
13373 module: 'p5.sound'
13374 },
13375 setBuffer: {
13376 name: 'setBuffer',
13377 params: [
13378 {
13379 name: 'buf',
13380 description:
13381 '<p>Array of Float32 Array(s). 2 Float32 Arrays\n will create a stereo source. 1 will create\n a mono source.</p>\n',
13382 type: 'Array'
13383 }
13384 ],
13385 class: 'p5.SoundFile',
13386 module: 'p5.sound'
13387 },
13388 processPeaks: {
13389 name: 'processPeaks',
13390 params: [
13391 {
13392 name: 'callback',
13393 description: '<p>a function to call once this data is returned</p>\n',
13394 type: 'Function'
13395 },
13396 {
13397 name: 'initThreshold',
13398 description: '<p>initial threshold defaults to 0.9</p>\n',
13399 type: 'Number',
13400 optional: true
13401 },
13402 {
13403 name: 'minThreshold',
13404 description: '<p>minimum threshold defaults to 0.22</p>\n',
13405 type: 'Number',
13406 optional: true
13407 },
13408 {
13409 name: 'minPeaks',
13410 description: '<p>minimum number of peaks defaults to 200</p>\n',
13411 type: 'Number',
13412 optional: true
13413 }
13414 ],
13415 class: 'p5.SoundFile',
13416 module: 'p5.sound'
13417 },
13418 addCue: {
13419 name: 'addCue',
13420 params: [
13421 {
13422 name: 'time',
13423 description:
13424 "<p>Time in seconds, relative to this media\n element'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",
13425 type: 'Number'
13426 },
13427 {
13428 name: 'callback',
13429 description:
13430 '<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',
13431 type: 'Function'
13432 },
13433 {
13434 name: 'value',
13435 description:
13436 '<p>An object to be passed as the\n second parameter to the\n callback function.</p>\n',
13437 type: 'Object',
13438 optional: true
13439 }
13440 ],
13441 class: 'p5.SoundFile',
13442 module: 'p5.sound'
13443 },
13444 removeCue: {
13445 name: 'removeCue',
13446 params: [
13447 {
13448 name: 'id',
13449 description: '<p>ID of the cue, as returned by addCue</p>\n',
13450 type: 'Number'
13451 }
13452 ],
13453 class: 'p5.SoundFile',
13454 module: 'p5.sound'
13455 },
13456 clearCues: {
13457 name: 'clearCues',
13458 class: 'p5.SoundFile',
13459 module: 'p5.sound'
13460 },
13461 save: {
13462 name: 'save',
13463 params: [
13464 {
13465 name: 'fileName',
13466 description: '<p>name of the resulting .wav file.</p>\n',
13467 type: 'String',
13468 optional: true
13469 }
13470 ],
13471 class: 'p5.SoundFile',
13472 module: 'p5.sound'
13473 },
13474 getBlob: {
13475 name: 'getBlob',
13476 class: 'p5.SoundFile',
13477 module: 'p5.sound'
13478 }
13479 },
13480 'p5.Amplitude': {
13481 setInput: {
13482 name: 'setInput',
13483 params: [
13484 {
13485 name: 'snd',
13486 description:
13487 '<p>set the sound source\n (optional, defaults to\n master output)</p>\n',
13488 type: 'SoundObject|undefined',
13489 optional: true
13490 },
13491 {
13492 name: 'smoothing',
13493 description:
13494 '<p>a range between 0.0 and 1.0\n to smooth amplitude readings</p>\n',
13495 type: 'Number|undefined',
13496 optional: true
13497 }
13498 ],
13499 class: 'p5.Amplitude',
13500 module: 'p5.sound'
13501 },
13502 getLevel: {
13503 name: 'getLevel',
13504 params: [
13505 {
13506 name: 'channel',
13507 description:
13508 '<p>Optionally return only channel 0 (left) or 1 (right)</p>\n',
13509 type: 'Number',
13510 optional: true
13511 }
13512 ],
13513 class: 'p5.Amplitude',
13514 module: 'p5.sound'
13515 },
13516 toggleNormalize: {
13517 name: 'toggleNormalize',
13518 params: [
13519 {
13520 name: 'boolean',
13521 description: '<p>set normalize to true (1) or false (0)</p>\n',
13522 type: 'Boolean',
13523 optional: true
13524 }
13525 ],
13526 class: 'p5.Amplitude',
13527 module: 'p5.sound'
13528 },
13529 smooth: {
13530 name: 'smooth',
13531 params: [
13532 {
13533 name: 'set',
13534 description: '<p>smoothing from 0.0 <= 1</p>\n',
13535 type: 'Number'
13536 }
13537 ],
13538 class: 'p5.Amplitude',
13539 module: 'p5.sound'
13540 }
13541 },
13542 'p5.FFT': {
13543 setInput: {
13544 name: 'setInput',
13545 params: [
13546 {
13547 name: 'source',
13548 description: '<p>p5.sound object (or web audio API source node)</p>\n',
13549 type: 'Object',
13550 optional: true
13551 }
13552 ],
13553 class: 'p5.FFT',
13554 module: 'p5.sound'
13555 },
13556 waveform: {
13557 name: 'waveform',
13558 params: [
13559 {
13560 name: 'bins',
13561 description:
13562 '<p>Must be a power of two between\n 16 and 1024. Defaults to 1024.</p>\n',
13563 type: 'Number',
13564 optional: true
13565 },
13566 {
13567 name: 'precision',
13568 description:
13569 '<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',
13570 type: 'String',
13571 optional: true
13572 }
13573 ],
13574 class: 'p5.FFT',
13575 module: 'p5.sound'
13576 },
13577 analyze: {
13578 name: 'analyze',
13579 params: [
13580 {
13581 name: 'bins',
13582 description:
13583 '<p>Must be a power of two between\n 16 and 1024. Defaults to 1024.</p>\n',
13584 type: 'Number',
13585 optional: true
13586 },
13587 {
13588 name: 'scale',
13589 description:
13590 '<p>If "dB," returns decibel\n float measurements between\n -140 and 0 (max).\n Otherwise returns integers from 0-255.</p>\n',
13591 type: 'Number',
13592 optional: true
13593 }
13594 ],
13595 class: 'p5.FFT',
13596 module: 'p5.sound'
13597 },
13598 getEnergy: {
13599 name: 'getEnergy',
13600 params: [
13601 {
13602 name: 'frequency1',
13603 description:
13604 '<p>Will return a value representing\n energy at this frequency. Alternately,\n the strings "bass", "lowMid" "mid",\n "highMid", and "treble" will return\n predefined frequency ranges.</p>\n',
13605 type: 'Number|String'
13606 },
13607 {
13608 name: 'frequency2',
13609 description:
13610 '<p>If a second frequency is given,\n will return average amount of\n energy that exists between the\n two frequencies.</p>\n',
13611 type: 'Number',
13612 optional: true
13613 }
13614 ],
13615 class: 'p5.FFT',
13616 module: 'p5.sound'
13617 },
13618 getCentroid: {
13619 name: 'getCentroid',
13620 class: 'p5.FFT',
13621 module: 'p5.sound'
13622 },
13623 smooth: {
13624 name: 'smooth',
13625 params: [
13626 {
13627 name: 'smoothing',
13628 description:
13629 '<p>0.0 < smoothing < 1.0.\n Defaults to 0.8.</p>\n',
13630 type: 'Number'
13631 }
13632 ],
13633 class: 'p5.FFT',
13634 module: 'p5.sound'
13635 },
13636 linAverages: {
13637 name: 'linAverages',
13638 params: [
13639 {
13640 name: 'N',
13641 description: '<p>Number of returned frequency groups</p>\n',
13642 type: 'Number'
13643 }
13644 ],
13645 class: 'p5.FFT',
13646 module: 'p5.sound'
13647 },
13648 logAverages: {
13649 name: 'logAverages',
13650 params: [
13651 {
13652 name: 'octaveBands',
13653 description: '<p>Array of Octave Bands objects for grouping</p>\n',
13654 type: 'Array'
13655 }
13656 ],
13657 class: 'p5.FFT',
13658 module: 'p5.sound'
13659 },
13660 getOctaveBands: {
13661 name: 'getOctaveBands',
13662 params: [
13663 {
13664 name: 'N',
13665 description:
13666 '<p>Specifies the 1/N type of generated octave bands</p>\n',
13667 type: 'Number'
13668 },
13669 {
13670 name: 'fCtr0',
13671 description: '<p>Minimum central frequency for the lowest band</p>\n',
13672 type: 'Number'
13673 }
13674 ],
13675 class: 'p5.FFT',
13676 module: 'p5.sound'
13677 }
13678 },
13679 'p5.Signal': {
13680 fade: {
13681 name: 'fade',
13682 params: [
13683 {
13684 name: 'value',
13685 description: '<p>Value to set this signal</p>\n',
13686 type: 'Number'
13687 },
13688 {
13689 name: 'secondsFromNow',
13690 description: '<p>Length of fade, in seconds from now</p>\n',
13691 type: 'Number',
13692 optional: true
13693 }
13694 ],
13695 class: 'p5.Signal',
13696 module: 'p5.sound'
13697 },
13698 setInput: {
13699 name: 'setInput',
13700 params: [
13701 {
13702 name: 'input',
13703 description: '',
13704 type: 'Object'
13705 }
13706 ],
13707 class: 'p5.Signal',
13708 module: 'p5.sound'
13709 },
13710 add: {
13711 name: 'add',
13712 params: [
13713 {
13714 name: 'number',
13715 description: '',
13716 type: 'Number'
13717 }
13718 ],
13719 class: 'p5.Signal',
13720 module: 'p5.sound'
13721 },
13722 mult: {
13723 name: 'mult',
13724 params: [
13725 {
13726 name: 'number',
13727 description: '<p>to multiply</p>\n',
13728 type: 'Number'
13729 }
13730 ],
13731 class: 'p5.Signal',
13732 module: 'p5.sound'
13733 },
13734 scale: {
13735 name: 'scale',
13736 params: [
13737 {
13738 name: 'number',
13739 description: '<p>to multiply</p>\n',
13740 type: 'Number'
13741 },
13742 {
13743 name: 'inMin',
13744 description: '<p>input range minumum</p>\n',
13745 type: 'Number'
13746 },
13747 {
13748 name: 'inMax',
13749 description: '<p>input range maximum</p>\n',
13750 type: 'Number'
13751 },
13752 {
13753 name: 'outMin',
13754 description: '<p>input range minumum</p>\n',
13755 type: 'Number'
13756 },
13757 {
13758 name: 'outMax',
13759 description: '<p>input range maximum</p>\n',
13760 type: 'Number'
13761 }
13762 ],
13763 class: 'p5.Signal',
13764 module: 'p5.sound'
13765 }
13766 },
13767 'p5.Envelope': {
13768 attackTime: {
13769 name: 'attackTime',
13770 class: 'p5.Envelope',
13771 module: 'p5.sound'
13772 },
13773 attackLevel: {
13774 name: 'attackLevel',
13775 class: 'p5.Envelope',
13776 module: 'p5.sound'
13777 },
13778 decayTime: {
13779 name: 'decayTime',
13780 class: 'p5.Envelope',
13781 module: 'p5.sound'
13782 },
13783 decayLevel: {
13784 name: 'decayLevel',
13785 class: 'p5.Envelope',
13786 module: 'p5.sound'
13787 },
13788 releaseTime: {
13789 name: 'releaseTime',
13790 class: 'p5.Envelope',
13791 module: 'p5.sound'
13792 },
13793 releaseLevel: {
13794 name: 'releaseLevel',
13795 class: 'p5.Envelope',
13796 module: 'p5.sound'
13797 },
13798 set: {
13799 name: 'set',
13800 params: [
13801 {
13802 name: 'attackTime',
13803 description:
13804 '<p>Time (in seconds) before level\n reaches attackLevel</p>\n',
13805 type: 'Number'
13806 },
13807 {
13808 name: 'attackLevel',
13809 description:
13810 '<p>Typically an amplitude between\n 0.0 and 1.0</p>\n',
13811 type: 'Number'
13812 },
13813 {
13814 name: 'decayTime',
13815 description: '<p>Time</p>\n',
13816 type: 'Number'
13817 },
13818 {
13819 name: 'decayLevel',
13820 description:
13821 '<p>Amplitude (In a standard ADSR envelope,\n decayLevel = sustainLevel)</p>\n',
13822 type: 'Number'
13823 },
13824 {
13825 name: 'releaseTime',
13826 description: '<p>Release Time (in seconds)</p>\n',
13827 type: 'Number'
13828 },
13829 {
13830 name: 'releaseLevel',
13831 description: '<p>Amplitude</p>\n',
13832 type: 'Number'
13833 }
13834 ],
13835 class: 'p5.Envelope',
13836 module: 'p5.sound'
13837 },
13838 setADSR: {
13839 name: 'setADSR',
13840 params: [
13841 {
13842 name: 'attackTime',
13843 description:
13844 '<p>Time (in seconds before envelope\n reaches Attack Level</p>\n',
13845 type: 'Number'
13846 },
13847 {
13848 name: 'decayTime',
13849 description:
13850 '<p>Time (in seconds) before envelope\n reaches Decay/Sustain Level</p>\n',
13851 type: 'Number',
13852 optional: true
13853 },
13854 {
13855 name: 'susRatio',
13856 description:
13857 '<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',
13858 type: 'Number',
13859 optional: true
13860 },
13861 {
13862 name: 'releaseTime',
13863 description: '<p>Time in seconds from now (defaults to 0)</p>\n',
13864 type: 'Number',
13865 optional: true
13866 }
13867 ],
13868 class: 'p5.Envelope',
13869 module: 'p5.sound'
13870 },
13871 setRange: {
13872 name: 'setRange',
13873 params: [
13874 {
13875 name: 'aLevel',
13876 description: '<p>attack level (defaults to 1)</p>\n',
13877 type: 'Number'
13878 },
13879 {
13880 name: 'rLevel',
13881 description: '<p>release level (defaults to 0)</p>\n',
13882 type: 'Number'
13883 }
13884 ],
13885 class: 'p5.Envelope',
13886 module: 'p5.sound'
13887 },
13888 setInput: {
13889 name: 'setInput',
13890 params: [
13891 {
13892 name: 'inputs',
13893 description:
13894 '<p>A p5.sound object or\n Web Audio Param.</p>\n',
13895 type: 'Object',
13896 optional: true,
13897 multiple: true
13898 }
13899 ],
13900 class: 'p5.Envelope',
13901 module: 'p5.sound'
13902 },
13903 setExp: {
13904 name: 'setExp',
13905 params: [
13906 {
13907 name: 'isExp',
13908 description: '<p>true is exponential, false is linear</p>\n',
13909 type: 'Boolean'
13910 }
13911 ],
13912 class: 'p5.Envelope',
13913 module: 'p5.sound'
13914 },
13915 play: {
13916 name: 'play',
13917 params: [
13918 {
13919 name: 'unit',
13920 description:
13921 '<p>A p5.sound object or\n Web Audio Param.</p>\n',
13922 type: 'Object'
13923 },
13924 {
13925 name: 'startTime',
13926 description: '<p>time from now (in seconds) at which to play</p>\n',
13927 type: 'Number',
13928 optional: true
13929 },
13930 {
13931 name: 'sustainTime',
13932 description: '<p>time to sustain before releasing the envelope</p>\n',
13933 type: 'Number',
13934 optional: true
13935 }
13936 ],
13937 class: 'p5.Envelope',
13938 module: 'p5.sound'
13939 },
13940 triggerAttack: {
13941 name: 'triggerAttack',
13942 params: [
13943 {
13944 name: 'unit',
13945 description: '<p>p5.sound Object or Web Audio Param</p>\n',
13946 type: 'Object'
13947 },
13948 {
13949 name: 'secondsFromNow',
13950 description: '<p>time from now (in seconds)</p>\n',
13951 type: 'Number'
13952 }
13953 ],
13954 class: 'p5.Envelope',
13955 module: 'p5.sound'
13956 },
13957 triggerRelease: {
13958 name: 'triggerRelease',
13959 params: [
13960 {
13961 name: 'unit',
13962 description: '<p>p5.sound Object or Web Audio Param</p>\n',
13963 type: 'Object'
13964 },
13965 {
13966 name: 'secondsFromNow',
13967 description: '<p>time to trigger the release</p>\n',
13968 type: 'Number'
13969 }
13970 ],
13971 class: 'p5.Envelope',
13972 module: 'p5.sound'
13973 },
13974 ramp: {
13975 name: 'ramp',
13976 params: [
13977 {
13978 name: 'unit',
13979 description: '<p>p5.sound Object or Web Audio Param</p>\n',
13980 type: 'Object'
13981 },
13982 {
13983 name: 'secondsFromNow',
13984 description: '<p>When to trigger the ramp</p>\n',
13985 type: 'Number'
13986 },
13987 {
13988 name: 'v',
13989 description: '<p>Target value</p>\n',
13990 type: 'Number'
13991 },
13992 {
13993 name: 'v2',
13994 description: '<p>Second target value (optional)</p>\n',
13995 type: 'Number',
13996 optional: true
13997 }
13998 ],
13999 class: 'p5.Envelope',
14000 module: 'p5.sound'
14001 },
14002 add: {
14003 name: 'add',
14004 params: [
14005 {
14006 name: 'number',
14007 description: '<p>Constant number to add</p>\n',
14008 type: 'Number'
14009 }
14010 ],
14011 class: 'p5.Envelope',
14012 module: 'p5.sound'
14013 },
14014 mult: {
14015 name: 'mult',
14016 params: [
14017 {
14018 name: 'number',
14019 description: '<p>Constant number to multiply</p>\n',
14020 type: 'Number'
14021 }
14022 ],
14023 class: 'p5.Envelope',
14024 module: 'p5.sound'
14025 },
14026 scale: {
14027 name: 'scale',
14028 params: [
14029 {
14030 name: 'inMin',
14031 description: '<p>input range minumum</p>\n',
14032 type: 'Number'
14033 },
14034 {
14035 name: 'inMax',
14036 description: '<p>input range maximum</p>\n',
14037 type: 'Number'
14038 },
14039 {
14040 name: 'outMin',
14041 description: '<p>input range minumum</p>\n',
14042 type: 'Number'
14043 },
14044 {
14045 name: 'outMax',
14046 description: '<p>input range maximum</p>\n',
14047 type: 'Number'
14048 }
14049 ],
14050 class: 'p5.Envelope',
14051 module: 'p5.sound'
14052 }
14053 },
14054 'p5.Pulse': {
14055 width: {
14056 name: 'width',
14057 params: [
14058 {
14059 name: 'width',
14060 description:
14061 '<p>Width between the pulses (0 to 1.0,\n defaults to 0)</p>\n',
14062 type: 'Number',
14063 optional: true
14064 }
14065 ],
14066 class: 'p5.Pulse',
14067 module: 'p5.sound'
14068 }
14069 },
14070 'p5.Noise': {
14071 setType: {
14072 name: 'setType',
14073 params: [
14074 {
14075 name: 'type',
14076 description: "<p>'white', 'pink' or 'brown'</p>\n",
14077 type: 'String',
14078 optional: true
14079 }
14080 ],
14081 class: 'p5.Noise',
14082 module: 'p5.sound'
14083 }
14084 },
14085 'p5.AudioIn': {
14086 input: {
14087 name: 'input',
14088 class: 'p5.AudioIn',
14089 module: 'p5.sound'
14090 },
14091 output: {
14092 name: 'output',
14093 class: 'p5.AudioIn',
14094 module: 'p5.sound'
14095 },
14096 stream: {
14097 name: 'stream',
14098 class: 'p5.AudioIn',
14099 module: 'p5.sound'
14100 },
14101 mediaStream: {
14102 name: 'mediaStream',
14103 class: 'p5.AudioIn',
14104 module: 'p5.sound'
14105 },
14106 currentSource: {
14107 name: 'currentSource',
14108 class: 'p5.AudioIn',
14109 module: 'p5.sound'
14110 },
14111 enabled: {
14112 name: 'enabled',
14113 class: 'p5.AudioIn',
14114 module: 'p5.sound'
14115 },
14116 amplitude: {
14117 name: 'amplitude',
14118 class: 'p5.AudioIn',
14119 module: 'p5.sound'
14120 },
14121 start: {
14122 name: 'start',
14123 params: [
14124 {
14125 name: 'successCallback',
14126 description:
14127 '<p>Name of a function to call on\n success.</p>\n',
14128 type: 'Function',
14129 optional: true
14130 },
14131 {
14132 name: 'errorCallback',
14133 description:
14134 '<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',
14135 type: 'Function',
14136 optional: true
14137 }
14138 ],
14139 class: 'p5.AudioIn',
14140 module: 'p5.sound'
14141 },
14142 stop: {
14143 name: 'stop',
14144 class: 'p5.AudioIn',
14145 module: 'p5.sound'
14146 },
14147 connect: {
14148 name: 'connect',
14149 params: [
14150 {
14151 name: 'unit',
14152 description:
14153 '<p>An object that accepts audio input,\n such as an FFT</p>\n',
14154 type: 'Object',
14155 optional: true
14156 }
14157 ],
14158 class: 'p5.AudioIn',
14159 module: 'p5.sound'
14160 },
14161 disconnect: {
14162 name: 'disconnect',
14163 class: 'p5.AudioIn',
14164 module: 'p5.sound'
14165 },
14166 getLevel: {
14167 name: 'getLevel',
14168 params: [
14169 {
14170 name: 'smoothing',
14171 description:
14172 '<p>Smoothing is 0.0 by default.\n Smooths values based on previous values.</p>\n',
14173 type: 'Number',
14174 optional: true
14175 }
14176 ],
14177 class: 'p5.AudioIn',
14178 module: 'p5.sound'
14179 },
14180 amp: {
14181 name: 'amp',
14182 params: [
14183 {
14184 name: 'vol',
14185 description: '<p>between 0 and 1.0</p>\n',
14186 type: 'Number'
14187 },
14188 {
14189 name: 'time',
14190 description: '<p>ramp time (optional)</p>\n',
14191 type: 'Number',
14192 optional: true
14193 }
14194 ],
14195 class: 'p5.AudioIn',
14196 module: 'p5.sound'
14197 },
14198 getSources: {
14199 name: 'getSources',
14200 params: [
14201 {
14202 name: 'successCallback',
14203 description:
14204 '<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',
14205 type: 'Function',
14206 optional: true
14207 },
14208 {
14209 name: 'errorCallback',
14210 description:
14211 '<p>This optional callback receives the error\n message as its argument.</p>\n',
14212 type: 'Function',
14213 optional: true
14214 }
14215 ],
14216 class: 'p5.AudioIn',
14217 module: 'p5.sound'
14218 },
14219 setSource: {
14220 name: 'setSource',
14221 params: [
14222 {
14223 name: 'num',
14224 description: '<p>position of input source in the array</p>\n',
14225 type: 'Number'
14226 }
14227 ],
14228 class: 'p5.AudioIn',
14229 module: 'p5.sound'
14230 }
14231 },
14232 'p5.EQ': {
14233 bands: {
14234 name: 'bands',
14235 class: 'p5.EQ',
14236 module: 'p5.sound'
14237 },
14238 process: {
14239 name: 'process',
14240 params: [
14241 {
14242 name: 'src',
14243 description: '<p>Audio source</p>\n',
14244 type: 'Object'
14245 }
14246 ],
14247 class: 'p5.EQ',
14248 module: 'p5.sound'
14249 }
14250 },
14251 'p5.Panner3D': {
14252 panner: {
14253 name: 'panner',
14254 class: 'p5.Panner3D',
14255 module: 'p5.sound'
14256 },
14257 process: {
14258 name: 'process',
14259 params: [
14260 {
14261 name: 'src',
14262 description: '<p>Input source</p>\n',
14263 type: 'Object'
14264 }
14265 ],
14266 class: 'p5.Panner3D',
14267 module: 'p5.sound'
14268 },
14269 set: {
14270 name: 'set',
14271 params: [
14272 {
14273 name: 'xVal',
14274 description: '',
14275 type: 'Number'
14276 },
14277 {
14278 name: 'yVal',
14279 description: '',
14280 type: 'Number'
14281 },
14282 {
14283 name: 'zVal',
14284 description: '',
14285 type: 'Number'
14286 },
14287 {
14288 name: 'time',
14289 description: '',
14290 type: 'Number'
14291 }
14292 ],
14293 class: 'p5.Panner3D',
14294 module: 'p5.sound'
14295 },
14296 positionX: {
14297 name: 'positionX',
14298 class: 'p5.Panner3D',
14299 module: 'p5.sound'
14300 },
14301 positionY: {
14302 name: 'positionY',
14303 class: 'p5.Panner3D',
14304 module: 'p5.sound'
14305 },
14306 positionZ: {
14307 name: 'positionZ',
14308 class: 'p5.Panner3D',
14309 module: 'p5.sound'
14310 },
14311 orient: {
14312 name: 'orient',
14313 params: [
14314 {
14315 name: 'xVal',
14316 description: '',
14317 type: 'Number'
14318 },
14319 {
14320 name: 'yVal',
14321 description: '',
14322 type: 'Number'
14323 },
14324 {
14325 name: 'zVal',
14326 description: '',
14327 type: 'Number'
14328 },
14329 {
14330 name: 'time',
14331 description: '',
14332 type: 'Number'
14333 }
14334 ],
14335 class: 'p5.Panner3D',
14336 module: 'p5.sound'
14337 },
14338 orientX: {
14339 name: 'orientX',
14340 class: 'p5.Panner3D',
14341 module: 'p5.sound'
14342 },
14343 orientY: {
14344 name: 'orientY',
14345 class: 'p5.Panner3D',
14346 module: 'p5.sound'
14347 },
14348 orientZ: {
14349 name: 'orientZ',
14350 class: 'p5.Panner3D',
14351 module: 'p5.sound'
14352 },
14353 setFalloff: {
14354 name: 'setFalloff',
14355 params: [
14356 {
14357 name: 'maxDistance',
14358 description: '',
14359 type: 'Number',
14360 optional: true
14361 },
14362 {
14363 name: 'rolloffFactor',
14364 description: '',
14365 type: 'Number',
14366 optional: true
14367 }
14368 ],
14369 class: 'p5.Panner3D',
14370 module: 'p5.sound'
14371 },
14372 maxDist: {
14373 name: 'maxDist',
14374 params: [
14375 {
14376 name: 'maxDistance',
14377 description: '',
14378 type: 'Number'
14379 }
14380 ],
14381 class: 'p5.Panner3D',
14382 module: 'p5.sound'
14383 },
14384 rollof: {
14385 name: 'rollof',
14386 params: [
14387 {
14388 name: 'rolloffFactor',
14389 description: '',
14390 type: 'Number'
14391 }
14392 ],
14393 class: 'p5.Panner3D',
14394 module: 'p5.sound'
14395 }
14396 },
14397 'p5.Delay': {
14398 leftDelay: {
14399 name: 'leftDelay',
14400 class: 'p5.Delay',
14401 module: 'p5.sound'
14402 },
14403 rightDelay: {
14404 name: 'rightDelay',
14405 class: 'p5.Delay',
14406 module: 'p5.sound'
14407 },
14408 process: {
14409 name: 'process',
14410 params: [
14411 {
14412 name: 'Signal',
14413 description: '<p>An object that outputs audio</p>\n',
14414 type: 'Object'
14415 },
14416 {
14417 name: 'delayTime',
14418 description:
14419 '<p>Time (in seconds) of the delay/echo.\n Some browsers limit delayTime to\n 1 second.</p>\n',
14420 type: 'Number',
14421 optional: true
14422 },
14423 {
14424 name: 'feedback',
14425 description:
14426 '<p>sends the delay back through itself\n in a loop that decreases in volume\n each time.</p>\n',
14427 type: 'Number',
14428 optional: true
14429 },
14430 {
14431 name: 'lowPass',
14432 description:
14433 '<p>Cutoff frequency. Only frequencies\n below the lowPass will be part of the\n delay.</p>\n',
14434 type: 'Number',
14435 optional: true
14436 }
14437 ],
14438 class: 'p5.Delay',
14439 module: 'p5.sound'
14440 },
14441 delayTime: {
14442 name: 'delayTime',
14443 params: [
14444 {
14445 name: 'delayTime',
14446 description: '<p>Time (in seconds) of the delay</p>\n',
14447 type: 'Number'
14448 }
14449 ],
14450 class: 'p5.Delay',
14451 module: 'p5.sound'
14452 },
14453 feedback: {
14454 name: 'feedback',
14455 params: [
14456 {
14457 name: 'feedback',
14458 description:
14459 '<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',
14460 type: 'Number|Object'
14461 }
14462 ],
14463 class: 'p5.Delay',
14464 module: 'p5.sound'
14465 },
14466 filter: {
14467 name: 'filter',
14468 params: [
14469 {
14470 name: 'cutoffFreq',
14471 description:
14472 '<p>A lowpass filter will cut off any\n frequencies higher than the filter frequency.</p>\n',
14473 type: 'Number|Object'
14474 },
14475 {
14476 name: 'res',
14477 description:
14478 '<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',
14479 type: 'Number|Object'
14480 }
14481 ],
14482 class: 'p5.Delay',
14483 module: 'p5.sound'
14484 },
14485 setType: {
14486 name: 'setType',
14487 params: [
14488 {
14489 name: 'type',
14490 description: "<p>'pingPong' (1) or 'default' (0)</p>\n",
14491 type: 'String|Number'
14492 }
14493 ],
14494 class: 'p5.Delay',
14495 module: 'p5.sound'
14496 },
14497 amp: {
14498 name: 'amp',
14499 params: [
14500 {
14501 name: 'volume',
14502 description: '<p>amplitude between 0 and 1.0</p>\n',
14503 type: 'Number'
14504 },
14505 {
14506 name: 'rampTime',
14507 description: '<p>create a fade that lasts rampTime</p>\n',
14508 type: 'Number',
14509 optional: true
14510 },
14511 {
14512 name: 'timeFromNow',
14513 description:
14514 '<p>schedule this event to happen\n seconds from now</p>\n',
14515 type: 'Number',
14516 optional: true
14517 }
14518 ],
14519 class: 'p5.Delay',
14520 module: 'p5.sound'
14521 },
14522 connect: {
14523 name: 'connect',
14524 params: [
14525 {
14526 name: 'unit',
14527 description: '',
14528 type: 'Object'
14529 }
14530 ],
14531 class: 'p5.Delay',
14532 module: 'p5.sound'
14533 },
14534 disconnect: {
14535 name: 'disconnect',
14536 class: 'p5.Delay',
14537 module: 'p5.sound'
14538 }
14539 },
14540 'p5.Reverb': {
14541 process: {
14542 name: 'process',
14543 params: [
14544 {
14545 name: 'src',
14546 description:
14547 '<p>p5.sound / Web Audio object with a sound\n output.</p>\n',
14548 type: 'Object'
14549 },
14550 {
14551 name: 'seconds',
14552 description:
14553 '<p>Duration of the reverb, in seconds.\n Min: 0, Max: 10. Defaults to 3.</p>\n',
14554 type: 'Number',
14555 optional: true
14556 },
14557 {
14558 name: 'decayRate',
14559 description:
14560 '<p>Percentage of decay with each echo.\n Min: 0, Max: 100. Defaults to 2.</p>\n',
14561 type: 'Number',
14562 optional: true
14563 },
14564 {
14565 name: 'reverse',
14566 description: '<p>Play the reverb backwards or forwards.</p>\n',
14567 type: 'Boolean',
14568 optional: true
14569 }
14570 ],
14571 class: 'p5.Reverb',
14572 module: 'p5.sound'
14573 },
14574 set: {
14575 name: 'set',
14576 params: [
14577 {
14578 name: 'seconds',
14579 description:
14580 '<p>Duration of the reverb, in seconds.\n Min: 0, Max: 10. Defaults to 3.</p>\n',
14581 type: 'Number',
14582 optional: true
14583 },
14584 {
14585 name: 'decayRate',
14586 description:
14587 '<p>Percentage of decay with each echo.\n Min: 0, Max: 100. Defaults to 2.</p>\n',
14588 type: 'Number',
14589 optional: true
14590 },
14591 {
14592 name: 'reverse',
14593 description: '<p>Play the reverb backwards or forwards.</p>\n',
14594 type: 'Boolean',
14595 optional: true
14596 }
14597 ],
14598 class: 'p5.Reverb',
14599 module: 'p5.sound'
14600 },
14601 amp: {
14602 name: 'amp',
14603 params: [
14604 {
14605 name: 'volume',
14606 description: '<p>amplitude between 0 and 1.0</p>\n',
14607 type: 'Number'
14608 },
14609 {
14610 name: 'rampTime',
14611 description: '<p>create a fade that lasts rampTime</p>\n',
14612 type: 'Number',
14613 optional: true
14614 },
14615 {
14616 name: 'timeFromNow',
14617 description:
14618 '<p>schedule this event to happen\n seconds from now</p>\n',
14619 type: 'Number',
14620 optional: true
14621 }
14622 ],
14623 class: 'p5.Reverb',
14624 module: 'p5.sound'
14625 },
14626 connect: {
14627 name: 'connect',
14628 params: [
14629 {
14630 name: 'unit',
14631 description: '',
14632 type: 'Object'
14633 }
14634 ],
14635 class: 'p5.Reverb',
14636 module: 'p5.sound'
14637 },
14638 disconnect: {
14639 name: 'disconnect',
14640 class: 'p5.Reverb',
14641 module: 'p5.sound'
14642 }
14643 },
14644 'p5.Convolver': {
14645 convolverNode: {
14646 name: 'convolverNode',
14647 class: 'p5.Convolver',
14648 module: 'p5.sound'
14649 },
14650 process: {
14651 name: 'process',
14652 params: [
14653 {
14654 name: 'src',
14655 description:
14656 '<p>p5.sound / Web Audio object with a sound\n output.</p>\n',
14657 type: 'Object'
14658 }
14659 ],
14660 class: 'p5.Convolver',
14661 module: 'p5.sound'
14662 },
14663 impulses: {
14664 name: 'impulses',
14665 class: 'p5.Convolver',
14666 module: 'p5.sound'
14667 },
14668 addImpulse: {
14669 name: 'addImpulse',
14670 params: [
14671 {
14672 name: 'path',
14673 description: '<p>path to a sound file</p>\n',
14674 type: 'String'
14675 },
14676 {
14677 name: 'callback',
14678 description: '<p>function (optional)</p>\n',
14679 type: 'Function'
14680 },
14681 {
14682 name: 'errorCallback',
14683 description: '<p>function (optional)</p>\n',
14684 type: 'Function'
14685 }
14686 ],
14687 class: 'p5.Convolver',
14688 module: 'p5.sound'
14689 },
14690 resetImpulse: {
14691 name: 'resetImpulse',
14692 params: [
14693 {
14694 name: 'path',
14695 description: '<p>path to a sound file</p>\n',
14696 type: 'String'
14697 },
14698 {
14699 name: 'callback',
14700 description: '<p>function (optional)</p>\n',
14701 type: 'Function'
14702 },
14703 {
14704 name: 'errorCallback',
14705 description: '<p>function (optional)</p>\n',
14706 type: 'Function'
14707 }
14708 ],
14709 class: 'p5.Convolver',
14710 module: 'p5.sound'
14711 },
14712 toggleImpulse: {
14713 name: 'toggleImpulse',
14714 params: [
14715 {
14716 name: 'id',
14717 description:
14718 '<p>Identify the impulse by its original filename\n (String), or by its position in the\n <code>.impulses</code> Array (Number).</p>\n',
14719 type: 'String|Number'
14720 }
14721 ],
14722 class: 'p5.Convolver',
14723 module: 'p5.sound'
14724 }
14725 },
14726 'p5.Phrase': {
14727 sequence: {
14728 name: 'sequence',
14729 class: 'p5.Phrase',
14730 module: 'p5.sound'
14731 }
14732 },
14733 'p5.Part': {
14734 setBPM: {
14735 name: 'setBPM',
14736 params: [
14737 {
14738 name: 'BPM',
14739 description: '<p>Beats Per Minute</p>\n',
14740 type: 'Number'
14741 },
14742 {
14743 name: 'rampTime',
14744 description: '<p>Seconds from now</p>\n',
14745 type: 'Number',
14746 optional: true
14747 }
14748 ],
14749 class: 'p5.Part',
14750 module: 'p5.sound'
14751 },
14752 getBPM: {
14753 name: 'getBPM',
14754 class: 'p5.Part',
14755 module: 'p5.sound'
14756 },
14757 start: {
14758 name: 'start',
14759 params: [
14760 {
14761 name: 'time',
14762 description: '<p>seconds from now</p>\n',
14763 type: 'Number',
14764 optional: true
14765 }
14766 ],
14767 class: 'p5.Part',
14768 module: 'p5.sound'
14769 },
14770 loop: {
14771 name: 'loop',
14772 params: [
14773 {
14774 name: 'time',
14775 description: '<p>seconds from now</p>\n',
14776 type: 'Number',
14777 optional: true
14778 }
14779 ],
14780 class: 'p5.Part',
14781 module: 'p5.sound'
14782 },
14783 noLoop: {
14784 name: 'noLoop',
14785 class: 'p5.Part',
14786 module: 'p5.sound'
14787 },
14788 stop: {
14789 name: 'stop',
14790 params: [
14791 {
14792 name: 'time',
14793 description: '<p>seconds from now</p>\n',
14794 type: 'Number',
14795 optional: true
14796 }
14797 ],
14798 class: 'p5.Part',
14799 module: 'p5.sound'
14800 },
14801 pause: {
14802 name: 'pause',
14803 params: [
14804 {
14805 name: 'time',
14806 description: '<p>seconds from now</p>\n',
14807 type: 'Number'
14808 }
14809 ],
14810 class: 'p5.Part',
14811 module: 'p5.sound'
14812 },
14813 addPhrase: {
14814 name: 'addPhrase',
14815 params: [
14816 {
14817 name: 'phrase',
14818 description: '<p>reference to a p5.Phrase</p>\n',
14819 type: 'p5.Phrase'
14820 }
14821 ],
14822 class: 'p5.Part',
14823 module: 'p5.sound'
14824 },
14825 removePhrase: {
14826 name: 'removePhrase',
14827 params: [
14828 {
14829 name: 'phraseName',
14830 description: '',
14831 type: 'String'
14832 }
14833 ],
14834 class: 'p5.Part',
14835 module: 'p5.sound'
14836 },
14837 getPhrase: {
14838 name: 'getPhrase',
14839 params: [
14840 {
14841 name: 'phraseName',
14842 description: '',
14843 type: 'String'
14844 }
14845 ],
14846 class: 'p5.Part',
14847 module: 'p5.sound'
14848 },
14849 replaceSequence: {
14850 name: 'replaceSequence',
14851 params: [
14852 {
14853 name: 'phraseName',
14854 description: '',
14855 type: 'String'
14856 },
14857 {
14858 name: 'sequence',
14859 description:
14860 '<p>Array of values to pass into the callback\n at each step of the phrase.</p>\n',
14861 type: 'Array'
14862 }
14863 ],
14864 class: 'p5.Part',
14865 module: 'p5.sound'
14866 },
14867 onStep: {
14868 name: 'onStep',
14869 params: [
14870 {
14871 name: 'callback',
14872 description:
14873 '<p>The name of the callback\n you want to fire\n on every beat/tatum.</p>\n',
14874 type: 'Function'
14875 }
14876 ],
14877 class: 'p5.Part',
14878 module: 'p5.sound'
14879 }
14880 },
14881 'p5.Score': {
14882 start: {
14883 name: 'start',
14884 class: 'p5.Score',
14885 module: 'p5.sound'
14886 },
14887 stop: {
14888 name: 'stop',
14889 class: 'p5.Score',
14890 module: 'p5.sound'
14891 },
14892 pause: {
14893 name: 'pause',
14894 class: 'p5.Score',
14895 module: 'p5.sound'
14896 },
14897 loop: {
14898 name: 'loop',
14899 class: 'p5.Score',
14900 module: 'p5.sound'
14901 },
14902 noLoop: {
14903 name: 'noLoop',
14904 class: 'p5.Score',
14905 module: 'p5.sound'
14906 },
14907 setBPM: {
14908 name: 'setBPM',
14909 params: [
14910 {
14911 name: 'BPM',
14912 description: '<p>Beats Per Minute</p>\n',
14913 type: 'Number'
14914 },
14915 {
14916 name: 'rampTime',
14917 description: '<p>Seconds from now</p>\n',
14918 type: 'Number'
14919 }
14920 ],
14921 class: 'p5.Score',
14922 module: 'p5.sound'
14923 }
14924 },
14925 'p5.SoundLoop': {
14926 musicalTimeMode: {
14927 name: 'musicalTimeMode',
14928 class: 'p5.SoundLoop',
14929 module: 'p5.sound'
14930 },
14931 maxIterations: {
14932 name: 'maxIterations',
14933 class: 'p5.SoundLoop',
14934 module: 'p5.sound'
14935 },
14936 start: {
14937 name: 'start',
14938 params: [
14939 {
14940 name: 'timeFromNow',
14941 description: '<p>schedule a starting time</p>\n',
14942 type: 'Number',
14943 optional: true
14944 }
14945 ],
14946 class: 'p5.SoundLoop',
14947 module: 'p5.sound'
14948 },
14949 stop: {
14950 name: 'stop',
14951 params: [
14952 {
14953 name: 'timeFromNow',
14954 description: '<p>schedule a stopping time</p>\n',
14955 type: 'Number',
14956 optional: true
14957 }
14958 ],
14959 class: 'p5.SoundLoop',
14960 module: 'p5.sound'
14961 },
14962 pause: {
14963 name: 'pause',
14964 params: [
14965 {
14966 name: 'timeFromNow',
14967 description: '<p>schedule a pausing time</p>\n',
14968 type: 'Number',
14969 optional: true
14970 }
14971 ],
14972 class: 'p5.SoundLoop',
14973 module: 'p5.sound'
14974 },
14975 syncedStart: {
14976 name: 'syncedStart',
14977 params: [
14978 {
14979 name: 'otherLoop',
14980 description: '<p>a p5.SoundLoop to sync with</p>\n',
14981 type: 'Object'
14982 },
14983 {
14984 name: 'timeFromNow',
14985 description:
14986 '<p>Start the loops in sync after timeFromNow seconds</p>\n',
14987 type: 'Number',
14988 optional: true
14989 }
14990 ],
14991 class: 'p5.SoundLoop',
14992 module: 'p5.sound'
14993 },
14994 bpm: {
14995 name: 'bpm',
14996 class: 'p5.SoundLoop',
14997 module: 'p5.sound'
14998 },
14999 timeSignature: {
15000 name: 'timeSignature',
15001 class: 'p5.SoundLoop',
15002 module: 'p5.sound'
15003 },
15004 interval: {
15005 name: 'interval',
15006 class: 'p5.SoundLoop',
15007 module: 'p5.sound'
15008 },
15009 iterations: {
15010 name: 'iterations',
15011 class: 'p5.SoundLoop',
15012 module: 'p5.sound'
15013 }
15014 },
15015 'p5.Compressor': {
15016 compressor: {
15017 name: 'compressor',
15018 class: 'p5.Compressor',
15019 module: 'p5.sound'
15020 },
15021 process: {
15022 name: 'process',
15023 params: [
15024 {
15025 name: 'src',
15026 description: '<p>Sound source to be connected</p>\n',
15027 type: 'Object'
15028 },
15029 {
15030 name: 'attack',
15031 description:
15032 '<p>The amount of time (in seconds) to reduce the gain by 10dB,\n default = .003, range 0 - 1</p>\n',
15033 type: 'Number',
15034 optional: true
15035 },
15036 {
15037 name: 'knee',
15038 description:
15039 '<p>A decibel value representing the range above the\n threshold where the curve smoothly transitions to the "ratio" portion.\n default = 30, range 0 - 40</p>\n',
15040 type: 'Number',
15041 optional: true
15042 },
15043 {
15044 name: 'ratio',
15045 description:
15046 '<p>The amount of dB change in input for a 1 dB change in output\n default = 12, range 1 - 20</p>\n',
15047 type: 'Number',
15048 optional: true
15049 },
15050 {
15051 name: 'threshold',
15052 description:
15053 '<p>The decibel value above which the compression will start taking effect\n default = -24, range -100 - 0</p>\n',
15054 type: 'Number',
15055 optional: true
15056 },
15057 {
15058 name: 'release',
15059 description:
15060 '<p>The amount of time (in seconds) to increase the gain by 10dB\n default = .25, range 0 - 1</p>\n',
15061 type: 'Number',
15062 optional: true
15063 }
15064 ],
15065 class: 'p5.Compressor',
15066 module: 'p5.sound'
15067 },
15068 set: {
15069 name: 'set',
15070 params: [
15071 {
15072 name: 'attack',
15073 description:
15074 '<p>The amount of time (in seconds) to reduce the gain by 10dB,\n default = .003, range 0 - 1</p>\n',
15075 type: 'Number'
15076 },
15077 {
15078 name: 'knee',
15079 description:
15080 '<p>A decibel value representing the range above the\n threshold where the curve smoothly transitions to the "ratio" portion.\n default = 30, range 0 - 40</p>\n',
15081 type: 'Number'
15082 },
15083 {
15084 name: 'ratio',
15085 description:
15086 '<p>The amount of dB change in input for a 1 dB change in output\n default = 12, range 1 - 20</p>\n',
15087 type: 'Number'
15088 },
15089 {
15090 name: 'threshold',
15091 description:
15092 '<p>The decibel value above which the compression will start taking effect\n default = -24, range -100 - 0</p>\n',
15093 type: 'Number'
15094 },
15095 {
15096 name: 'release',
15097 description:
15098 '<p>The amount of time (in seconds) to increase the gain by 10dB\n default = .25, range 0 - 1</p>\n',
15099 type: 'Number'
15100 }
15101 ],
15102 class: 'p5.Compressor',
15103 module: 'p5.sound'
15104 },
15105 attack: {
15106 name: 'attack',
15107 params: [
15108 {
15109 name: 'attack',
15110 description:
15111 '<p>Attack is the amount of time (in seconds) to reduce the gain by 10dB,\n default = .003, range 0 - 1</p>\n',
15112 type: 'Number',
15113 optional: true
15114 },
15115 {
15116 name: 'time',
15117 description:
15118 '<p>Assign time value to schedule the change in value</p>\n',
15119 type: 'Number',
15120 optional: true
15121 }
15122 ],
15123 class: 'p5.Compressor',
15124 module: 'p5.sound'
15125 },
15126 knee: {
15127 name: 'knee',
15128 params: [
15129 {
15130 name: 'knee',
15131 description:
15132 '<p>A decibel value representing the range above the\n threshold where the curve smoothly transitions to the "ratio" portion.\n default = 30, range 0 - 40</p>\n',
15133 type: 'Number',
15134 optional: true
15135 },
15136 {
15137 name: 'time',
15138 description:
15139 '<p>Assign time value to schedule the change in value</p>\n',
15140 type: 'Number',
15141 optional: true
15142 }
15143 ],
15144 class: 'p5.Compressor',
15145 module: 'p5.sound'
15146 },
15147 ratio: {
15148 name: 'ratio',
15149 params: [
15150 {
15151 name: 'ratio',
15152 description:
15153 '<p>The amount of dB change in input for a 1 dB change in output\n default = 12, range 1 - 20</p>\n',
15154 type: 'Number',
15155 optional: true
15156 },
15157 {
15158 name: 'time',
15159 description:
15160 '<p>Assign time value to schedule the change in value</p>\n',
15161 type: 'Number',
15162 optional: true
15163 }
15164 ],
15165 class: 'p5.Compressor',
15166 module: 'p5.sound'
15167 },
15168 threshold: {
15169 name: 'threshold',
15170 params: [
15171 {
15172 name: 'threshold',
15173 description:
15174 '<p>The decibel value above which the compression will start taking effect\n default = -24, range -100 - 0</p>\n',
15175 type: 'Number'
15176 },
15177 {
15178 name: 'time',
15179 description:
15180 '<p>Assign time value to schedule the change in value</p>\n',
15181 type: 'Number',
15182 optional: true
15183 }
15184 ],
15185 class: 'p5.Compressor',
15186 module: 'p5.sound'
15187 },
15188 release: {
15189 name: 'release',
15190 params: [
15191 {
15192 name: 'release',
15193 description:
15194 '<p>The amount of time (in seconds) to increase the gain by 10dB\n default = .25, range 0 - 1</p>\n',
15195 type: 'Number'
15196 },
15197 {
15198 name: 'time',
15199 description:
15200 '<p>Assign time value to schedule the change in value</p>\n',
15201 type: 'Number',
15202 optional: true
15203 }
15204 ],
15205 class: 'p5.Compressor',
15206 module: 'p5.sound'
15207 },
15208 reduction: {
15209 name: 'reduction',
15210 class: 'p5.Compressor',
15211 module: 'p5.sound'
15212 }
15213 },
15214 'p5.SoundRecorder': {
15215 setInput: {
15216 name: 'setInput',
15217 params: [
15218 {
15219 name: 'unit',
15220 description:
15221 '<p>p5.sound object or a web audio unit\n that outputs sound</p>\n',
15222 type: 'Object',
15223 optional: true
15224 }
15225 ],
15226 class: 'p5.SoundRecorder',
15227 module: 'p5.sound'
15228 },
15229 record: {
15230 name: 'record',
15231 params: [
15232 {
15233 name: 'soundFile',
15234 description: '<p>p5.SoundFile</p>\n',
15235 type: 'p5.SoundFile'
15236 },
15237 {
15238 name: 'duration',
15239 description: '<p>Time (in seconds)</p>\n',
15240 type: 'Number',
15241 optional: true
15242 },
15243 {
15244 name: 'callback',
15245 description:
15246 '<p>The name of a function that will be\n called once the recording completes</p>\n',
15247 type: 'Function',
15248 optional: true
15249 }
15250 ],
15251 class: 'p5.SoundRecorder',
15252 module: 'p5.sound'
15253 },
15254 stop: {
15255 name: 'stop',
15256 class: 'p5.SoundRecorder',
15257 module: 'p5.sound'
15258 }
15259 },
15260 'p5.PeakDetect': {
15261 isDetected: {
15262 name: 'isDetected',
15263 class: 'p5.PeakDetect',
15264 module: 'p5.sound'
15265 },
15266 update: {
15267 name: 'update',
15268 params: [
15269 {
15270 name: 'fftObject',
15271 description: '<p>A p5.FFT object</p>\n',
15272 type: 'p5.FFT'
15273 }
15274 ],
15275 class: 'p5.PeakDetect',
15276 module: 'p5.sound'
15277 },
15278 onPeak: {
15279 name: 'onPeak',
15280 params: [
15281 {
15282 name: 'callback',
15283 description:
15284 '<p>Name of a function that will\n be called when a peak is\n detected.</p>\n',
15285 type: 'Function'
15286 },
15287 {
15288 name: 'val',
15289 description:
15290 '<p>Optional value to pass\n into the function when\n a peak is detected.</p>\n',
15291 type: 'Object',
15292 optional: true
15293 }
15294 ],
15295 class: 'p5.PeakDetect',
15296 module: 'p5.sound'
15297 }
15298 },
15299 'p5.Gain': {
15300 setInput: {
15301 name: 'setInput',
15302 params: [
15303 {
15304 name: 'src',
15305 description:
15306 '<p>p5.sound / Web Audio object with a sound\n output.</p>\n',
15307 type: 'Object'
15308 }
15309 ],
15310 class: 'p5.Gain',
15311 module: 'p5.sound'
15312 },
15313 connect: {
15314 name: 'connect',
15315 params: [
15316 {
15317 name: 'unit',
15318 description: '',
15319 type: 'Object'
15320 }
15321 ],
15322 class: 'p5.Gain',
15323 module: 'p5.sound'
15324 },
15325 disconnect: {
15326 name: 'disconnect',
15327 class: 'p5.Gain',
15328 module: 'p5.sound'
15329 },
15330 amp: {
15331 name: 'amp',
15332 params: [
15333 {
15334 name: 'volume',
15335 description: '<p>amplitude between 0 and 1.0</p>\n',
15336 type: 'Number'
15337 },
15338 {
15339 name: 'rampTime',
15340 description: '<p>create a fade that lasts rampTime</p>\n',
15341 type: 'Number',
15342 optional: true
15343 },
15344 {
15345 name: 'timeFromNow',
15346 description:
15347 '<p>schedule this event to happen\n seconds from now</p>\n',
15348 type: 'Number',
15349 optional: true
15350 }
15351 ],
15352 class: 'p5.Gain',
15353 module: 'p5.sound'
15354 }
15355 },
15356 'p5.Distortion': {
15357 WaveShaperNode: {
15358 name: 'WaveShaperNode',
15359 class: 'p5.Distortion',
15360 module: 'p5.sound'
15361 },
15362 process: {
15363 name: 'process',
15364 params: [
15365 {
15366 name: 'amount',
15367 description:
15368 '<p>Unbounded distortion amount.\n Normal values range from 0-1.</p>\n',
15369 type: 'Number',
15370 optional: true,
15371 optdefault: '0.25'
15372 },
15373 {
15374 name: 'oversample',
15375 description: "<p>'none', '2x', or '4x'.</p>\n",
15376 type: 'String',
15377 optional: true,
15378 optdefault: "'none'"
15379 }
15380 ],
15381 class: 'p5.Distortion',
15382 module: 'p5.sound'
15383 },
15384 set: {
15385 name: 'set',
15386 params: [
15387 {
15388 name: 'amount',
15389 description:
15390 '<p>Unbounded distortion amount.\n Normal values range from 0-1.</p>\n',
15391 type: 'Number',
15392 optional: true,
15393 optdefault: '0.25'
15394 },
15395 {
15396 name: 'oversample',
15397 description: "<p>'none', '2x', or '4x'.</p>\n",
15398 type: 'String',
15399 optional: true,
15400 optdefault: "'none'"
15401 }
15402 ],
15403 class: 'p5.Distortion',
15404 module: 'p5.sound'
15405 },
15406 getAmount: {
15407 name: 'getAmount',
15408 class: 'p5.Distortion',
15409 module: 'p5.sound'
15410 },
15411 getOversample: {
15412 name: 'getOversample',
15413 class: 'p5.Distortion',
15414 module: 'p5.sound'
15415 }
15416 }
15417 };
15418 },
15419 {}
15420 ],
15421 2: [
15422 function(_dereq_, module, exports) {
15423 function _arrayWithHoles(arr) {
15424 if (Array.isArray(arr)) return arr;
15425 }
15426
15427 module.exports = _arrayWithHoles;
15428 },
15429 {}
15430 ],
15431 3: [
15432 function(_dereq_, module, exports) {
15433 function _arrayWithoutHoles(arr) {
15434 if (Array.isArray(arr)) {
15435 for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) {
15436 arr2[i] = arr[i];
15437 }
15438
15439 return arr2;
15440 }
15441 }
15442
15443 module.exports = _arrayWithoutHoles;
15444 },
15445 {}
15446 ],
15447 4: [
15448 function(_dereq_, module, exports) {
15449 function _assertThisInitialized(self) {
15450 if (self === void 0) {
15451 throw new ReferenceError(
15452 "this hasn't been initialised - super() hasn't been called"
15453 );
15454 }
15455
15456 return self;
15457 }
15458
15459 module.exports = _assertThisInitialized;
15460 },
15461 {}
15462 ],
15463 5: [
15464 function(_dereq_, module, exports) {
15465 function _classCallCheck(instance, Constructor) {
15466 if (!(instance instanceof Constructor)) {
15467 throw new TypeError('Cannot call a class as a function');
15468 }
15469 }
15470
15471 module.exports = _classCallCheck;
15472 },
15473 {}
15474 ],
15475 6: [
15476 function(_dereq_, module, exports) {
15477 function _defineProperties(target, props) {
15478 for (var i = 0; i < props.length; i++) {
15479 var descriptor = props[i];
15480 descriptor.enumerable = descriptor.enumerable || false;
15481 descriptor.configurable = true;
15482 if ('value' in descriptor) descriptor.writable = true;
15483 Object.defineProperty(target, descriptor.key, descriptor);
15484 }
15485 }
15486
15487 function _createClass(Constructor, protoProps, staticProps) {
15488 if (protoProps) _defineProperties(Constructor.prototype, protoProps);
15489 if (staticProps) _defineProperties(Constructor, staticProps);
15490 return Constructor;
15491 }
15492
15493 module.exports = _createClass;
15494 },
15495 {}
15496 ],
15497 7: [
15498 function(_dereq_, module, exports) {
15499 function _defineProperty(obj, key, value) {
15500 if (key in obj) {
15501 Object.defineProperty(obj, key, {
15502 value: value,
15503 enumerable: true,
15504 configurable: true,
15505 writable: true
15506 });
15507 } else {
15508 obj[key] = value;
15509 }
15510
15511 return obj;
15512 }
15513
15514 module.exports = _defineProperty;
15515 },
15516 {}
15517 ],
15518 8: [
15519 function(_dereq_, module, exports) {
15520 function _getPrototypeOf(o) {
15521 module.exports = _getPrototypeOf = Object.setPrototypeOf
15522 ? Object.getPrototypeOf
15523 : function _getPrototypeOf(o) {
15524 return o.__proto__ || Object.getPrototypeOf(o);
15525 };
15526 return _getPrototypeOf(o);
15527 }
15528
15529 module.exports = _getPrototypeOf;
15530 },
15531 {}
15532 ],
15533 9: [
15534 function(_dereq_, module, exports) {
15535 var setPrototypeOf = _dereq_('./setPrototypeOf');
15536
15537 function _inherits(subClass, superClass) {
15538 if (typeof superClass !== 'function' && superClass !== null) {
15539 throw new TypeError('Super expression must either be null or a function');
15540 }
15541
15542 subClass.prototype = Object.create(superClass && superClass.prototype, {
15543 constructor: {
15544 value: subClass,
15545 writable: true,
15546 configurable: true
15547 }
15548 });
15549 if (superClass) setPrototypeOf(subClass, superClass);
15550 }
15551
15552 module.exports = _inherits;
15553 },
15554 { './setPrototypeOf': 16 }
15555 ],
15556 10: [
15557 function(_dereq_, module, exports) {
15558 function _iterableToArray(iter) {
15559 if (
15560 Symbol.iterator in Object(iter) ||
15561 Object.prototype.toString.call(iter) === '[object Arguments]'
15562 )
15563 return Array.from(iter);
15564 }
15565
15566 module.exports = _iterableToArray;
15567 },
15568 {}
15569 ],
15570 11: [
15571 function(_dereq_, module, exports) {
15572 function _iterableToArrayLimit(arr, i) {
15573 var _arr = [];
15574 var _n = true;
15575 var _d = false;
15576 var _e = undefined;
15577
15578 try {
15579 for (
15580 var _i = arr[Symbol.iterator](), _s;
15581 !(_n = (_s = _i.next()).done);
15582 _n = true
15583 ) {
15584 _arr.push(_s.value);
15585
15586 if (i && _arr.length === i) break;
15587 }
15588 } catch (err) {
15589 _d = true;
15590 _e = err;
15591 } finally {
15592 try {
15593 if (!_n && _i['return'] != null) _i['return']();
15594 } finally {
15595 if (_d) throw _e;
15596 }
15597 }
15598
15599 return _arr;
15600 }
15601
15602 module.exports = _iterableToArrayLimit;
15603 },
15604 {}
15605 ],
15606 12: [
15607 function(_dereq_, module, exports) {
15608 function _nonIterableRest() {
15609 throw new TypeError('Invalid attempt to destructure non-iterable instance');
15610 }
15611
15612 module.exports = _nonIterableRest;
15613 },
15614 {}
15615 ],
15616 13: [
15617 function(_dereq_, module, exports) {
15618 function _nonIterableSpread() {
15619 throw new TypeError('Invalid attempt to spread non-iterable instance');
15620 }
15621
15622 module.exports = _nonIterableSpread;
15623 },
15624 {}
15625 ],
15626 14: [
15627 function(_dereq_, module, exports) {
15628 var defineProperty = _dereq_('./defineProperty');
15629
15630 function _objectSpread(target) {
15631 for (var i = 1; i < arguments.length; i++) {
15632 var source = arguments[i] != null ? arguments[i] : {};
15633 var ownKeys = Object.keys(source);
15634
15635 if (typeof Object.getOwnPropertySymbols === 'function') {
15636 ownKeys = ownKeys.concat(
15637 Object.getOwnPropertySymbols(source).filter(function(sym) {
15638 return Object.getOwnPropertyDescriptor(source, sym).enumerable;
15639 })
15640 );
15641 }
15642
15643 ownKeys.forEach(function(key) {
15644 defineProperty(target, key, source[key]);
15645 });
15646 }
15647
15648 return target;
15649 }
15650
15651 module.exports = _objectSpread;
15652 },
15653 { './defineProperty': 7 }
15654 ],
15655 15: [
15656 function(_dereq_, module, exports) {
15657 var _typeof = _dereq_('../helpers/typeof');
15658
15659 var assertThisInitialized = _dereq_('./assertThisInitialized');
15660
15661 function _possibleConstructorReturn(self, call) {
15662 if (call && (_typeof(call) === 'object' || typeof call === 'function')) {
15663 return call;
15664 }
15665
15666 return assertThisInitialized(self);
15667 }
15668
15669 module.exports = _possibleConstructorReturn;
15670 },
15671 { '../helpers/typeof': 19, './assertThisInitialized': 4 }
15672 ],
15673 16: [
15674 function(_dereq_, module, exports) {
15675 function _setPrototypeOf(o, p) {
15676 module.exports = _setPrototypeOf =
15677 Object.setPrototypeOf ||
15678 function _setPrototypeOf(o, p) {
15679 o.__proto__ = p;
15680 return o;
15681 };
15682
15683 return _setPrototypeOf(o, p);
15684 }
15685
15686 module.exports = _setPrototypeOf;
15687 },
15688 {}
15689 ],
15690 17: [
15691 function(_dereq_, module, exports) {
15692 var arrayWithHoles = _dereq_('./arrayWithHoles');
15693
15694 var iterableToArrayLimit = _dereq_('./iterableToArrayLimit');
15695
15696 var nonIterableRest = _dereq_('./nonIterableRest');
15697
15698 function _slicedToArray(arr, i) {
15699 return arrayWithHoles(arr) || iterableToArrayLimit(arr, i) || nonIterableRest();
15700 }
15701
15702 module.exports = _slicedToArray;
15703 },
15704 { './arrayWithHoles': 2, './iterableToArrayLimit': 11, './nonIterableRest': 12 }
15705 ],
15706 18: [
15707 function(_dereq_, module, exports) {
15708 var arrayWithoutHoles = _dereq_('./arrayWithoutHoles');
15709
15710 var iterableToArray = _dereq_('./iterableToArray');
15711
15712 var nonIterableSpread = _dereq_('./nonIterableSpread');
15713
15714 function _toConsumableArray(arr) {
15715 return arrayWithoutHoles(arr) || iterableToArray(arr) || nonIterableSpread();
15716 }
15717
15718 module.exports = _toConsumableArray;
15719 },
15720 { './arrayWithoutHoles': 3, './iterableToArray': 10, './nonIterableSpread': 13 }
15721 ],
15722 19: [
15723 function(_dereq_, module, exports) {
15724 function _typeof2(obj) {
15725 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
15726 _typeof2 = function _typeof2(obj) {
15727 return typeof obj;
15728 };
15729 } else {
15730 _typeof2 = function _typeof2(obj) {
15731 return obj &&
15732 typeof Symbol === 'function' &&
15733 obj.constructor === Symbol &&
15734 obj !== Symbol.prototype
15735 ? 'symbol'
15736 : typeof obj;
15737 };
15738 }
15739 return _typeof2(obj);
15740 }
15741
15742 function _typeof(obj) {
15743 if (typeof Symbol === 'function' && _typeof2(Symbol.iterator) === 'symbol') {
15744 module.exports = _typeof = function _typeof(obj) {
15745 return _typeof2(obj);
15746 };
15747 } else {
15748 module.exports = _typeof = function _typeof(obj) {
15749 return obj &&
15750 typeof Symbol === 'function' &&
15751 obj.constructor === Symbol &&
15752 obj !== Symbol.prototype
15753 ? 'symbol'
15754 : _typeof2(obj);
15755 };
15756 }
15757
15758 return _typeof(obj);
15759 }
15760
15761 module.exports = _typeof;
15762 },
15763 {}
15764 ],
15765 20: [
15766 function(_dereq_, module, exports) {
15767 'use strict';
15768
15769 exports.byteLength = byteLength;
15770 exports.toByteArray = toByteArray;
15771 exports.fromByteArray = fromByteArray;
15772
15773 var lookup = [];
15774 var revLookup = [];
15775 var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array;
15776
15777 var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
15778 for (var i = 0, len = code.length; i < len; ++i) {
15779 lookup[i] = code[i];
15780 revLookup[code.charCodeAt(i)] = i;
15781 }
15782
15783 // Support decoding URL-safe base64 strings, as Node.js does.
15784 // See: https://en.wikipedia.org/wiki/Base64#URL_applications
15785 revLookup['-'.charCodeAt(0)] = 62;
15786 revLookup['_'.charCodeAt(0)] = 63;
15787
15788 function getLens(b64) {
15789 var len = b64.length;
15790
15791 if (len % 4 > 0) {
15792 throw new Error('Invalid string. Length must be a multiple of 4');
15793 }
15794
15795 // Trim off extra bytes after placeholder bytes are found
15796 // See: https://github.com/beatgammit/base64-js/issues/42
15797 var validLen = b64.indexOf('=');
15798 if (validLen === -1) validLen = len;
15799
15800 var placeHoldersLen = validLen === len ? 0 : 4 - validLen % 4;
15801
15802 return [validLen, placeHoldersLen];
15803 }
15804
15805 // base64 is 4/3 + up to two characters of the original data
15806 function byteLength(b64) {
15807 var lens = getLens(b64);
15808 var validLen = lens[0];
15809 var placeHoldersLen = lens[1];
15810 return (validLen + placeHoldersLen) * 3 / 4 - placeHoldersLen;
15811 }
15812
15813 function _byteLength(b64, validLen, placeHoldersLen) {
15814 return (validLen + placeHoldersLen) * 3 / 4 - placeHoldersLen;
15815 }
15816
15817 function toByteArray(b64) {
15818 var tmp;
15819 var lens = getLens(b64);
15820 var validLen = lens[0];
15821 var placeHoldersLen = lens[1];
15822
15823 var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen));
15824
15825 var curByte = 0;
15826
15827 // if there are placeholders, only get up to the last complete 4 chars
15828 var len = placeHoldersLen > 0 ? validLen - 4 : validLen;
15829
15830 var i;
15831 for (i = 0; i < len; i += 4) {
15832 tmp =
15833 (revLookup[b64.charCodeAt(i)] << 18) |
15834 (revLookup[b64.charCodeAt(i + 1)] << 12) |
15835 (revLookup[b64.charCodeAt(i + 2)] << 6) |
15836 revLookup[b64.charCodeAt(i + 3)];
15837 arr[curByte++] = (tmp >> 16) & 0xff;
15838 arr[curByte++] = (tmp >> 8) & 0xff;
15839 arr[curByte++] = tmp & 0xff;
15840 }
15841
15842 if (placeHoldersLen === 2) {
15843 tmp =
15844 (revLookup[b64.charCodeAt(i)] << 2) |
15845 (revLookup[b64.charCodeAt(i + 1)] >> 4);
15846 arr[curByte++] = tmp & 0xff;
15847 }
15848
15849 if (placeHoldersLen === 1) {
15850 tmp =
15851 (revLookup[b64.charCodeAt(i)] << 10) |
15852 (revLookup[b64.charCodeAt(i + 1)] << 4) |
15853 (revLookup[b64.charCodeAt(i + 2)] >> 2);
15854 arr[curByte++] = (tmp >> 8) & 0xff;
15855 arr[curByte++] = tmp & 0xff;
15856 }
15857
15858 return arr;
15859 }
15860
15861 function tripletToBase64(num) {
15862 return (
15863 lookup[(num >> 18) & 0x3f] +
15864 lookup[(num >> 12) & 0x3f] +
15865 lookup[(num >> 6) & 0x3f] +
15866 lookup[num & 0x3f]
15867 );
15868 }
15869
15870 function encodeChunk(uint8, start, end) {
15871 var tmp;
15872 var output = [];
15873 for (var i = start; i < end; i += 3) {
15874 tmp =
15875 ((uint8[i] << 16) & 0xff0000) +
15876 ((uint8[i + 1] << 8) & 0xff00) +
15877 (uint8[i + 2] & 0xff);
15878 output.push(tripletToBase64(tmp));
15879 }
15880 return output.join('');
15881 }
15882
15883 function fromByteArray(uint8) {
15884 var tmp;
15885 var len = uint8.length;
15886 var extraBytes = len % 3; // if we have 1 byte left, pad 2 bytes
15887 var parts = [];
15888 var maxChunkLength = 16383; // must be multiple of 3
15889
15890 // go through the array every three bytes, we'll deal with trailing stuff later
15891 for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
15892 parts.push(
15893 encodeChunk(uint8, i, i + maxChunkLength > len2 ? len2 : i + maxChunkLength)
15894 );
15895 }
15896
15897 // pad the end with zeros, but make sure to not forget the extra bytes
15898 if (extraBytes === 1) {
15899 tmp = uint8[len - 1];
15900 parts.push(lookup[tmp >> 2] + lookup[(tmp << 4) & 0x3f] + '==');
15901 } else if (extraBytes === 2) {
15902 tmp = (uint8[len - 2] << 8) + uint8[len - 1];
15903 parts.push(
15904 lookup[tmp >> 10] +
15905 lookup[(tmp >> 4) & 0x3f] +
15906 lookup[(tmp << 2) & 0x3f] +
15907 '='
15908 );
15909 }
15910
15911 return parts.join('');
15912 }
15913 },
15914 {}
15915 ],
15916 21: [function(_dereq_, module, exports) {}, {}],
15917 22: [
15918 function(_dereq_, module, exports) {
15919 (function(Buffer) {
15920 /*!
15921 * The buffer module from node.js, for the browser.
15922 *
15923 * @author Feross Aboukhadijeh <https://feross.org>
15924 * @license MIT
15925 */
15926 /* eslint-disable no-proto */
15927
15928 'use strict';
15929
15930 var base64 = _dereq_('base64-js');
15931 var ieee754 = _dereq_('ieee754');
15932 var customInspectSymbol =
15933 typeof Symbol === 'function' && typeof Symbol.for === 'function'
15934 ? Symbol.for('nodejs.util.inspect.custom')
15935 : null;
15936
15937 exports.Buffer = Buffer;
15938 exports.SlowBuffer = SlowBuffer;
15939 exports.INSPECT_MAX_BYTES = 50;
15940
15941 var K_MAX_LENGTH = 0x7fffffff;
15942 exports.kMaxLength = K_MAX_LENGTH;
15943
15944 /**
15945 * If `Buffer.TYPED_ARRAY_SUPPORT`:
15946 * === true Use Uint8Array implementation (fastest)
15947 * === false Print warning and recommend using `buffer` v4.x which has an Object
15948 * implementation (most compatible, even IE6)
15949 *
15950 * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
15951 * Opera 11.6+, iOS 4.2+.
15952 *
15953 * We report that the browser does not support typed arrays if the are not subclassable
15954 * using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array`
15955 * (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks support
15956 * for __proto__ and has a buggy typed array implementation.
15957 */
15958 Buffer.TYPED_ARRAY_SUPPORT = typedArraySupport();
15959
15960 if (
15961 !Buffer.TYPED_ARRAY_SUPPORT &&
15962 typeof console !== 'undefined' &&
15963 typeof console.error === 'function'
15964 ) {
15965 console.error(
15966 'This browser lacks typed array (Uint8Array) support which is required by ' +
15967 '`buffer` v5.x. Use `buffer` v4.x if you require old browser support.'
15968 );
15969 }
15970
15971 function typedArraySupport() {
15972 // Can typed array instances can be augmented?
15973 try {
15974 var arr = new Uint8Array(1);
15975 var proto = {
15976 foo: function() {
15977 return 42;
15978 }
15979 };
15980 Object.setPrototypeOf(proto, Uint8Array.prototype);
15981 Object.setPrototypeOf(arr, proto);
15982 return arr.foo() === 42;
15983 } catch (e) {
15984 return false;
15985 }
15986 }
15987
15988 Object.defineProperty(Buffer.prototype, 'parent', {
15989 enumerable: true,
15990 get: function() {
15991 if (!Buffer.isBuffer(this)) return undefined;
15992 return this.buffer;
15993 }
15994 });
15995
15996 Object.defineProperty(Buffer.prototype, 'offset', {
15997 enumerable: true,
15998 get: function() {
15999 if (!Buffer.isBuffer(this)) return undefined;
16000 return this.byteOffset;
16001 }
16002 });
16003
16004 function createBuffer(length) {
16005 if (length > K_MAX_LENGTH) {
16006 throw new RangeError(
16007 'The value "' + length + '" is invalid for option "size"'
16008 );
16009 }
16010 // Return an augmented `Uint8Array` instance
16011 var buf = new Uint8Array(length);
16012 Object.setPrototypeOf(buf, Buffer.prototype);
16013 return buf;
16014 }
16015
16016 /**
16017 * The Buffer constructor returns instances of `Uint8Array` that have their
16018 * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of
16019 * `Uint8Array`, so the returned instances will have all the node `Buffer` methods
16020 * and the `Uint8Array` methods. Square bracket notation works as expected -- it
16021 * returns a single octet.
16022 *
16023 * The `Uint8Array` prototype remains unmodified.
16024 */
16025
16026 function Buffer(arg, encodingOrOffset, length) {
16027 // Common case.
16028 if (typeof arg === 'number') {
16029 if (typeof encodingOrOffset === 'string') {
16030 throw new TypeError(
16031 'The "string" argument must be of type string. Received type number'
16032 );
16033 }
16034 return allocUnsafe(arg);
16035 }
16036 return from(arg, encodingOrOffset, length);
16037 }
16038
16039 // Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97
16040 if (
16041 typeof Symbol !== 'undefined' &&
16042 Symbol.species != null &&
16043 Buffer[Symbol.species] === Buffer
16044 ) {
16045 Object.defineProperty(Buffer, Symbol.species, {
16046 value: null,
16047 configurable: true,
16048 enumerable: false,
16049 writable: false
16050 });
16051 }
16052
16053 Buffer.poolSize = 8192; // not used by this implementation
16054
16055 function from(value, encodingOrOffset, length) {
16056 if (typeof value === 'string') {
16057 return fromString(value, encodingOrOffset);
16058 }
16059
16060 if (ArrayBuffer.isView(value)) {
16061 return fromArrayLike(value);
16062 }
16063
16064 if (value == null) {
16065 throw new TypeError(
16066 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' +
16067 'or Array-like Object. Received type ' +
16068 typeof value
16069 );
16070 }
16071
16072 if (
16073 isInstance(value, ArrayBuffer) ||
16074 (value && isInstance(value.buffer, ArrayBuffer))
16075 ) {
16076 return fromArrayBuffer(value, encodingOrOffset, length);
16077 }
16078
16079 if (typeof value === 'number') {
16080 throw new TypeError(
16081 'The "value" argument must not be of type number. Received type number'
16082 );
16083 }
16084
16085 var valueOf = value.valueOf && value.valueOf();
16086 if (valueOf != null && valueOf !== value) {
16087 return Buffer.from(valueOf, encodingOrOffset, length);
16088 }
16089
16090 var b = fromObject(value);
16091 if (b) return b;
16092
16093 if (
16094 typeof Symbol !== 'undefined' &&
16095 Symbol.toPrimitive != null &&
16096 typeof value[Symbol.toPrimitive] === 'function'
16097 ) {
16098 return Buffer.from(
16099 value[Symbol.toPrimitive]('string'),
16100 encodingOrOffset,
16101 length
16102 );
16103 }
16104
16105 throw new TypeError(
16106 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' +
16107 'or Array-like Object. Received type ' +
16108 typeof value
16109 );
16110 }
16111
16112 /**
16113 * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError
16114 * if value is a number.
16115 * Buffer.from(str[, encoding])
16116 * Buffer.from(array)
16117 * Buffer.from(buffer)
16118 * Buffer.from(arrayBuffer[, byteOffset[, length]])
16119 **/
16120 Buffer.from = function(value, encodingOrOffset, length) {
16121 return from(value, encodingOrOffset, length);
16122 };
16123
16124 // Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug:
16125 // https://github.com/feross/buffer/pull/148
16126 Object.setPrototypeOf(Buffer.prototype, Uint8Array.prototype);
16127 Object.setPrototypeOf(Buffer, Uint8Array);
16128
16129 function assertSize(size) {
16130 if (typeof size !== 'number') {
16131 throw new TypeError('"size" argument must be of type number');
16132 } else if (size < 0) {
16133 throw new RangeError(
16134 'The value "' + size + '" is invalid for option "size"'
16135 );
16136 }
16137 }
16138
16139 function alloc(size, fill, encoding) {
16140 assertSize(size);
16141 if (size <= 0) {
16142 return createBuffer(size);
16143 }
16144 if (fill !== undefined) {
16145 // Only pay attention to encoding if it's a string. This
16146 // prevents accidentally sending in a number that would
16147 // be interpretted as a start offset.
16148 return typeof encoding === 'string'
16149 ? createBuffer(size).fill(fill, encoding)
16150 : createBuffer(size).fill(fill);
16151 }
16152 return createBuffer(size);
16153 }
16154
16155 /**
16156 * Creates a new filled Buffer instance.
16157 * alloc(size[, fill[, encoding]])
16158 **/
16159 Buffer.alloc = function(size, fill, encoding) {
16160 return alloc(size, fill, encoding);
16161 };
16162
16163 function allocUnsafe(size) {
16164 assertSize(size);
16165 return createBuffer(size < 0 ? 0 : checked(size) | 0);
16166 }
16167
16168 /**
16169 * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance.
16170 * */
16171 Buffer.allocUnsafe = function(size) {
16172 return allocUnsafe(size);
16173 };
16174 /**
16175 * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance.
16176 */
16177 Buffer.allocUnsafeSlow = function(size) {
16178 return allocUnsafe(size);
16179 };
16180
16181 function fromString(string, encoding) {
16182 if (typeof encoding !== 'string' || encoding === '') {
16183 encoding = 'utf8';
16184 }
16185
16186 if (!Buffer.isEncoding(encoding)) {
16187 throw new TypeError('Unknown encoding: ' + encoding);
16188 }
16189
16190 var length = byteLength(string, encoding) | 0;
16191 var buf = createBuffer(length);
16192
16193 var actual = buf.write(string, encoding);
16194
16195 if (actual !== length) {
16196 // Writing a hex string, for example, that contains invalid characters will
16197 // cause everything after the first invalid character to be ignored. (e.g.
16198 // 'abxxcd' will be treated as 'ab')
16199 buf = buf.slice(0, actual);
16200 }
16201
16202 return buf;
16203 }
16204
16205 function fromArrayLike(array) {
16206 var length = array.length < 0 ? 0 : checked(array.length) | 0;
16207 var buf = createBuffer(length);
16208 for (var i = 0; i < length; i += 1) {
16209 buf[i] = array[i] & 255;
16210 }
16211 return buf;
16212 }
16213
16214 function fromArrayBuffer(array, byteOffset, length) {
16215 if (byteOffset < 0 || array.byteLength < byteOffset) {
16216 throw new RangeError('"offset" is outside of buffer bounds');
16217 }
16218
16219 if (array.byteLength < byteOffset + (length || 0)) {
16220 throw new RangeError('"length" is outside of buffer bounds');
16221 }
16222
16223 var buf;
16224 if (byteOffset === undefined && length === undefined) {
16225 buf = new Uint8Array(array);
16226 } else if (length === undefined) {
16227 buf = new Uint8Array(array, byteOffset);
16228 } else {
16229 buf = new Uint8Array(array, byteOffset, length);
16230 }
16231
16232 // Return an augmented `Uint8Array` instance
16233 Object.setPrototypeOf(buf, Buffer.prototype);
16234
16235 return buf;
16236 }
16237
16238 function fromObject(obj) {
16239 if (Buffer.isBuffer(obj)) {
16240 var len = checked(obj.length) | 0;
16241 var buf = createBuffer(len);
16242
16243 if (buf.length === 0) {
16244 return buf;
16245 }
16246
16247 obj.copy(buf, 0, 0, len);
16248 return buf;
16249 }
16250
16251 if (obj.length !== undefined) {
16252 if (typeof obj.length !== 'number' || numberIsNaN(obj.length)) {
16253 return createBuffer(0);
16254 }
16255 return fromArrayLike(obj);
16256 }
16257
16258 if (obj.type === 'Buffer' && Array.isArray(obj.data)) {
16259 return fromArrayLike(obj.data);
16260 }
16261 }
16262
16263 function checked(length) {
16264 // Note: cannot use `length < K_MAX_LENGTH` here because that fails when
16265 // length is NaN (which is otherwise coerced to zero.)
16266 if (length >= K_MAX_LENGTH) {
16267 throw new RangeError(
16268 'Attempt to allocate Buffer larger than maximum ' +
16269 'size: 0x' +
16270 K_MAX_LENGTH.toString(16) +
16271 ' bytes'
16272 );
16273 }
16274 return length | 0;
16275 }
16276
16277 function SlowBuffer(length) {
16278 if (+length != length) {
16279 // eslint-disable-line eqeqeq
16280 length = 0;
16281 }
16282 return Buffer.alloc(+length);
16283 }
16284
16285 Buffer.isBuffer = function isBuffer(b) {
16286 return b != null && b._isBuffer === true && b !== Buffer.prototype; // so Buffer.isBuffer(Buffer.prototype) will be false
16287 };
16288
16289 Buffer.compare = function compare(a, b) {
16290 if (isInstance(a, Uint8Array)) a = Buffer.from(a, a.offset, a.byteLength);
16291 if (isInstance(b, Uint8Array)) b = Buffer.from(b, b.offset, b.byteLength);
16292 if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {
16293 throw new TypeError(
16294 'The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array'
16295 );
16296 }
16297
16298 if (a === b) return 0;
16299
16300 var x = a.length;
16301 var y = b.length;
16302
16303 for (var i = 0, len = Math.min(x, y); i < len; ++i) {
16304 if (a[i] !== b[i]) {
16305 x = a[i];
16306 y = b[i];
16307 break;
16308 }
16309 }
16310
16311 if (x < y) return -1;
16312 if (y < x) return 1;
16313 return 0;
16314 };
16315
16316 Buffer.isEncoding = function isEncoding(encoding) {
16317 switch (String(encoding).toLowerCase()) {
16318 case 'hex':
16319 case 'utf8':
16320 case 'utf-8':
16321 case 'ascii':
16322 case 'latin1':
16323 case 'binary':
16324 case 'base64':
16325 case 'ucs2':
16326 case 'ucs-2':
16327 case 'utf16le':
16328 case 'utf-16le':
16329 return true;
16330 default:
16331 return false;
16332 }
16333 };
16334
16335 Buffer.concat = function concat(list, length) {
16336 if (!Array.isArray(list)) {
16337 throw new TypeError('"list" argument must be an Array of Buffers');
16338 }
16339
16340 if (list.length === 0) {
16341 return Buffer.alloc(0);
16342 }
16343
16344 var i;
16345 if (length === undefined) {
16346 length = 0;
16347 for (i = 0; i < list.length; ++i) {
16348 length += list[i].length;
16349 }
16350 }
16351
16352 var buffer = Buffer.allocUnsafe(length);
16353 var pos = 0;
16354 for (i = 0; i < list.length; ++i) {
16355 var buf = list[i];
16356 if (isInstance(buf, Uint8Array)) {
16357 buf = Buffer.from(buf);
16358 }
16359 if (!Buffer.isBuffer(buf)) {
16360 throw new TypeError('"list" argument must be an Array of Buffers');
16361 }
16362 buf.copy(buffer, pos);
16363 pos += buf.length;
16364 }
16365 return buffer;
16366 };
16367
16368 function byteLength(string, encoding) {
16369 if (Buffer.isBuffer(string)) {
16370 return string.length;
16371 }
16372 if (ArrayBuffer.isView(string) || isInstance(string, ArrayBuffer)) {
16373 return string.byteLength;
16374 }
16375 if (typeof string !== 'string') {
16376 throw new TypeError(
16377 'The "string" argument must be one of type string, Buffer, or ArrayBuffer. ' +
16378 'Received type ' +
16379 typeof string
16380 );
16381 }
16382
16383 var len = string.length;
16384 var mustMatch = arguments.length > 2 && arguments[2] === true;
16385 if (!mustMatch && len === 0) return 0;
16386
16387 // Use a for loop to avoid recursion
16388 var loweredCase = false;
16389 for (;;) {
16390 switch (encoding) {
16391 case 'ascii':
16392 case 'latin1':
16393 case 'binary':
16394 return len;
16395 case 'utf8':
16396 case 'utf-8':
16397 return utf8ToBytes(string).length;
16398 case 'ucs2':
16399 case 'ucs-2':
16400 case 'utf16le':
16401 case 'utf-16le':
16402 return len * 2;
16403 case 'hex':
16404 return len >>> 1;
16405 case 'base64':
16406 return base64ToBytes(string).length;
16407 default:
16408 if (loweredCase) {
16409 return mustMatch ? -1 : utf8ToBytes(string).length; // assume utf8
16410 }
16411 encoding = ('' + encoding).toLowerCase();
16412 loweredCase = true;
16413 }
16414 }
16415 }
16416 Buffer.byteLength = byteLength;
16417
16418 function slowToString(encoding, start, end) {
16419 var loweredCase = false;
16420
16421 // No need to verify that "this.length <= MAX_UINT32" since it's a read-only
16422 // property of a typed array.
16423
16424 // This behaves neither like String nor Uint8Array in that we set start/end
16425 // to their upper/lower bounds if the value passed is out of range.
16426 // undefined is handled specially as per ECMA-262 6th Edition,
16427 // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization.
16428 if (start === undefined || start < 0) {
16429 start = 0;
16430 }
16431 // Return early if start > this.length. Done here to prevent potential uint32
16432 // coercion fail below.
16433 if (start > this.length) {
16434 return '';
16435 }
16436
16437 if (end === undefined || end > this.length) {
16438 end = this.length;
16439 }
16440
16441 if (end <= 0) {
16442 return '';
16443 }
16444
16445 // Force coersion to uint32. This will also coerce falsey/NaN values to 0.
16446 end >>>= 0;
16447 start >>>= 0;
16448
16449 if (end <= start) {
16450 return '';
16451 }
16452
16453 if (!encoding) encoding = 'utf8';
16454
16455 while (true) {
16456 switch (encoding) {
16457 case 'hex':
16458 return hexSlice(this, start, end);
16459
16460 case 'utf8':
16461 case 'utf-8':
16462 return utf8Slice(this, start, end);
16463
16464 case 'ascii':
16465 return asciiSlice(this, start, end);
16466
16467 case 'latin1':
16468 case 'binary':
16469 return latin1Slice(this, start, end);
16470
16471 case 'base64':
16472 return base64Slice(this, start, end);
16473
16474 case 'ucs2':
16475 case 'ucs-2':
16476 case 'utf16le':
16477 case 'utf-16le':
16478 return utf16leSlice(this, start, end);
16479
16480 default:
16481 if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding);
16482 encoding = (encoding + '').toLowerCase();
16483 loweredCase = true;
16484 }
16485 }
16486 }
16487
16488 // This property is used by `Buffer.isBuffer` (and the `is-buffer` npm package)
16489 // to detect a Buffer instance. It's not possible to use `instanceof Buffer`
16490 // reliably in a browserify context because there could be multiple different
16491 // copies of the 'buffer' package in use. This method works even for Buffer
16492 // instances that were created from another copy of the `buffer` package.
16493 // See: https://github.com/feross/buffer/issues/154
16494 Buffer.prototype._isBuffer = true;
16495
16496 function swap(b, n, m) {
16497 var i = b[n];
16498 b[n] = b[m];
16499 b[m] = i;
16500 }
16501
16502 Buffer.prototype.swap16 = function swap16() {
16503 var len = this.length;
16504 if (len % 2 !== 0) {
16505 throw new RangeError('Buffer size must be a multiple of 16-bits');
16506 }
16507 for (var i = 0; i < len; i += 2) {
16508 swap(this, i, i + 1);
16509 }
16510 return this;
16511 };
16512
16513 Buffer.prototype.swap32 = function swap32() {
16514 var len = this.length;
16515 if (len % 4 !== 0) {
16516 throw new RangeError('Buffer size must be a multiple of 32-bits');
16517 }
16518 for (var i = 0; i < len; i += 4) {
16519 swap(this, i, i + 3);
16520 swap(this, i + 1, i + 2);
16521 }
16522 return this;
16523 };
16524
16525 Buffer.prototype.swap64 = function swap64() {
16526 var len = this.length;
16527 if (len % 8 !== 0) {
16528 throw new RangeError('Buffer size must be a multiple of 64-bits');
16529 }
16530 for (var i = 0; i < len; i += 8) {
16531 swap(this, i, i + 7);
16532 swap(this, i + 1, i + 6);
16533 swap(this, i + 2, i + 5);
16534 swap(this, i + 3, i + 4);
16535 }
16536 return this;
16537 };
16538
16539 Buffer.prototype.toString = function toString() {
16540 var length = this.length;
16541 if (length === 0) return '';
16542 if (arguments.length === 0) return utf8Slice(this, 0, length);
16543 return slowToString.apply(this, arguments);
16544 };
16545
16546 Buffer.prototype.toLocaleString = Buffer.prototype.toString;
16547
16548 Buffer.prototype.equals = function equals(b) {
16549 if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer');
16550 if (this === b) return true;
16551 return Buffer.compare(this, b) === 0;
16552 };
16553
16554 Buffer.prototype.inspect = function inspect() {
16555 var str = '';
16556 var max = exports.INSPECT_MAX_BYTES;
16557 str = this.toString('hex', 0, max)
16558 .replace(/(.{2})/g, '$1 ')
16559 .trim();
16560 if (this.length > max) str += ' ... ';
16561 return '<Buffer ' + str + '>';
16562 };
16563 if (customInspectSymbol) {
16564 Buffer.prototype[customInspectSymbol] = Buffer.prototype.inspect;
16565 }
16566
16567 Buffer.prototype.compare = function compare(
16568 target,
16569 start,
16570 end,
16571 thisStart,
16572 thisEnd
16573 ) {
16574 if (isInstance(target, Uint8Array)) {
16575 target = Buffer.from(target, target.offset, target.byteLength);
16576 }
16577 if (!Buffer.isBuffer(target)) {
16578 throw new TypeError(
16579 'The "target" argument must be one of type Buffer or Uint8Array. ' +
16580 'Received type ' +
16581 typeof target
16582 );
16583 }
16584
16585 if (start === undefined) {
16586 start = 0;
16587 }
16588 if (end === undefined) {
16589 end = target ? target.length : 0;
16590 }
16591 if (thisStart === undefined) {
16592 thisStart = 0;
16593 }
16594 if (thisEnd === undefined) {
16595 thisEnd = this.length;
16596 }
16597
16598 if (
16599 start < 0 ||
16600 end > target.length ||
16601 thisStart < 0 ||
16602 thisEnd > this.length
16603 ) {
16604 throw new RangeError('out of range index');
16605 }
16606
16607 if (thisStart >= thisEnd && start >= end) {
16608 return 0;
16609 }
16610 if (thisStart >= thisEnd) {
16611 return -1;
16612 }
16613 if (start >= end) {
16614 return 1;
16615 }
16616
16617 start >>>= 0;
16618 end >>>= 0;
16619 thisStart >>>= 0;
16620 thisEnd >>>= 0;
16621
16622 if (this === target) return 0;
16623
16624 var x = thisEnd - thisStart;
16625 var y = end - start;
16626 var len = Math.min(x, y);
16627
16628 var thisCopy = this.slice(thisStart, thisEnd);
16629 var targetCopy = target.slice(start, end);
16630
16631 for (var i = 0; i < len; ++i) {
16632 if (thisCopy[i] !== targetCopy[i]) {
16633 x = thisCopy[i];
16634 y = targetCopy[i];
16635 break;
16636 }
16637 }
16638
16639 if (x < y) return -1;
16640 if (y < x) return 1;
16641 return 0;
16642 };
16643
16644 // Finds either the first index of `val` in `buffer` at offset >= `byteOffset`,
16645 // OR the last index of `val` in `buffer` at offset <= `byteOffset`.
16646 //
16647 // Arguments:
16648 // - buffer - a Buffer to search
16649 // - val - a string, Buffer, or number
16650 // - byteOffset - an index into `buffer`; will be clamped to an int32
16651 // - encoding - an optional encoding, relevant is val is a string
16652 // - dir - true for indexOf, false for lastIndexOf
16653 function bidirectionalIndexOf(buffer, val, byteOffset, encoding, dir) {
16654 // Empty buffer means no match
16655 if (buffer.length === 0) return -1;
16656
16657 // Normalize byteOffset
16658 if (typeof byteOffset === 'string') {
16659 encoding = byteOffset;
16660 byteOffset = 0;
16661 } else if (byteOffset > 0x7fffffff) {
16662 byteOffset = 0x7fffffff;
16663 } else if (byteOffset < -0x80000000) {
16664 byteOffset = -0x80000000;
16665 }
16666 byteOffset = +byteOffset; // Coerce to Number.
16667 if (numberIsNaN(byteOffset)) {
16668 // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer
16669 byteOffset = dir ? 0 : buffer.length - 1;
16670 }
16671
16672 // Normalize byteOffset: negative offsets start from the end of the buffer
16673 if (byteOffset < 0) byteOffset = buffer.length + byteOffset;
16674 if (byteOffset >= buffer.length) {
16675 if (dir) return -1;
16676 else byteOffset = buffer.length - 1;
16677 } else if (byteOffset < 0) {
16678 if (dir) byteOffset = 0;
16679 else return -1;
16680 }
16681
16682 // Normalize val
16683 if (typeof val === 'string') {
16684 val = Buffer.from(val, encoding);
16685 }
16686
16687 // Finally, search either indexOf (if dir is true) or lastIndexOf
16688 if (Buffer.isBuffer(val)) {
16689 // Special case: looking for empty string/buffer always fails
16690 if (val.length === 0) {
16691 return -1;
16692 }
16693 return arrayIndexOf(buffer, val, byteOffset, encoding, dir);
16694 } else if (typeof val === 'number') {
16695 val = val & 0xff; // Search for a byte value [0-255]
16696 if (typeof Uint8Array.prototype.indexOf === 'function') {
16697 if (dir) {
16698 return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset);
16699 } else {
16700 return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset);
16701 }
16702 }
16703 return arrayIndexOf(buffer, [val], byteOffset, encoding, dir);
16704 }
16705
16706 throw new TypeError('val must be string, number or Buffer');
16707 }
16708
16709 function arrayIndexOf(arr, val, byteOffset, encoding, dir) {
16710 var indexSize = 1;
16711 var arrLength = arr.length;
16712 var valLength = val.length;
16713
16714 if (encoding !== undefined) {
16715 encoding = String(encoding).toLowerCase();
16716 if (
16717 encoding === 'ucs2' ||
16718 encoding === 'ucs-2' ||
16719 encoding === 'utf16le' ||
16720 encoding === 'utf-16le'
16721 ) {
16722 if (arr.length < 2 || val.length < 2) {
16723 return -1;
16724 }
16725 indexSize = 2;
16726 arrLength /= 2;
16727 valLength /= 2;
16728 byteOffset /= 2;
16729 }
16730 }
16731
16732 function read(buf, i) {
16733 if (indexSize === 1) {
16734 return buf[i];
16735 } else {
16736 return buf.readUInt16BE(i * indexSize);
16737 }
16738 }
16739
16740 var i;
16741 if (dir) {
16742 var foundIndex = -1;
16743 for (i = byteOffset; i < arrLength; i++) {
16744 if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) {
16745 if (foundIndex === -1) foundIndex = i;
16746 if (i - foundIndex + 1 === valLength) return foundIndex * indexSize;
16747 } else {
16748 if (foundIndex !== -1) i -= i - foundIndex;
16749 foundIndex = -1;
16750 }
16751 }
16752 } else {
16753 if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength;
16754 for (i = byteOffset; i >= 0; i--) {
16755 var found = true;
16756 for (var j = 0; j < valLength; j++) {
16757 if (read(arr, i + j) !== read(val, j)) {
16758 found = false;
16759 break;
16760 }
16761 }
16762 if (found) return i;
16763 }
16764 }
16765
16766 return -1;
16767 }
16768
16769 Buffer.prototype.includes = function includes(val, byteOffset, encoding) {
16770 return this.indexOf(val, byteOffset, encoding) !== -1;
16771 };
16772
16773 Buffer.prototype.indexOf = function indexOf(val, byteOffset, encoding) {
16774 return bidirectionalIndexOf(this, val, byteOffset, encoding, true);
16775 };
16776
16777 Buffer.prototype.lastIndexOf = function lastIndexOf(val, byteOffset, encoding) {
16778 return bidirectionalIndexOf(this, val, byteOffset, encoding, false);
16779 };
16780
16781 function hexWrite(buf, string, offset, length) {
16782 offset = Number(offset) || 0;
16783 var remaining = buf.length - offset;
16784 if (!length) {
16785 length = remaining;
16786 } else {
16787 length = Number(length);
16788 if (length > remaining) {
16789 length = remaining;
16790 }
16791 }
16792
16793 var strLen = string.length;
16794
16795 if (length > strLen / 2) {
16796 length = strLen / 2;
16797 }
16798 for (var i = 0; i < length; ++i) {
16799 var parsed = parseInt(string.substr(i * 2, 2), 16);
16800 if (numberIsNaN(parsed)) return i;
16801 buf[offset + i] = parsed;
16802 }
16803 return i;
16804 }
16805
16806 function utf8Write(buf, string, offset, length) {
16807 return blitBuffer(
16808 utf8ToBytes(string, buf.length - offset),
16809 buf,
16810 offset,
16811 length
16812 );
16813 }
16814
16815 function asciiWrite(buf, string, offset, length) {
16816 return blitBuffer(asciiToBytes(string), buf, offset, length);
16817 }
16818
16819 function latin1Write(buf, string, offset, length) {
16820 return asciiWrite(buf, string, offset, length);
16821 }
16822
16823 function base64Write(buf, string, offset, length) {
16824 return blitBuffer(base64ToBytes(string), buf, offset, length);
16825 }
16826
16827 function ucs2Write(buf, string, offset, length) {
16828 return blitBuffer(
16829 utf16leToBytes(string, buf.length - offset),
16830 buf,
16831 offset,
16832 length
16833 );
16834 }
16835
16836 Buffer.prototype.write = function write(string, offset, length, encoding) {
16837 // Buffer#write(string)
16838 if (offset === undefined) {
16839 encoding = 'utf8';
16840 length = this.length;
16841 offset = 0;
16842 // Buffer#write(string, encoding)
16843 } else if (length === undefined && typeof offset === 'string') {
16844 encoding = offset;
16845 length = this.length;
16846 offset = 0;
16847 // Buffer#write(string, offset[, length][, encoding])
16848 } else if (isFinite(offset)) {
16849 offset = offset >>> 0;
16850 if (isFinite(length)) {
16851 length = length >>> 0;
16852 if (encoding === undefined) encoding = 'utf8';
16853 } else {
16854 encoding = length;
16855 length = undefined;
16856 }
16857 } else {
16858 throw new Error(
16859 'Buffer.write(string, encoding, offset[, length]) is no longer supported'
16860 );
16861 }
16862
16863 var remaining = this.length - offset;
16864 if (length === undefined || length > remaining) length = remaining;
16865
16866 if (
16867 (string.length > 0 && (length < 0 || offset < 0)) ||
16868 offset > this.length
16869 ) {
16870 throw new RangeError('Attempt to write outside buffer bounds');
16871 }
16872
16873 if (!encoding) encoding = 'utf8';
16874
16875 var loweredCase = false;
16876 for (;;) {
16877 switch (encoding) {
16878 case 'hex':
16879 return hexWrite(this, string, offset, length);
16880
16881 case 'utf8':
16882 case 'utf-8':
16883 return utf8Write(this, string, offset, length);
16884
16885 case 'ascii':
16886 return asciiWrite(this, string, offset, length);
16887
16888 case 'latin1':
16889 case 'binary':
16890 return latin1Write(this, string, offset, length);
16891
16892 case 'base64':
16893 // Warning: maxLength not taken into account in base64Write
16894 return base64Write(this, string, offset, length);
16895
16896 case 'ucs2':
16897 case 'ucs-2':
16898 case 'utf16le':
16899 case 'utf-16le':
16900 return ucs2Write(this, string, offset, length);
16901
16902 default:
16903 if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding);
16904 encoding = ('' + encoding).toLowerCase();
16905 loweredCase = true;
16906 }
16907 }
16908 };
16909
16910 Buffer.prototype.toJSON = function toJSON() {
16911 return {
16912 type: 'Buffer',
16913 data: Array.prototype.slice.call(this._arr || this, 0)
16914 };
16915 };
16916
16917 function base64Slice(buf, start, end) {
16918 if (start === 0 && end === buf.length) {
16919 return base64.fromByteArray(buf);
16920 } else {
16921 return base64.fromByteArray(buf.slice(start, end));
16922 }
16923 }
16924
16925 function utf8Slice(buf, start, end) {
16926 end = Math.min(buf.length, end);
16927 var res = [];
16928
16929 var i = start;
16930 while (i < end) {
16931 var firstByte = buf[i];
16932 var codePoint = null;
16933 var bytesPerSequence =
16934 firstByte > 0xef ? 4 : firstByte > 0xdf ? 3 : firstByte > 0xbf ? 2 : 1;
16935
16936 if (i + bytesPerSequence <= end) {
16937 var secondByte, thirdByte, fourthByte, tempCodePoint;
16938
16939 switch (bytesPerSequence) {
16940 case 1:
16941 if (firstByte < 0x80) {
16942 codePoint = firstByte;
16943 }
16944 break;
16945 case 2:
16946 secondByte = buf[i + 1];
16947 if ((secondByte & 0xc0) === 0x80) {
16948 tempCodePoint = ((firstByte & 0x1f) << 0x6) | (secondByte & 0x3f);
16949 if (tempCodePoint > 0x7f) {
16950 codePoint = tempCodePoint;
16951 }
16952 }
16953 break;
16954 case 3:
16955 secondByte = buf[i + 1];
16956 thirdByte = buf[i + 2];
16957 if ((secondByte & 0xc0) === 0x80 && (thirdByte & 0xc0) === 0x80) {
16958 tempCodePoint =
16959 ((firstByte & 0xf) << 0xc) |
16960 ((secondByte & 0x3f) << 0x6) |
16961 (thirdByte & 0x3f);
16962 if (
16963 tempCodePoint > 0x7ff &&
16964 (tempCodePoint < 0xd800 || tempCodePoint > 0xdfff)
16965 ) {
16966 codePoint = tempCodePoint;
16967 }
16968 }
16969 break;
16970 case 4:
16971 secondByte = buf[i + 1];
16972 thirdByte = buf[i + 2];
16973 fourthByte = buf[i + 3];
16974 if (
16975 (secondByte & 0xc0) === 0x80 &&
16976 (thirdByte & 0xc0) === 0x80 &&
16977 (fourthByte & 0xc0) === 0x80
16978 ) {
16979 tempCodePoint =
16980 ((firstByte & 0xf) << 0x12) |
16981 ((secondByte & 0x3f) << 0xc) |
16982 ((thirdByte & 0x3f) << 0x6) |
16983 (fourthByte & 0x3f);
16984 if (tempCodePoint > 0xffff && tempCodePoint < 0x110000) {
16985 codePoint = tempCodePoint;
16986 }
16987 }
16988 }
16989 }
16990
16991 if (codePoint === null) {
16992 // we did not generate a valid codePoint so insert a
16993 // replacement char (U+FFFD) and advance only 1 byte
16994 codePoint = 0xfffd;
16995 bytesPerSequence = 1;
16996 } else if (codePoint > 0xffff) {
16997 // encode to utf16 (surrogate pair dance)
16998 codePoint -= 0x10000;
16999 res.push(((codePoint >>> 10) & 0x3ff) | 0xd800);
17000 codePoint = 0xdc00 | (codePoint & 0x3ff);
17001 }
17002
17003 res.push(codePoint);
17004 i += bytesPerSequence;
17005 }
17006
17007 return decodeCodePointsArray(res);
17008 }
17009
17010 // Based on http://stackoverflow.com/a/22747272/680742, the browser with
17011 // the lowest limit is Chrome, with 0x10000 args.
17012 // We go 1 magnitude less, for safety
17013 var MAX_ARGUMENTS_LENGTH = 0x1000;
17014
17015 function decodeCodePointsArray(codePoints) {
17016 var len = codePoints.length;
17017 if (len <= MAX_ARGUMENTS_LENGTH) {
17018 return String.fromCharCode.apply(String, codePoints); // avoid extra slice()
17019 }
17020
17021 // Decode in chunks to avoid "call stack size exceeded".
17022 var res = '';
17023 var i = 0;
17024 while (i < len) {
17025 res += String.fromCharCode.apply(
17026 String,
17027 codePoints.slice(i, (i += MAX_ARGUMENTS_LENGTH))
17028 );
17029 }
17030 return res;
17031 }
17032
17033 function asciiSlice(buf, start, end) {
17034 var ret = '';
17035 end = Math.min(buf.length, end);
17036
17037 for (var i = start; i < end; ++i) {
17038 ret += String.fromCharCode(buf[i] & 0x7f);
17039 }
17040 return ret;
17041 }
17042
17043 function latin1Slice(buf, start, end) {
17044 var ret = '';
17045 end = Math.min(buf.length, end);
17046
17047 for (var i = start; i < end; ++i) {
17048 ret += String.fromCharCode(buf[i]);
17049 }
17050 return ret;
17051 }
17052
17053 function hexSlice(buf, start, end) {
17054 var len = buf.length;
17055
17056 if (!start || start < 0) start = 0;
17057 if (!end || end < 0 || end > len) end = len;
17058
17059 var out = '';
17060 for (var i = start; i < end; ++i) {
17061 out += hexSliceLookupTable[buf[i]];
17062 }
17063 return out;
17064 }
17065
17066 function utf16leSlice(buf, start, end) {
17067 var bytes = buf.slice(start, end);
17068 var res = '';
17069 for (var i = 0; i < bytes.length; i += 2) {
17070 res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256);
17071 }
17072 return res;
17073 }
17074
17075 Buffer.prototype.slice = function slice(start, end) {
17076 var len = this.length;
17077 start = ~~start;
17078 end = end === undefined ? len : ~~end;
17079
17080 if (start < 0) {
17081 start += len;
17082 if (start < 0) start = 0;
17083 } else if (start > len) {
17084 start = len;
17085 }
17086
17087 if (end < 0) {
17088 end += len;
17089 if (end < 0) end = 0;
17090 } else if (end > len) {
17091 end = len;
17092 }
17093
17094 if (end < start) end = start;
17095
17096 var newBuf = this.subarray(start, end);
17097 // Return an augmented `Uint8Array` instance
17098 Object.setPrototypeOf(newBuf, Buffer.prototype);
17099
17100 return newBuf;
17101 };
17102
17103 /*
17104 * Need to make sure that buffer isn't trying to write out of bounds.
17105 */
17106 function checkOffset(offset, ext, length) {
17107 if (offset % 1 !== 0 || offset < 0)
17108 throw new RangeError('offset is not uint');
17109 if (offset + ext > length)
17110 throw new RangeError('Trying to access beyond buffer length');
17111 }
17112
17113 Buffer.prototype.readUIntLE = function readUIntLE(
17114 offset,
17115 byteLength,
17116 noAssert
17117 ) {
17118 offset = offset >>> 0;
17119 byteLength = byteLength >>> 0;
17120 if (!noAssert) checkOffset(offset, byteLength, this.length);
17121
17122 var val = this[offset];
17123 var mul = 1;
17124 var i = 0;
17125 while (++i < byteLength && (mul *= 0x100)) {
17126 val += this[offset + i] * mul;
17127 }
17128
17129 return val;
17130 };
17131
17132 Buffer.prototype.readUIntBE = function readUIntBE(
17133 offset,
17134 byteLength,
17135 noAssert
17136 ) {
17137 offset = offset >>> 0;
17138 byteLength = byteLength >>> 0;
17139 if (!noAssert) {
17140 checkOffset(offset, byteLength, this.length);
17141 }
17142
17143 var val = this[offset + --byteLength];
17144 var mul = 1;
17145 while (byteLength > 0 && (mul *= 0x100)) {
17146 val += this[offset + --byteLength] * mul;
17147 }
17148
17149 return val;
17150 };
17151
17152 Buffer.prototype.readUInt8 = function readUInt8(offset, noAssert) {
17153 offset = offset >>> 0;
17154 if (!noAssert) checkOffset(offset, 1, this.length);
17155 return this[offset];
17156 };
17157
17158 Buffer.prototype.readUInt16LE = function readUInt16LE(offset, noAssert) {
17159 offset = offset >>> 0;
17160 if (!noAssert) checkOffset(offset, 2, this.length);
17161 return this[offset] | (this[offset + 1] << 8);
17162 };
17163
17164 Buffer.prototype.readUInt16BE = function readUInt16BE(offset, noAssert) {
17165 offset = offset >>> 0;
17166 if (!noAssert) checkOffset(offset, 2, this.length);
17167 return (this[offset] << 8) | this[offset + 1];
17168 };
17169
17170 Buffer.prototype.readUInt32LE = function readUInt32LE(offset, noAssert) {
17171 offset = offset >>> 0;
17172 if (!noAssert) checkOffset(offset, 4, this.length);
17173
17174 return (
17175 (this[offset] | (this[offset + 1] << 8) | (this[offset + 2] << 16)) +
17176 this[offset + 3] * 0x1000000
17177 );
17178 };
17179
17180 Buffer.prototype.readUInt32BE = function readUInt32BE(offset, noAssert) {
17181 offset = offset >>> 0;
17182 if (!noAssert) checkOffset(offset, 4, this.length);
17183
17184 return (
17185 this[offset] * 0x1000000 +
17186 ((this[offset + 1] << 16) | (this[offset + 2] << 8) | this[offset + 3])
17187 );
17188 };
17189
17190 Buffer.prototype.readIntLE = function readIntLE(offset, byteLength, noAssert) {
17191 offset = offset >>> 0;
17192 byteLength = byteLength >>> 0;
17193 if (!noAssert) checkOffset(offset, byteLength, this.length);
17194
17195 var val = this[offset];
17196 var mul = 1;
17197 var i = 0;
17198 while (++i < byteLength && (mul *= 0x100)) {
17199 val += this[offset + i] * mul;
17200 }
17201 mul *= 0x80;
17202
17203 if (val >= mul) val -= Math.pow(2, 8 * byteLength);
17204
17205 return val;
17206 };
17207
17208 Buffer.prototype.readIntBE = function readIntBE(offset, byteLength, noAssert) {
17209 offset = offset >>> 0;
17210 byteLength = byteLength >>> 0;
17211 if (!noAssert) checkOffset(offset, byteLength, this.length);
17212
17213 var i = byteLength;
17214 var mul = 1;
17215 var val = this[offset + --i];
17216 while (i > 0 && (mul *= 0x100)) {
17217 val += this[offset + --i] * mul;
17218 }
17219 mul *= 0x80;
17220
17221 if (val >= mul) val -= Math.pow(2, 8 * byteLength);
17222
17223 return val;
17224 };
17225
17226 Buffer.prototype.readInt8 = function readInt8(offset, noAssert) {
17227 offset = offset >>> 0;
17228 if (!noAssert) checkOffset(offset, 1, this.length);
17229 if (!(this[offset] & 0x80)) return this[offset];
17230 return (0xff - this[offset] + 1) * -1;
17231 };
17232
17233 Buffer.prototype.readInt16LE = function readInt16LE(offset, noAssert) {
17234 offset = offset >>> 0;
17235 if (!noAssert) checkOffset(offset, 2, this.length);
17236 var val = this[offset] | (this[offset + 1] << 8);
17237 return val & 0x8000 ? val | 0xffff0000 : val;
17238 };
17239
17240 Buffer.prototype.readInt16BE = function readInt16BE(offset, noAssert) {
17241 offset = offset >>> 0;
17242 if (!noAssert) checkOffset(offset, 2, this.length);
17243 var val = this[offset + 1] | (this[offset] << 8);
17244 return val & 0x8000 ? val | 0xffff0000 : val;
17245 };
17246
17247 Buffer.prototype.readInt32LE = function readInt32LE(offset, noAssert) {
17248 offset = offset >>> 0;
17249 if (!noAssert) checkOffset(offset, 4, this.length);
17250
17251 return (
17252 this[offset] |
17253 (this[offset + 1] << 8) |
17254 (this[offset + 2] << 16) |
17255 (this[offset + 3] << 24)
17256 );
17257 };
17258
17259 Buffer.prototype.readInt32BE = function readInt32BE(offset, noAssert) {
17260 offset = offset >>> 0;
17261 if (!noAssert) checkOffset(offset, 4, this.length);
17262
17263 return (
17264 (this[offset] << 24) |
17265 (this[offset + 1] << 16) |
17266 (this[offset + 2] << 8) |
17267 this[offset + 3]
17268 );
17269 };
17270
17271 Buffer.prototype.readFloatLE = function readFloatLE(offset, noAssert) {
17272 offset = offset >>> 0;
17273 if (!noAssert) checkOffset(offset, 4, this.length);
17274 return ieee754.read(this, offset, true, 23, 4);
17275 };
17276
17277 Buffer.prototype.readFloatBE = function readFloatBE(offset, noAssert) {
17278 offset = offset >>> 0;
17279 if (!noAssert) checkOffset(offset, 4, this.length);
17280 return ieee754.read(this, offset, false, 23, 4);
17281 };
17282
17283 Buffer.prototype.readDoubleLE = function readDoubleLE(offset, noAssert) {
17284 offset = offset >>> 0;
17285 if (!noAssert) checkOffset(offset, 8, this.length);
17286 return ieee754.read(this, offset, true, 52, 8);
17287 };
17288
17289 Buffer.prototype.readDoubleBE = function readDoubleBE(offset, noAssert) {
17290 offset = offset >>> 0;
17291 if (!noAssert) checkOffset(offset, 8, this.length);
17292 return ieee754.read(this, offset, false, 52, 8);
17293 };
17294
17295 function checkInt(buf, value, offset, ext, max, min) {
17296 if (!Buffer.isBuffer(buf))
17297 throw new TypeError('"buffer" argument must be a Buffer instance');
17298 if (value > max || value < min)
17299 throw new RangeError('"value" argument is out of bounds');
17300 if (offset + ext > buf.length) throw new RangeError('Index out of range');
17301 }
17302
17303 Buffer.prototype.writeUIntLE = function writeUIntLE(
17304 value,
17305 offset,
17306 byteLength,
17307 noAssert
17308 ) {
17309 value = +value;
17310 offset = offset >>> 0;
17311 byteLength = byteLength >>> 0;
17312 if (!noAssert) {
17313 var maxBytes = Math.pow(2, 8 * byteLength) - 1;
17314 checkInt(this, value, offset, byteLength, maxBytes, 0);
17315 }
17316
17317 var mul = 1;
17318 var i = 0;
17319 this[offset] = value & 0xff;
17320 while (++i < byteLength && (mul *= 0x100)) {
17321 this[offset + i] = (value / mul) & 0xff;
17322 }
17323
17324 return offset + byteLength;
17325 };
17326
17327 Buffer.prototype.writeUIntBE = function writeUIntBE(
17328 value,
17329 offset,
17330 byteLength,
17331 noAssert
17332 ) {
17333 value = +value;
17334 offset = offset >>> 0;
17335 byteLength = byteLength >>> 0;
17336 if (!noAssert) {
17337 var maxBytes = Math.pow(2, 8 * byteLength) - 1;
17338 checkInt(this, value, offset, byteLength, maxBytes, 0);
17339 }
17340
17341 var i = byteLength - 1;
17342 var mul = 1;
17343 this[offset + i] = value & 0xff;
17344 while (--i >= 0 && (mul *= 0x100)) {
17345 this[offset + i] = (value / mul) & 0xff;
17346 }
17347
17348 return offset + byteLength;
17349 };
17350
17351 Buffer.prototype.writeUInt8 = function writeUInt8(value, offset, noAssert) {
17352 value = +value;
17353 offset = offset >>> 0;
17354 if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0);
17355 this[offset] = value & 0xff;
17356 return offset + 1;
17357 };
17358
17359 Buffer.prototype.writeUInt16LE = function writeUInt16LE(
17360 value,
17361 offset,
17362 noAssert
17363 ) {
17364 value = +value;
17365 offset = offset >>> 0;
17366 if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0);
17367 this[offset] = value & 0xff;
17368 this[offset + 1] = value >>> 8;
17369 return offset + 2;
17370 };
17371
17372 Buffer.prototype.writeUInt16BE = function writeUInt16BE(
17373 value,
17374 offset,
17375 noAssert
17376 ) {
17377 value = +value;
17378 offset = offset >>> 0;
17379 if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0);
17380 this[offset] = value >>> 8;
17381 this[offset + 1] = value & 0xff;
17382 return offset + 2;
17383 };
17384
17385 Buffer.prototype.writeUInt32LE = function writeUInt32LE(
17386 value,
17387 offset,
17388 noAssert
17389 ) {
17390 value = +value;
17391 offset = offset >>> 0;
17392 if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0);
17393 this[offset + 3] = value >>> 24;
17394 this[offset + 2] = value >>> 16;
17395 this[offset + 1] = value >>> 8;
17396 this[offset] = value & 0xff;
17397 return offset + 4;
17398 };
17399
17400 Buffer.prototype.writeUInt32BE = function writeUInt32BE(
17401 value,
17402 offset,
17403 noAssert
17404 ) {
17405 value = +value;
17406 offset = offset >>> 0;
17407 if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0);
17408 this[offset] = value >>> 24;
17409 this[offset + 1] = value >>> 16;
17410 this[offset + 2] = value >>> 8;
17411 this[offset + 3] = value & 0xff;
17412 return offset + 4;
17413 };
17414
17415 Buffer.prototype.writeIntLE = function writeIntLE(
17416 value,
17417 offset,
17418 byteLength,
17419 noAssert
17420 ) {
17421 value = +value;
17422 offset = offset >>> 0;
17423 if (!noAssert) {
17424 var limit = Math.pow(2, 8 * byteLength - 1);
17425
17426 checkInt(this, value, offset, byteLength, limit - 1, -limit);
17427 }
17428
17429 var i = 0;
17430 var mul = 1;
17431 var sub = 0;
17432 this[offset] = value & 0xff;
17433 while (++i < byteLength && (mul *= 0x100)) {
17434 if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) {
17435 sub = 1;
17436 }
17437 this[offset + i] = (((value / mul) >> 0) - sub) & 0xff;
17438 }
17439
17440 return offset + byteLength;
17441 };
17442
17443 Buffer.prototype.writeIntBE = function writeIntBE(
17444 value,
17445 offset,
17446 byteLength,
17447 noAssert
17448 ) {
17449 value = +value;
17450 offset = offset >>> 0;
17451 if (!noAssert) {
17452 var limit = Math.pow(2, 8 * byteLength - 1);
17453
17454 checkInt(this, value, offset, byteLength, limit - 1, -limit);
17455 }
17456
17457 var i = byteLength - 1;
17458 var mul = 1;
17459 var sub = 0;
17460 this[offset + i] = value & 0xff;
17461 while (--i >= 0 && (mul *= 0x100)) {
17462 if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) {
17463 sub = 1;
17464 }
17465 this[offset + i] = (((value / mul) >> 0) - sub) & 0xff;
17466 }
17467
17468 return offset + byteLength;
17469 };
17470
17471 Buffer.prototype.writeInt8 = function writeInt8(value, offset, noAssert) {
17472 value = +value;
17473 offset = offset >>> 0;
17474 if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80);
17475 if (value < 0) value = 0xff + value + 1;
17476 this[offset] = value & 0xff;
17477 return offset + 1;
17478 };
17479
17480 Buffer.prototype.writeInt16LE = function writeInt16LE(value, offset, noAssert) {
17481 value = +value;
17482 offset = offset >>> 0;
17483 if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000);
17484 this[offset] = value & 0xff;
17485 this[offset + 1] = value >>> 8;
17486 return offset + 2;
17487 };
17488
17489 Buffer.prototype.writeInt16BE = function writeInt16BE(value, offset, noAssert) {
17490 value = +value;
17491 offset = offset >>> 0;
17492 if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000);
17493 this[offset] = value >>> 8;
17494 this[offset + 1] = value & 0xff;
17495 return offset + 2;
17496 };
17497
17498 Buffer.prototype.writeInt32LE = function writeInt32LE(value, offset, noAssert) {
17499 value = +value;
17500 offset = offset >>> 0;
17501 if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000);
17502 this[offset] = value & 0xff;
17503 this[offset + 1] = value >>> 8;
17504 this[offset + 2] = value >>> 16;
17505 this[offset + 3] = value >>> 24;
17506 return offset + 4;
17507 };
17508
17509 Buffer.prototype.writeInt32BE = function writeInt32BE(value, offset, noAssert) {
17510 value = +value;
17511 offset = offset >>> 0;
17512 if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000);
17513 if (value < 0) value = 0xffffffff + value + 1;
17514 this[offset] = value >>> 24;
17515 this[offset + 1] = value >>> 16;
17516 this[offset + 2] = value >>> 8;
17517 this[offset + 3] = value & 0xff;
17518 return offset + 4;
17519 };
17520
17521 function checkIEEE754(buf, value, offset, ext, max, min) {
17522 if (offset + ext > buf.length) throw new RangeError('Index out of range');
17523 if (offset < 0) throw new RangeError('Index out of range');
17524 }
17525
17526 function writeFloat(buf, value, offset, littleEndian, noAssert) {
17527 value = +value;
17528 offset = offset >>> 0;
17529 if (!noAssert) {
17530 checkIEEE754(
17531 buf,
17532 value,
17533 offset,
17534 4,
17535 3.4028234663852886e38,
17536 -3.4028234663852886e38
17537 );
17538 }
17539 ieee754.write(buf, value, offset, littleEndian, 23, 4);
17540 return offset + 4;
17541 }
17542
17543 Buffer.prototype.writeFloatLE = function writeFloatLE(value, offset, noAssert) {
17544 return writeFloat(this, value, offset, true, noAssert);
17545 };
17546
17547 Buffer.prototype.writeFloatBE = function writeFloatBE(value, offset, noAssert) {
17548 return writeFloat(this, value, offset, false, noAssert);
17549 };
17550
17551 function writeDouble(buf, value, offset, littleEndian, noAssert) {
17552 value = +value;
17553 offset = offset >>> 0;
17554 if (!noAssert) {
17555 checkIEEE754(
17556 buf,
17557 value,
17558 offset,
17559 8,
17560 1.7976931348623157e308,
17561 -1.7976931348623157e308
17562 );
17563 }
17564 ieee754.write(buf, value, offset, littleEndian, 52, 8);
17565 return offset + 8;
17566 }
17567
17568 Buffer.prototype.writeDoubleLE = function writeDoubleLE(
17569 value,
17570 offset,
17571 noAssert
17572 ) {
17573 return writeDouble(this, value, offset, true, noAssert);
17574 };
17575
17576 Buffer.prototype.writeDoubleBE = function writeDoubleBE(
17577 value,
17578 offset,
17579 noAssert
17580 ) {
17581 return writeDouble(this, value, offset, false, noAssert);
17582 };
17583
17584 // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
17585 Buffer.prototype.copy = function copy(target, targetStart, start, end) {
17586 if (!Buffer.isBuffer(target))
17587 throw new TypeError('argument should be a Buffer');
17588 if (!start) start = 0;
17589 if (!end && end !== 0) end = this.length;
17590 if (targetStart >= target.length) targetStart = target.length;
17591 if (!targetStart) targetStart = 0;
17592 if (end > 0 && end < start) end = start;
17593
17594 // Copy 0 bytes; we're done
17595 if (end === start) return 0;
17596 if (target.length === 0 || this.length === 0) return 0;
17597
17598 // Fatal error conditions
17599 if (targetStart < 0) {
17600 throw new RangeError('targetStart out of bounds');
17601 }
17602 if (start < 0 || start >= this.length)
17603 throw new RangeError('Index out of range');
17604 if (end < 0) throw new RangeError('sourceEnd out of bounds');
17605
17606 // Are we oob?
17607 if (end > this.length) end = this.length;
17608 if (target.length - targetStart < end - start) {
17609 end = target.length - targetStart + start;
17610 }
17611
17612 var len = end - start;
17613
17614 if (
17615 this === target &&
17616 typeof Uint8Array.prototype.copyWithin === 'function'
17617 ) {
17618 // Use built-in when available, missing from IE11
17619 this.copyWithin(targetStart, start, end);
17620 } else if (this === target && start < targetStart && targetStart < end) {
17621 // descending copy from end
17622 for (var i = len - 1; i >= 0; --i) {
17623 target[i + targetStart] = this[i + start];
17624 }
17625 } else {
17626 Uint8Array.prototype.set.call(
17627 target,
17628 this.subarray(start, end),
17629 targetStart
17630 );
17631 }
17632
17633 return len;
17634 };
17635
17636 // Usage:
17637 // buffer.fill(number[, offset[, end]])
17638 // buffer.fill(buffer[, offset[, end]])
17639 // buffer.fill(string[, offset[, end]][, encoding])
17640 Buffer.prototype.fill = function fill(val, start, end, encoding) {
17641 // Handle string cases:
17642 if (typeof val === 'string') {
17643 if (typeof start === 'string') {
17644 encoding = start;
17645 start = 0;
17646 end = this.length;
17647 } else if (typeof end === 'string') {
17648 encoding = end;
17649 end = this.length;
17650 }
17651 if (encoding !== undefined && typeof encoding !== 'string') {
17652 throw new TypeError('encoding must be a string');
17653 }
17654 if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) {
17655 throw new TypeError('Unknown encoding: ' + encoding);
17656 }
17657 if (val.length === 1) {
17658 var code = val.charCodeAt(0);
17659 if ((encoding === 'utf8' && code < 128) || encoding === 'latin1') {
17660 // Fast path: If `val` fits into a single byte, use that numeric value.
17661 val = code;
17662 }
17663 }
17664 } else if (typeof val === 'number') {
17665 val = val & 255;
17666 } else if (typeof val === 'boolean') {
17667 val = Number(val);
17668 }
17669
17670 // Invalid ranges are not set to a default, so can range check early.
17671 if (start < 0 || this.length < start || this.length < end) {
17672 throw new RangeError('Out of range index');
17673 }
17674
17675 if (end <= start) {
17676 return this;
17677 }
17678
17679 start = start >>> 0;
17680 end = end === undefined ? this.length : end >>> 0;
17681
17682 if (!val) val = 0;
17683
17684 var i;
17685 if (typeof val === 'number') {
17686 for (i = start; i < end; ++i) {
17687 this[i] = val;
17688 }
17689 } else {
17690 var bytes = Buffer.isBuffer(val) ? val : Buffer.from(val, encoding);
17691 var len = bytes.length;
17692 if (len === 0) {
17693 throw new TypeError(
17694 'The value "' + val + '" is invalid for argument "value"'
17695 );
17696 }
17697 for (i = 0; i < end - start; ++i) {
17698 this[i + start] = bytes[i % len];
17699 }
17700 }
17701
17702 return this;
17703 };
17704
17705 // HELPER FUNCTIONS
17706 // ================
17707
17708 var INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g;
17709
17710 function base64clean(str) {
17711 // Node takes equal signs as end of the Base64 encoding
17712 str = str.split('=')[0];
17713 // Node strips out invalid characters like \n and \t from the string, base64-js does not
17714 str = str.trim().replace(INVALID_BASE64_RE, '');
17715 // Node converts strings with length < 2 to ''
17716 if (str.length < 2) return '';
17717 // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
17718 while (str.length % 4 !== 0) {
17719 str = str + '=';
17720 }
17721 return str;
17722 }
17723
17724 function utf8ToBytes(string, units) {
17725 units = units || Infinity;
17726 var codePoint;
17727 var length = string.length;
17728 var leadSurrogate = null;
17729 var bytes = [];
17730
17731 for (var i = 0; i < length; ++i) {
17732 codePoint = string.charCodeAt(i);
17733
17734 // is surrogate component
17735 if (codePoint > 0xd7ff && codePoint < 0xe000) {
17736 // last char was a lead
17737 if (!leadSurrogate) {
17738 // no lead yet
17739 if (codePoint > 0xdbff) {
17740 // unexpected trail
17741 if ((units -= 3) > -1) bytes.push(0xef, 0xbf, 0xbd);
17742 continue;
17743 } else if (i + 1 === length) {
17744 // unpaired lead
17745 if ((units -= 3) > -1) bytes.push(0xef, 0xbf, 0xbd);
17746 continue;
17747 }
17748
17749 // valid lead
17750 leadSurrogate = codePoint;
17751
17752 continue;
17753 }
17754
17755 // 2 leads in a row
17756 if (codePoint < 0xdc00) {
17757 if ((units -= 3) > -1) bytes.push(0xef, 0xbf, 0xbd);
17758 leadSurrogate = codePoint;
17759 continue;
17760 }
17761
17762 // valid surrogate pair
17763 codePoint =
17764 (((leadSurrogate - 0xd800) << 10) | (codePoint - 0xdc00)) + 0x10000;
17765 } else if (leadSurrogate) {
17766 // valid bmp char, but last char was a lead
17767 if ((units -= 3) > -1) bytes.push(0xef, 0xbf, 0xbd);
17768 }
17769
17770 leadSurrogate = null;
17771
17772 // encode utf8
17773 if (codePoint < 0x80) {
17774 if ((units -= 1) < 0) break;
17775 bytes.push(codePoint);
17776 } else if (codePoint < 0x800) {
17777 if ((units -= 2) < 0) break;
17778 bytes.push((codePoint >> 0x6) | 0xc0, (codePoint & 0x3f) | 0x80);
17779 } else if (codePoint < 0x10000) {
17780 if ((units -= 3) < 0) break;
17781 bytes.push(
17782 (codePoint >> 0xc) | 0xe0,
17783 ((codePoint >> 0x6) & 0x3f) | 0x80,
17784 (codePoint & 0x3f) | 0x80
17785 );
17786 } else if (codePoint < 0x110000) {
17787 if ((units -= 4) < 0) break;
17788 bytes.push(
17789 (codePoint >> 0x12) | 0xf0,
17790 ((codePoint >> 0xc) & 0x3f) | 0x80,
17791 ((codePoint >> 0x6) & 0x3f) | 0x80,
17792 (codePoint & 0x3f) | 0x80
17793 );
17794 } else {
17795 throw new Error('Invalid code point');
17796 }
17797 }
17798
17799 return bytes;
17800 }
17801
17802 function asciiToBytes(str) {
17803 var byteArray = [];
17804 for (var i = 0; i < str.length; ++i) {
17805 // Node's code seems to be doing this and not & 0x7F..
17806 byteArray.push(str.charCodeAt(i) & 0xff);
17807 }
17808 return byteArray;
17809 }
17810
17811 function utf16leToBytes(str, units) {
17812 var c, hi, lo;
17813 var byteArray = [];
17814 for (var i = 0; i < str.length; ++i) {
17815 if ((units -= 2) < 0) break;
17816
17817 c = str.charCodeAt(i);
17818 hi = c >> 8;
17819 lo = c % 256;
17820 byteArray.push(lo);
17821 byteArray.push(hi);
17822 }
17823
17824 return byteArray;
17825 }
17826
17827 function base64ToBytes(str) {
17828 return base64.toByteArray(base64clean(str));
17829 }
17830
17831 function blitBuffer(src, dst, offset, length) {
17832 for (var i = 0; i < length; ++i) {
17833 if (i + offset >= dst.length || i >= src.length) break;
17834 dst[i + offset] = src[i];
17835 }
17836 return i;
17837 }
17838
17839 // ArrayBuffer or Uint8Array objects from other contexts (i.e. iframes) do not pass
17840 // the `instanceof` check but they should be treated as of that type.
17841 // See: https://github.com/feross/buffer/issues/166
17842 function isInstance(obj, type) {
17843 return (
17844 obj instanceof type ||
17845 (obj != null &&
17846 obj.constructor != null &&
17847 obj.constructor.name != null &&
17848 obj.constructor.name === type.name)
17849 );
17850 }
17851 function numberIsNaN(obj) {
17852 // For IE11 support
17853 return obj !== obj; // eslint-disable-line no-self-compare
17854 }
17855
17856 // Create lookup table for `toString('hex')`
17857 // See: https://github.com/feross/buffer/issues/219
17858 var hexSliceLookupTable = (function() {
17859 var alphabet = '0123456789abcdef';
17860 var table = new Array(256);
17861 for (var i = 0; i < 16; ++i) {
17862 var i16 = i * 16;
17863 for (var j = 0; j < 16; ++j) {
17864 table[i16 + j] = alphabet[i] + alphabet[j];
17865 }
17866 }
17867 return table;
17868 })();
17869 }.call(this, _dereq_('buffer').Buffer));
17870 },
17871 { 'base64-js': 20, buffer: 22, ieee754: 31 }
17872 ],
17873 23: [
17874 function(_dereq_, module, exports) {
17875 // This file can be required in Browserify and Node.js for automatic polyfill
17876 // To use it: require('es6-promise/auto');
17877 'use strict';
17878 module.exports = _dereq_('./').polyfill();
17879 },
17880 { './': 24 }
17881 ],
17882 24: [
17883 function(_dereq_, module, exports) {
17884 (function(process, global) {
17885 /*!
17886 * @overview es6-promise - a tiny implementation of Promises/A+.
17887 * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald)
17888 * @license Licensed under MIT license
17889 * See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE
17890 * @version v4.2.8+1e68dce6
17891 */
17892
17893 (function(global, factory) {
17894 typeof exports === 'object' && typeof module !== 'undefined'
17895 ? (module.exports = factory())
17896 : typeof define === 'function' && define.amd
17897 ? define(factory)
17898 : (global.ES6Promise = factory());
17899 })(this, function() {
17900 'use strict';
17901
17902 function objectOrFunction(x) {
17903 var type = typeof x;
17904 return x !== null && (type === 'object' || type === 'function');
17905 }
17906
17907 function isFunction(x) {
17908 return typeof x === 'function';
17909 }
17910
17911 var _isArray = void 0;
17912 if (Array.isArray) {
17913 _isArray = Array.isArray;
17914 } else {
17915 _isArray = function(x) {
17916 return Object.prototype.toString.call(x) === '[object Array]';
17917 };
17918 }
17919
17920 var isArray = _isArray;
17921
17922 var len = 0;
17923 var vertxNext = void 0;
17924 var customSchedulerFn = void 0;
17925
17926 var asap = function asap(callback, arg) {
17927 queue[len] = callback;
17928 queue[len + 1] = arg;
17929 len += 2;
17930 if (len === 2) {
17931 // If len is 2, that means that we need to schedule an async flush.
17932 // If additional callbacks are queued before the queue is flushed, they
17933 // will be processed by this flush that we are scheduling.
17934 if (customSchedulerFn) {
17935 customSchedulerFn(flush);
17936 } else {
17937 scheduleFlush();
17938 }
17939 }
17940 };
17941
17942 function setScheduler(scheduleFn) {
17943 customSchedulerFn = scheduleFn;
17944 }
17945
17946 function setAsap(asapFn) {
17947 asap = asapFn;
17948 }
17949
17950 var browserWindow = typeof window !== 'undefined' ? window : undefined;
17951 var browserGlobal = browserWindow || {};
17952 var BrowserMutationObserver =
17953 browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
17954 var isNode =
17955 typeof self === 'undefined' &&
17956 typeof process !== 'undefined' &&
17957 {}.toString.call(process) === '[object process]';
17958
17959 // test for web worker but not in IE10
17960 var isWorker =
17961 typeof Uint8ClampedArray !== 'undefined' &&
17962 typeof importScripts !== 'undefined' &&
17963 typeof MessageChannel !== 'undefined';
17964
17965 // node
17966 function useNextTick() {
17967 // node version 0.10.x displays a deprecation warning when nextTick is used recursively
17968 // see https://github.com/cujojs/when/issues/410 for details
17969 return function() {
17970 return process.nextTick(flush);
17971 };
17972 }
17973
17974 // vertx
17975 function useVertxTimer() {
17976 if (typeof vertxNext !== 'undefined') {
17977 return function() {
17978 vertxNext(flush);
17979 };
17980 }
17981
17982 return useSetTimeout();
17983 }
17984
17985 function useMutationObserver() {
17986 var iterations = 0;
17987 var observer = new BrowserMutationObserver(flush);
17988 var node = document.createTextNode('');
17989 observer.observe(node, { characterData: true });
17990
17991 return function() {
17992 node.data = iterations = ++iterations % 2;
17993 };
17994 }
17995
17996 // web worker
17997 function useMessageChannel() {
17998 var channel = new MessageChannel();
17999 channel.port1.onmessage = flush;
18000 return function() {
18001 return channel.port2.postMessage(0);
18002 };
18003 }
18004
18005 function useSetTimeout() {
18006 // Store setTimeout reference so es6-promise will be unaffected by
18007 // other code modifying setTimeout (like sinon.useFakeTimers())
18008 var globalSetTimeout = setTimeout;
18009 return function() {
18010 return globalSetTimeout(flush, 1);
18011 };
18012 }
18013
18014 var queue = new Array(1000);
18015 function flush() {
18016 for (var i = 0; i < len; i += 2) {
18017 var callback = queue[i];
18018 var arg = queue[i + 1];
18019
18020 callback(arg);
18021
18022 queue[i] = undefined;
18023 queue[i + 1] = undefined;
18024 }
18025
18026 len = 0;
18027 }
18028
18029 function attemptVertx() {
18030 try {
18031 var vertx = Function('return this')().require('vertx');
18032 vertxNext = vertx.runOnLoop || vertx.runOnContext;
18033 return useVertxTimer();
18034 } catch (e) {
18035 return useSetTimeout();
18036 }
18037 }
18038
18039 var scheduleFlush = void 0;
18040 // Decide what async method to use to triggering processing of queued callbacks:
18041 if (isNode) {
18042 scheduleFlush = useNextTick();
18043 } else if (BrowserMutationObserver) {
18044 scheduleFlush = useMutationObserver();
18045 } else if (isWorker) {
18046 scheduleFlush = useMessageChannel();
18047 } else if (browserWindow === undefined && typeof _dereq_ === 'function') {
18048 scheduleFlush = attemptVertx();
18049 } else {
18050 scheduleFlush = useSetTimeout();
18051 }
18052
18053 function then(onFulfillment, onRejection) {
18054 var parent = this;
18055
18056 var child = new this.constructor(noop);
18057
18058 if (child[PROMISE_ID] === undefined) {
18059 makePromise(child);
18060 }
18061
18062 var _state = parent._state;
18063
18064 if (_state) {
18065 var callback = arguments[_state - 1];
18066 asap(function() {
18067 return invokeCallback(_state, child, callback, parent._result);
18068 });
18069 } else {
18070 subscribe(parent, child, onFulfillment, onRejection);
18071 }
18072
18073 return child;
18074 }
18075
18076 /**
18077 `Promise.resolve` returns a promise that will become resolved with the
18078 passed `value`. It is shorthand for the following:
18079
18080 ```javascript
18081 let promise = new Promise(function(resolve, reject){
18082 resolve(1);
18083 });
18084
18085 promise.then(function(value){
18086 // value === 1
18087 });
18088 ```
18089
18090 Instead of writing the above, your code now simply becomes the following:
18091
18092 ```javascript
18093 let promise = Promise.resolve(1);
18094
18095 promise.then(function(value){
18096 // value === 1
18097 });
18098 ```
18099
18100 @method resolve
18101 @static
18102 @param {Any} value value that the returned promise will be resolved with
18103 Useful for tooling.
18104 @return {Promise} a promise that will become fulfilled with the given
18105 `value`
18106*/
18107 function resolve$1(object) {
18108 /*jshint validthis:true */
18109 var Constructor = this;
18110
18111 if (
18112 object &&
18113 typeof object === 'object' &&
18114 object.constructor === Constructor
18115 ) {
18116 return object;
18117 }
18118
18119 var promise = new Constructor(noop);
18120 resolve(promise, object);
18121 return promise;
18122 }
18123
18124 var PROMISE_ID = Math.random()
18125 .toString(36)
18126 .substring(2);
18127
18128 function noop() {}
18129
18130 var PENDING = void 0;
18131 var FULFILLED = 1;
18132 var REJECTED = 2;
18133
18134 function selfFulfillment() {
18135 return new TypeError('You cannot resolve a promise with itself');
18136 }
18137
18138 function cannotReturnOwn() {
18139 return new TypeError(
18140 'A promises callback cannot return that same promise.'
18141 );
18142 }
18143
18144 function tryThen(then$$1, value, fulfillmentHandler, rejectionHandler) {
18145 try {
18146 then$$1.call(value, fulfillmentHandler, rejectionHandler);
18147 } catch (e) {
18148 return e;
18149 }
18150 }
18151
18152 function handleForeignThenable(promise, thenable, then$$1) {
18153 asap(function(promise) {
18154 var sealed = false;
18155 var error = tryThen(
18156 then$$1,
18157 thenable,
18158 function(value) {
18159 if (sealed) {
18160 return;
18161 }
18162 sealed = true;
18163 if (thenable !== value) {
18164 resolve(promise, value);
18165 } else {
18166 fulfill(promise, value);
18167 }
18168 },
18169 function(reason) {
18170 if (sealed) {
18171 return;
18172 }
18173 sealed = true;
18174
18175 reject(promise, reason);
18176 },
18177 'Settle: ' + (promise._label || ' unknown promise')
18178 );
18179
18180 if (!sealed && error) {
18181 sealed = true;
18182 reject(promise, error);
18183 }
18184 }, promise);
18185 }
18186
18187 function handleOwnThenable(promise, thenable) {
18188 if (thenable._state === FULFILLED) {
18189 fulfill(promise, thenable._result);
18190 } else if (thenable._state === REJECTED) {
18191 reject(promise, thenable._result);
18192 } else {
18193 subscribe(
18194 thenable,
18195 undefined,
18196 function(value) {
18197 return resolve(promise, value);
18198 },
18199 function(reason) {
18200 return reject(promise, reason);
18201 }
18202 );
18203 }
18204 }
18205
18206 function handleMaybeThenable(promise, maybeThenable, then$$1) {
18207 if (
18208 maybeThenable.constructor === promise.constructor &&
18209 then$$1 === then &&
18210 maybeThenable.constructor.resolve === resolve$1
18211 ) {
18212 handleOwnThenable(promise, maybeThenable);
18213 } else {
18214 if (then$$1 === undefined) {
18215 fulfill(promise, maybeThenable);
18216 } else if (isFunction(then$$1)) {
18217 handleForeignThenable(promise, maybeThenable, then$$1);
18218 } else {
18219 fulfill(promise, maybeThenable);
18220 }
18221 }
18222 }
18223
18224 function resolve(promise, value) {
18225 if (promise === value) {
18226 reject(promise, selfFulfillment());
18227 } else if (objectOrFunction(value)) {
18228 var then$$1 = void 0;
18229 try {
18230 then$$1 = value.then;
18231 } catch (error) {
18232 reject(promise, error);
18233 return;
18234 }
18235 handleMaybeThenable(promise, value, then$$1);
18236 } else {
18237 fulfill(promise, value);
18238 }
18239 }
18240
18241 function publishRejection(promise) {
18242 if (promise._onerror) {
18243 promise._onerror(promise._result);
18244 }
18245
18246 publish(promise);
18247 }
18248
18249 function fulfill(promise, value) {
18250 if (promise._state !== PENDING) {
18251 return;
18252 }
18253
18254 promise._result = value;
18255 promise._state = FULFILLED;
18256
18257 if (promise._subscribers.length !== 0) {
18258 asap(publish, promise);
18259 }
18260 }
18261
18262 function reject(promise, reason) {
18263 if (promise._state !== PENDING) {
18264 return;
18265 }
18266 promise._state = REJECTED;
18267 promise._result = reason;
18268
18269 asap(publishRejection, promise);
18270 }
18271
18272 function subscribe(parent, child, onFulfillment, onRejection) {
18273 var _subscribers = parent._subscribers;
18274 var length = _subscribers.length;
18275
18276 parent._onerror = null;
18277
18278 _subscribers[length] = child;
18279 _subscribers[length + FULFILLED] = onFulfillment;
18280 _subscribers[length + REJECTED] = onRejection;
18281
18282 if (length === 0 && parent._state) {
18283 asap(publish, parent);
18284 }
18285 }
18286
18287 function publish(promise) {
18288 var subscribers = promise._subscribers;
18289 var settled = promise._state;
18290
18291 if (subscribers.length === 0) {
18292 return;
18293 }
18294
18295 var child = void 0,
18296 callback = void 0,
18297 detail = promise._result;
18298
18299 for (var i = 0; i < subscribers.length; i += 3) {
18300 child = subscribers[i];
18301 callback = subscribers[i + settled];
18302
18303 if (child) {
18304 invokeCallback(settled, child, callback, detail);
18305 } else {
18306 callback(detail);
18307 }
18308 }
18309
18310 promise._subscribers.length = 0;
18311 }
18312
18313 function invokeCallback(settled, promise, callback, detail) {
18314 var hasCallback = isFunction(callback),
18315 value = void 0,
18316 error = void 0,
18317 succeeded = true;
18318
18319 if (hasCallback) {
18320 try {
18321 value = callback(detail);
18322 } catch (e) {
18323 succeeded = false;
18324 error = e;
18325 }
18326
18327 if (promise === value) {
18328 reject(promise, cannotReturnOwn());
18329 return;
18330 }
18331 } else {
18332 value = detail;
18333 }
18334
18335 if (promise._state !== PENDING) {
18336 // noop
18337 } else if (hasCallback && succeeded) {
18338 resolve(promise, value);
18339 } else if (succeeded === false) {
18340 reject(promise, error);
18341 } else if (settled === FULFILLED) {
18342 fulfill(promise, value);
18343 } else if (settled === REJECTED) {
18344 reject(promise, value);
18345 }
18346 }
18347
18348 function initializePromise(promise, resolver) {
18349 try {
18350 resolver(
18351 function resolvePromise(value) {
18352 resolve(promise, value);
18353 },
18354 function rejectPromise(reason) {
18355 reject(promise, reason);
18356 }
18357 );
18358 } catch (e) {
18359 reject(promise, e);
18360 }
18361 }
18362
18363 var id = 0;
18364 function nextId() {
18365 return id++;
18366 }
18367
18368 function makePromise(promise) {
18369 promise[PROMISE_ID] = id++;
18370 promise._state = undefined;
18371 promise._result = undefined;
18372 promise._subscribers = [];
18373 }
18374
18375 function validationError() {
18376 return new Error('Array Methods must be provided an Array');
18377 }
18378
18379 var Enumerator = (function() {
18380 function Enumerator(Constructor, input) {
18381 this._instanceConstructor = Constructor;
18382 this.promise = new Constructor(noop);
18383
18384 if (!this.promise[PROMISE_ID]) {
18385 makePromise(this.promise);
18386 }
18387
18388 if (isArray(input)) {
18389 this.length = input.length;
18390 this._remaining = input.length;
18391
18392 this._result = new Array(this.length);
18393
18394 if (this.length === 0) {
18395 fulfill(this.promise, this._result);
18396 } else {
18397 this.length = this.length || 0;
18398 this._enumerate(input);
18399 if (this._remaining === 0) {
18400 fulfill(this.promise, this._result);
18401 }
18402 }
18403 } else {
18404 reject(this.promise, validationError());
18405 }
18406 }
18407
18408 Enumerator.prototype._enumerate = function _enumerate(input) {
18409 for (var i = 0; this._state === PENDING && i < input.length; i++) {
18410 this._eachEntry(input[i], i);
18411 }
18412 };
18413
18414 Enumerator.prototype._eachEntry = function _eachEntry(entry, i) {
18415 var c = this._instanceConstructor;
18416 var resolve$$1 = c.resolve;
18417
18418 if (resolve$$1 === resolve$1) {
18419 var _then = void 0;
18420 var error = void 0;
18421 var didError = false;
18422 try {
18423 _then = entry.then;
18424 } catch (e) {
18425 didError = true;
18426 error = e;
18427 }
18428
18429 if (_then === then && entry._state !== PENDING) {
18430 this._settledAt(entry._state, i, entry._result);
18431 } else if (typeof _then !== 'function') {
18432 this._remaining--;
18433 this._result[i] = entry;
18434 } else if (c === Promise$1) {
18435 var promise = new c(noop);
18436 if (didError) {
18437 reject(promise, error);
18438 } else {
18439 handleMaybeThenable(promise, entry, _then);
18440 }
18441 this._willSettleAt(promise, i);
18442 } else {
18443 this._willSettleAt(
18444 new c(function(resolve$$1) {
18445 return resolve$$1(entry);
18446 }),
18447 i
18448 );
18449 }
18450 } else {
18451 this._willSettleAt(resolve$$1(entry), i);
18452 }
18453 };
18454
18455 Enumerator.prototype._settledAt = function _settledAt(state, i, value) {
18456 var promise = this.promise;
18457
18458 if (promise._state === PENDING) {
18459 this._remaining--;
18460
18461 if (state === REJECTED) {
18462 reject(promise, value);
18463 } else {
18464 this._result[i] = value;
18465 }
18466 }
18467
18468 if (this._remaining === 0) {
18469 fulfill(promise, this._result);
18470 }
18471 };
18472
18473 Enumerator.prototype._willSettleAt = function _willSettleAt(promise, i) {
18474 var enumerator = this;
18475
18476 subscribe(
18477 promise,
18478 undefined,
18479 function(value) {
18480 return enumerator._settledAt(FULFILLED, i, value);
18481 },
18482 function(reason) {
18483 return enumerator._settledAt(REJECTED, i, reason);
18484 }
18485 );
18486 };
18487
18488 return Enumerator;
18489 })();
18490
18491 /**
18492 `Promise.all` accepts an array of promises, and returns a new promise which
18493 is fulfilled with an array of fulfillment values for the passed promises, or
18494 rejected with the reason of the first passed promise to be rejected. It casts all
18495 elements of the passed iterable to promises as it runs this algorithm.
18496
18497 Example:
18498
18499 ```javascript
18500 let promise1 = resolve(1);
18501 let promise2 = resolve(2);
18502 let promise3 = resolve(3);
18503 let promises = [ promise1, promise2, promise3 ];
18504
18505 Promise.all(promises).then(function(array){
18506 // The array here would be [ 1, 2, 3 ];
18507 });
18508 ```
18509
18510 If any of the `promises` given to `all` are rejected, the first promise
18511 that is rejected will be given as an argument to the returned promises's
18512 rejection handler. For example:
18513
18514 Example:
18515
18516 ```javascript
18517 let promise1 = resolve(1);
18518 let promise2 = reject(new Error("2"));
18519 let promise3 = reject(new Error("3"));
18520 let promises = [ promise1, promise2, promise3 ];
18521
18522 Promise.all(promises).then(function(array){
18523 // Code here never runs because there are rejected promises!
18524 }, function(error) {
18525 // error.message === "2"
18526 });
18527 ```
18528
18529 @method all
18530 @static
18531 @param {Array} entries array of promises
18532 @param {String} label optional string for labeling the promise.
18533 Useful for tooling.
18534 @return {Promise} promise that is fulfilled when all `promises` have been
18535 fulfilled, or rejected if any of them become rejected.
18536 @static
18537*/
18538 function all(entries) {
18539 return new Enumerator(this, entries).promise;
18540 }
18541
18542 /**
18543 `Promise.race` returns a new promise which is settled in the same way as the
18544 first passed promise to settle.
18545
18546 Example:
18547
18548 ```javascript
18549 let promise1 = new Promise(function(resolve, reject){
18550 setTimeout(function(){
18551 resolve('promise 1');
18552 }, 200);
18553 });
18554
18555 let promise2 = new Promise(function(resolve, reject){
18556 setTimeout(function(){
18557 resolve('promise 2');
18558 }, 100);
18559 });
18560
18561 Promise.race([promise1, promise2]).then(function(result){
18562 // result === 'promise 2' because it was resolved before promise1
18563 // was resolved.
18564 });
18565 ```
18566
18567 `Promise.race` is deterministic in that only the state of the first
18568 settled promise matters. For example, even if other promises given to the
18569 `promises` array argument are resolved, but the first settled promise has
18570 become rejected before the other promises became fulfilled, the returned
18571 promise will become rejected:
18572
18573 ```javascript
18574 let promise1 = new Promise(function(resolve, reject){
18575 setTimeout(function(){
18576 resolve('promise 1');
18577 }, 200);
18578 });
18579
18580 let promise2 = new Promise(function(resolve, reject){
18581 setTimeout(function(){
18582 reject(new Error('promise 2'));
18583 }, 100);
18584 });
18585
18586 Promise.race([promise1, promise2]).then(function(result){
18587 // Code here never runs
18588 }, function(reason){
18589 // reason.message === 'promise 2' because promise 2 became rejected before
18590 // promise 1 became fulfilled
18591 });
18592 ```
18593
18594 An example real-world use case is implementing timeouts:
18595
18596 ```javascript
18597 Promise.race([ajax('foo.json'), timeout(5000)])
18598 ```
18599
18600 @method race
18601 @static
18602 @param {Array} promises array of promises to observe
18603 Useful for tooling.
18604 @return {Promise} a promise which settles in the same way as the first passed
18605 promise to settle.
18606*/
18607 function race(entries) {
18608 /*jshint validthis:true */
18609 var Constructor = this;
18610
18611 if (!isArray(entries)) {
18612 return new Constructor(function(_, reject) {
18613 return reject(new TypeError('You must pass an array to race.'));
18614 });
18615 } else {
18616 return new Constructor(function(resolve, reject) {
18617 var length = entries.length;
18618 for (var i = 0; i < length; i++) {
18619 Constructor.resolve(entries[i]).then(resolve, reject);
18620 }
18621 });
18622 }
18623 }
18624
18625 /**
18626 `Promise.reject` returns a promise rejected with the passed `reason`.
18627 It is shorthand for the following:
18628
18629 ```javascript
18630 let promise = new Promise(function(resolve, reject){
18631 reject(new Error('WHOOPS'));
18632 });
18633
18634 promise.then(function(value){
18635 // Code here doesn't run because the promise is rejected!
18636 }, function(reason){
18637 // reason.message === 'WHOOPS'
18638 });
18639 ```
18640
18641 Instead of writing the above, your code now simply becomes the following:
18642
18643 ```javascript
18644 let promise = Promise.reject(new Error('WHOOPS'));
18645
18646 promise.then(function(value){
18647 // Code here doesn't run because the promise is rejected!
18648 }, function(reason){
18649 // reason.message === 'WHOOPS'
18650 });
18651 ```
18652
18653 @method reject
18654 @static
18655 @param {Any} reason value that the returned promise will be rejected with.
18656 Useful for tooling.
18657 @return {Promise} a promise rejected with the given `reason`.
18658*/
18659 function reject$1(reason) {
18660 /*jshint validthis:true */
18661 var Constructor = this;
18662 var promise = new Constructor(noop);
18663 reject(promise, reason);
18664 return promise;
18665 }
18666
18667 function needsResolver() {
18668 throw new TypeError(
18669 'You must pass a resolver function as the first argument to the promise constructor'
18670 );
18671 }
18672
18673 function needsNew() {
18674 throw new TypeError(
18675 "Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function."
18676 );
18677 }
18678
18679 /**
18680 Promise objects represent the eventual result of an asynchronous operation. The
18681 primary way of interacting with a promise is through its `then` method, which
18682 registers callbacks to receive either a promise's eventual value or the reason
18683 why the promise cannot be fulfilled.
18684
18685 Terminology
18686 -----------
18687
18688 - `promise` is an object or function with a `then` method whose behavior conforms to this specification.
18689 - `thenable` is an object or function that defines a `then` method.
18690 - `value` is any legal JavaScript value (including undefined, a thenable, or a promise).
18691 - `exception` is a value that is thrown using the throw statement.
18692 - `reason` is a value that indicates why a promise was rejected.
18693 - `settled` the final resting state of a promise, fulfilled or rejected.
18694
18695 A promise can be in one of three states: pending, fulfilled, or rejected.
18696
18697 Promises that are fulfilled have a fulfillment value and are in the fulfilled
18698 state. Promises that are rejected have a rejection reason and are in the
18699 rejected state. A fulfillment value is never a thenable.
18700
18701 Promises can also be said to *resolve* a value. If this value is also a
18702 promise, then the original promise's settled state will match the value's
18703 settled state. So a promise that *resolves* a promise that rejects will
18704 itself reject, and a promise that *resolves* a promise that fulfills will
18705 itself fulfill.
18706
18707
18708 Basic Usage:
18709 ------------
18710
18711 ```js
18712 let promise = new Promise(function(resolve, reject) {
18713 // on success
18714 resolve(value);
18715
18716 // on failure
18717 reject(reason);
18718 });
18719
18720 promise.then(function(value) {
18721 // on fulfillment
18722 }, function(reason) {
18723 // on rejection
18724 });
18725 ```
18726
18727 Advanced Usage:
18728 ---------------
18729
18730 Promises shine when abstracting away asynchronous interactions such as
18731 `XMLHttpRequest`s.
18732
18733 ```js
18734 function getJSON(url) {
18735 return new Promise(function(resolve, reject){
18736 let xhr = new XMLHttpRequest();
18737
18738 xhr.open('GET', url);
18739 xhr.onreadystatechange = handler;
18740 xhr.responseType = 'json';
18741 xhr.setRequestHeader('Accept', 'application/json');
18742 xhr.send();
18743
18744 function handler() {
18745 if (this.readyState === this.DONE) {
18746 if (this.status === 200) {
18747 resolve(this.response);
18748 } else {
18749 reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']'));
18750 }
18751 }
18752 };
18753 });
18754 }
18755
18756 getJSON('/posts.json').then(function(json) {
18757 // on fulfillment
18758 }, function(reason) {
18759 // on rejection
18760 });
18761 ```
18762
18763 Unlike callbacks, promises are great composable primitives.
18764
18765 ```js
18766 Promise.all([
18767 getJSON('/posts'),
18768 getJSON('/comments')
18769 ]).then(function(values){
18770 values[0] // => postsJSON
18771 values[1] // => commentsJSON
18772
18773 return values;
18774 });
18775 ```
18776
18777 @class Promise
18778 @param {Function} resolver
18779 Useful for tooling.
18780 @constructor
18781*/
18782
18783 var Promise$1 = (function() {
18784 function Promise(resolver) {
18785 this[PROMISE_ID] = nextId();
18786 this._result = this._state = undefined;
18787 this._subscribers = [];
18788
18789 if (noop !== resolver) {
18790 typeof resolver !== 'function' && needsResolver();
18791 this instanceof Promise
18792 ? initializePromise(this, resolver)
18793 : needsNew();
18794 }
18795 }
18796
18797 /**
18798 The primary way of interacting with a promise is through its `then` method,
18799 which registers callbacks to receive either a promise's eventual value or the
18800 reason why the promise cannot be fulfilled.
18801 ```js
18802 findUser().then(function(user){
18803 // user is available
18804 }, function(reason){
18805 // user is unavailable, and you are given the reason why
18806 });
18807 ```
18808 Chaining
18809 --------
18810 The return value of `then` is itself a promise. This second, 'downstream'
18811 promise is resolved with the return value of the first promise's fulfillment
18812 or rejection handler, or rejected if the handler throws an exception.
18813 ```js
18814 findUser().then(function (user) {
18815 return user.name;
18816 }, function (reason) {
18817 return 'default name';
18818 }).then(function (userName) {
18819 // If `findUser` fulfilled, `userName` will be the user's name, otherwise it
18820 // will be `'default name'`
18821 });
18822 findUser().then(function (user) {
18823 throw new Error('Found user, but still unhappy');
18824 }, function (reason) {
18825 throw new Error('`findUser` rejected and we're unhappy');
18826 }).then(function (value) {
18827 // never reached
18828 }, function (reason) {
18829 // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'.
18830 // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'.
18831 });
18832 ```
18833 If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream.
18834 ```js
18835 findUser().then(function (user) {
18836 throw new PedagogicalException('Upstream error');
18837 }).then(function (value) {
18838 // never reached
18839 }).then(function (value) {
18840 // never reached
18841 }, function (reason) {
18842 // The `PedgagocialException` is propagated all the way down to here
18843 });
18844 ```
18845 Assimilation
18846 ------------
18847 Sometimes the value you want to propagate to a downstream promise can only be
18848 retrieved asynchronously. This can be achieved by returning a promise in the
18849 fulfillment or rejection handler. The downstream promise will then be pending
18850 until the returned promise is settled. This is called *assimilation*.
18851 ```js
18852 findUser().then(function (user) {
18853 return findCommentsByAuthor(user);
18854 }).then(function (comments) {
18855 // The user's comments are now available
18856 });
18857 ```
18858 If the assimliated promise rejects, then the downstream promise will also reject.
18859 ```js
18860 findUser().then(function (user) {
18861 return findCommentsByAuthor(user);
18862 }).then(function (comments) {
18863 // If `findCommentsByAuthor` fulfills, we'll have the value here
18864 }, function (reason) {
18865 // If `findCommentsByAuthor` rejects, we'll have the reason here
18866 });
18867 ```
18868 Simple Example
18869 --------------
18870 Synchronous Example
18871 ```javascript
18872 let result;
18873 try {
18874 result = findResult();
18875 // success
18876 } catch(reason) {
18877 // failure
18878 }
18879 ```
18880 Errback Example
18881 ```js
18882 findResult(function(result, err){
18883 if (err) {
18884 // failure
18885 } else {
18886 // success
18887 }
18888 });
18889 ```
18890 Promise Example;
18891 ```javascript
18892 findResult().then(function(result){
18893 // success
18894 }, function(reason){
18895 // failure
18896 });
18897 ```
18898 Advanced Example
18899 --------------
18900 Synchronous Example
18901 ```javascript
18902 let author, books;
18903 try {
18904 author = findAuthor();
18905 books = findBooksByAuthor(author);
18906 // success
18907 } catch(reason) {
18908 // failure
18909 }
18910 ```
18911 Errback Example
18912 ```js
18913 function foundBooks(books) {
18914 }
18915 function failure(reason) {
18916 }
18917 findAuthor(function(author, err){
18918 if (err) {
18919 failure(err);
18920 // failure
18921 } else {
18922 try {
18923 findBoooksByAuthor(author, function(books, err) {
18924 if (err) {
18925 failure(err);
18926 } else {
18927 try {
18928 foundBooks(books);
18929 } catch(reason) {
18930 failure(reason);
18931 }
18932 }
18933 });
18934 } catch(error) {
18935 failure(err);
18936 }
18937 // success
18938 }
18939 });
18940 ```
18941 Promise Example;
18942 ```javascript
18943 findAuthor().
18944 then(findBooksByAuthor).
18945 then(function(books){
18946 // found books
18947 }).catch(function(reason){
18948 // something went wrong
18949 });
18950 ```
18951 @method then
18952 @param {Function} onFulfilled
18953 @param {Function} onRejected
18954 Useful for tooling.
18955 @return {Promise}
18956 */
18957
18958 /**
18959 `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same
18960 as the catch block of a try/catch statement.
18961 ```js
18962 function findAuthor(){
18963 throw new Error('couldn't find that author');
18964 }
18965 // synchronous
18966 try {
18967 findAuthor();
18968 } catch(reason) {
18969 // something went wrong
18970 }
18971 // async with promises
18972 findAuthor().catch(function(reason){
18973 // something went wrong
18974 });
18975 ```
18976 @method catch
18977 @param {Function} onRejection
18978 Useful for tooling.
18979 @return {Promise}
18980 */
18981
18982 Promise.prototype.catch = function _catch(onRejection) {
18983 return this.then(null, onRejection);
18984 };
18985
18986 /**
18987 `finally` will be invoked regardless of the promise's fate just as native
18988 try/catch/finally behaves
18989
18990 Synchronous example:
18991
18992 ```js
18993 findAuthor() {
18994 if (Math.random() > 0.5) {
18995 throw new Error();
18996 }
18997 return new Author();
18998 }
18999
19000 try {
19001 return findAuthor(); // succeed or fail
19002 } catch(error) {
19003 return findOtherAuther();
19004 } finally {
19005 // always runs
19006 // doesn't affect the return value
19007 }
19008 ```
19009
19010 Asynchronous example:
19011
19012 ```js
19013 findAuthor().catch(function(reason){
19014 return findOtherAuther();
19015 }).finally(function(){
19016 // author was either found, or not
19017 });
19018 ```
19019
19020 @method finally
19021 @param {Function} callback
19022 @return {Promise}
19023 */
19024
19025 Promise.prototype.finally = function _finally(callback) {
19026 var promise = this;
19027 var constructor = promise.constructor;
19028
19029 if (isFunction(callback)) {
19030 return promise.then(
19031 function(value) {
19032 return constructor.resolve(callback()).then(function() {
19033 return value;
19034 });
19035 },
19036 function(reason) {
19037 return constructor.resolve(callback()).then(function() {
19038 throw reason;
19039 });
19040 }
19041 );
19042 }
19043
19044 return promise.then(callback, callback);
19045 };
19046
19047 return Promise;
19048 })();
19049
19050 Promise$1.prototype.then = then;
19051 Promise$1.all = all;
19052 Promise$1.race = race;
19053 Promise$1.resolve = resolve$1;
19054 Promise$1.reject = reject$1;
19055 Promise$1._setScheduler = setScheduler;
19056 Promise$1._setAsap = setAsap;
19057 Promise$1._asap = asap;
19058
19059 /*global self*/
19060 function polyfill() {
19061 var local = void 0;
19062
19063 if (typeof global !== 'undefined') {
19064 local = global;
19065 } else if (typeof self !== 'undefined') {
19066 local = self;
19067 } else {
19068 try {
19069 local = Function('return this')();
19070 } catch (e) {
19071 throw new Error(
19072 'polyfill failed because global object is unavailable in this environment'
19073 );
19074 }
19075 }
19076
19077 var P = local.Promise;
19078
19079 if (P) {
19080 var promiseToString = null;
19081 try {
19082 promiseToString = Object.prototype.toString.call(P.resolve());
19083 } catch (e) {
19084 // silently ignored
19085 }
19086
19087 if (promiseToString === '[object Promise]' && !P.cast) {
19088 return;
19089 }
19090 }
19091
19092 local.Promise = Promise$1;
19093 }
19094
19095 // Strange compat..
19096 Promise$1.polyfill = polyfill;
19097 Promise$1.Promise = Promise$1;
19098
19099 return Promise$1;
19100 });
19101 }.call(
19102 this,
19103 _dereq_('_process'),
19104 typeof global !== 'undefined'
19105 ? global
19106 : typeof self !== 'undefined'
19107 ? self
19108 : typeof window !== 'undefined' ? window : {}
19109 ));
19110 },
19111 { _process: 36 }
19112 ],
19113 25: [
19114 function(_dereq_, module, exports) {
19115 (function(global, factory) {
19116 if (typeof define === 'function' && define.amd) {
19117 define(['exports', 'module'], factory);
19118 } else if (typeof exports !== 'undefined' && typeof module !== 'undefined') {
19119 factory(exports, module);
19120 } else {
19121 var mod = {
19122 exports: {}
19123 };
19124 factory(mod.exports, mod);
19125 global.fetchJsonp = mod.exports;
19126 }
19127 })(this, function(exports, module) {
19128 'use strict';
19129
19130 var defaultOptions = {
19131 timeout: 5000,
19132 jsonpCallback: 'callback',
19133 jsonpCallbackFunction: null
19134 };
19135
19136 function generateCallbackFunction() {
19137 return 'jsonp_' + Date.now() + '_' + Math.ceil(Math.random() * 100000);
19138 }
19139
19140 function clearFunction(functionName) {
19141 // IE8 throws an exception when you try to delete a property on window
19142 // http://stackoverflow.com/a/1824228/751089
19143 try {
19144 delete window[functionName];
19145 } catch (e) {
19146 window[functionName] = undefined;
19147 }
19148 }
19149
19150 function removeScript(scriptId) {
19151 var script = document.getElementById(scriptId);
19152 if (script) {
19153 document.getElementsByTagName('head')[0].removeChild(script);
19154 }
19155 }
19156
19157 function fetchJsonp(_url) {
19158 var options =
19159 arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
19160
19161 // to avoid param reassign
19162 var url = _url;
19163 var timeout = options.timeout || defaultOptions.timeout;
19164 var jsonpCallback = options.jsonpCallback || defaultOptions.jsonpCallback;
19165
19166 var timeoutId = undefined;
19167
19168 return new Promise(function(resolve, reject) {
19169 var callbackFunction =
19170 options.jsonpCallbackFunction || generateCallbackFunction();
19171 var scriptId = jsonpCallback + '_' + callbackFunction;
19172
19173 window[callbackFunction] = function(response) {
19174 resolve({
19175 ok: true,
19176 // keep consistent with fetch API
19177 json: function json() {
19178 return Promise.resolve(response);
19179 }
19180 });
19181
19182 if (timeoutId) clearTimeout(timeoutId);
19183
19184 removeScript(scriptId);
19185
19186 clearFunction(callbackFunction);
19187 };
19188
19189 // Check if the user set their own params, and if not add a ? to start a list of params
19190 url += url.indexOf('?') === -1 ? '?' : '&';
19191
19192 var jsonpScript = document.createElement('script');
19193 jsonpScript.setAttribute(
19194 'src',
19195 '' + url + jsonpCallback + '=' + callbackFunction
19196 );
19197 if (options.charset) {
19198 jsonpScript.setAttribute('charset', options.charset);
19199 }
19200 jsonpScript.id = scriptId;
19201 document.getElementsByTagName('head')[0].appendChild(jsonpScript);
19202
19203 timeoutId = setTimeout(function() {
19204 reject(new Error('JSONP request to ' + _url + ' timed out'));
19205
19206 clearFunction(callbackFunction);
19207 removeScript(scriptId);
19208 window[callbackFunction] = function() {
19209 clearFunction(callbackFunction);
19210 };
19211 }, timeout);
19212
19213 // Caught if got 404/500
19214 jsonpScript.onerror = function() {
19215 reject(new Error('JSONP request to ' + _url + ' failed'));
19216
19217 clearFunction(callbackFunction);
19218 removeScript(scriptId);
19219 if (timeoutId) clearTimeout(timeoutId);
19220 };
19221 });
19222 }
19223
19224 // export as global function
19225 /*
19226 let local;
19227 if (typeof global !== 'undefined') {
19228 local = global;
19229 } else if (typeof self !== 'undefined') {
19230 local = self;
19231 } else {
19232 try {
19233 local = Function('return this')();
19234 } catch (e) {
19235 throw new Error('polyfill failed because global object is unavailable in this environment');
19236 }
19237 }
19238 local.fetchJsonp = fetchJsonp;
19239 */
19240
19241 module.exports = fetchJsonp;
19242 });
19243 },
19244 {}
19245 ],
19246 26: [
19247 function(_dereq_, module, exports) {
19248 /* FileSaver.js
19249 * A saveAs() FileSaver implementation.
19250 * 1.3.2
19251 * 2016-06-16 18:25:19
19252 *
19253 * By Eli Grey, http://eligrey.com
19254 * License: MIT
19255 * See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md
19256 */
19257
19258 /*global self */
19259 /*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */
19260
19261 /*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */
19262
19263 var saveAs =
19264 saveAs ||
19265 (function(view) {
19266 'use strict';
19267 // IE <10 is explicitly unsupported
19268 if (
19269 typeof view === 'undefined' ||
19270 (typeof navigator !== 'undefined' &&
19271 /MSIE [1-9]\./.test(navigator.userAgent))
19272 ) {
19273 return;
19274 }
19275 var doc = view.document,
19276 // only get URL when necessary in case Blob.js hasn't overridden it yet
19277 get_URL = function() {
19278 return view.URL || view.webkitURL || view;
19279 },
19280 save_link = doc.createElementNS('http://www.w3.org/1999/xhtml', 'a'),
19281 can_use_save_link = 'download' in save_link,
19282 click = function(node) {
19283 var event = new MouseEvent('click');
19284 node.dispatchEvent(event);
19285 },
19286 is_safari = /constructor/i.test(view.HTMLElement) || view.safari,
19287 is_chrome_ios = /CriOS\/[\d]+/.test(navigator.userAgent),
19288 throw_outside = function(ex) {
19289 (view.setImmediate || view.setTimeout)(function() {
19290 throw ex;
19291 }, 0);
19292 },
19293 force_saveable_type = 'application/octet-stream',
19294 // the Blob API is fundamentally broken as there is no "downloadfinished" event to subscribe to
19295 arbitrary_revoke_timeout = 1000 * 40, // in ms
19296 revoke = function(file) {
19297 var revoker = function() {
19298 if (typeof file === 'string') {
19299 // file is an object URL
19300 get_URL().revokeObjectURL(file);
19301 } else {
19302 // file is a File
19303 file.remove();
19304 }
19305 };
19306 setTimeout(revoker, arbitrary_revoke_timeout);
19307 },
19308 dispatch = function(filesaver, event_types, event) {
19309 event_types = [].concat(event_types);
19310 var i = event_types.length;
19311 while (i--) {
19312 var listener = filesaver['on' + event_types[i]];
19313 if (typeof listener === 'function') {
19314 try {
19315 listener.call(filesaver, event || filesaver);
19316 } catch (ex) {
19317 throw_outside(ex);
19318 }
19319 }
19320 }
19321 },
19322 auto_bom = function(blob) {
19323 // prepend BOM for UTF-8 XML and text/* types (including HTML)
19324 // note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF
19325 if (
19326 /^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(
19327 blob.type
19328 )
19329 ) {
19330 return new Blob([String.fromCharCode(0xfeff), blob], {
19331 type: blob.type
19332 });
19333 }
19334 return blob;
19335 },
19336 FileSaver = function(blob, name, no_auto_bom) {
19337 if (!no_auto_bom) {
19338 blob = auto_bom(blob);
19339 }
19340 // First try a.download, then web filesystem, then object URLs
19341 var filesaver = this,
19342 type = blob.type,
19343 force = type === force_saveable_type,
19344 object_url,
19345 dispatch_all = function() {
19346 dispatch(filesaver, 'writestart progress write writeend'.split(' '));
19347 },
19348 // on any filesys errors revert to saving with object URLs
19349 fs_error = function() {
19350 if ((is_chrome_ios || (force && is_safari)) && view.FileReader) {
19351 // Safari doesn't allow downloading of blob urls
19352 var reader = new FileReader();
19353 reader.onloadend = function() {
19354 var url = is_chrome_ios
19355 ? reader.result
19356 : reader.result.replace(
19357 /^data:[^;]*;/,
19358 'data:attachment/file;'
19359 );
19360 var popup = view.open(url, '_blank');
19361 if (!popup) view.location.href = url;
19362 url = undefined; // release reference before dispatching
19363 filesaver.readyState = filesaver.DONE;
19364 dispatch_all();
19365 };
19366 reader.readAsDataURL(blob);
19367 filesaver.readyState = filesaver.INIT;
19368 return;
19369 }
19370 // don't create more object URLs than needed
19371 if (!object_url) {
19372 object_url = get_URL().createObjectURL(blob);
19373 }
19374 if (force) {
19375 view.location.href = object_url;
19376 } else {
19377 var opened = view.open(object_url, '_blank');
19378 if (!opened) {
19379 // Apple does not allow window.open, see https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/WorkingwithWindowsandTabs/WorkingwithWindowsandTabs.html
19380 view.location.href = object_url;
19381 }
19382 }
19383 filesaver.readyState = filesaver.DONE;
19384 dispatch_all();
19385 revoke(object_url);
19386 };
19387 filesaver.readyState = filesaver.INIT;
19388
19389 if (can_use_save_link) {
19390 object_url = get_URL().createObjectURL(blob);
19391 setTimeout(function() {
19392 save_link.href = object_url;
19393 save_link.download = name;
19394 click(save_link);
19395 dispatch_all();
19396 revoke(object_url);
19397 filesaver.readyState = filesaver.DONE;
19398 });
19399 return;
19400 }
19401
19402 fs_error();
19403 },
19404 FS_proto = FileSaver.prototype,
19405 saveAs = function(blob, name, no_auto_bom) {
19406 return new FileSaver(blob, name || blob.name || 'download', no_auto_bom);
19407 };
19408 // IE 10+ (native saveAs)
19409 if (typeof navigator !== 'undefined' && navigator.msSaveOrOpenBlob) {
19410 return function(blob, name, no_auto_bom) {
19411 name = name || blob.name || 'download';
19412
19413 if (!no_auto_bom) {
19414 blob = auto_bom(blob);
19415 }
19416 return navigator.msSaveOrOpenBlob(blob, name);
19417 };
19418 }
19419
19420 FS_proto.abort = function() {};
19421 FS_proto.readyState = FS_proto.INIT = 0;
19422 FS_proto.WRITING = 1;
19423 FS_proto.DONE = 2;
19424
19425 FS_proto.error = FS_proto.onwritestart = FS_proto.onprogress = FS_proto.onwrite = FS_proto.onabort = FS_proto.onerror = FS_proto.onwriteend = null;
19426
19427 return saveAs;
19428 })(
19429 (typeof self !== 'undefined' && self) ||
19430 (typeof window !== 'undefined' && window) ||
19431 this.content
19432 );
19433 // `self` is undefined in Firefox for Android content script context
19434 // while `this` is nsIContentFrameMessageManager
19435 // with an attribute `content` that corresponds to the window
19436
19437 if (typeof module !== 'undefined' && module.exports) {
19438 module.exports.saveAs = saveAs;
19439 } else if (
19440 typeof define !== 'undefined' &&
19441 define !== null &&
19442 define.amd !== null
19443 ) {
19444 define('FileSaver.js', function() {
19445 return saveAs;
19446 });
19447 }
19448 },
19449 {}
19450 ],
19451 27: [
19452 function(_dereq_, module, exports) {
19453 'use strict';
19454
19455 function _interopDefault(ex) {
19456 return ex && typeof ex === 'object' && 'default' in ex ? ex['default'] : ex;
19457 }
19458
19459 var _classCallCheck = _interopDefault(
19460 _dereq_('@babel/runtime/helpers/classCallCheck')
19461 );
19462 var _createClass = _interopDefault(_dereq_('@babel/runtime/helpers/createClass'));
19463
19464 var arr = [];
19465 var each = arr.forEach;
19466 var slice = arr.slice;
19467 function defaults(obj) {
19468 each.call(slice.call(arguments, 1), function(source) {
19469 if (source) {
19470 for (var prop in source) {
19471 if (obj[prop] === undefined) obj[prop] = source[prop];
19472 }
19473 }
19474 });
19475 return obj;
19476 }
19477
19478 var cookie = {
19479 create: function create(name, value, minutes, domain) {
19480 var expires;
19481
19482 if (minutes) {
19483 var date = new Date();
19484 date.setTime(date.getTime() + minutes * 60 * 1000);
19485 expires = '; expires=' + date.toGMTString();
19486 } else expires = '';
19487
19488 domain = domain ? 'domain=' + domain + ';' : '';
19489 document.cookie = name + '=' + value + expires + ';' + domain + 'path=/';
19490 },
19491 read: function read(name) {
19492 var nameEQ = name + '=';
19493 var ca = document.cookie.split(';');
19494
19495 for (var i = 0; i < ca.length; i++) {
19496 var c = ca[i];
19497
19498 while (c.charAt(0) === ' ') {
19499 c = c.substring(1, c.length);
19500 }
19501
19502 if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length);
19503 }
19504
19505 return null;
19506 },
19507 remove: function remove(name) {
19508 this.create(name, '', -1);
19509 }
19510 };
19511 var cookie$1 = {
19512 name: 'cookie',
19513 lookup: function lookup(options) {
19514 var found;
19515
19516 if (options.lookupCookie && typeof document !== 'undefined') {
19517 var c = cookie.read(options.lookupCookie);
19518 if (c) found = c;
19519 }
19520
19521 return found;
19522 },
19523 cacheUserLanguage: function cacheUserLanguage(lng, options) {
19524 if (options.lookupCookie && typeof document !== 'undefined') {
19525 cookie.create(
19526 options.lookupCookie,
19527 lng,
19528 options.cookieMinutes,
19529 options.cookieDomain
19530 );
19531 }
19532 }
19533 };
19534
19535 var querystring = {
19536 name: 'querystring',
19537 lookup: function lookup(options) {
19538 var found;
19539
19540 if (typeof window !== 'undefined') {
19541 var query = window.location.search.substring(1);
19542 var params = query.split('&');
19543
19544 for (var i = 0; i < params.length; i++) {
19545 var pos = params[i].indexOf('=');
19546
19547 if (pos > 0) {
19548 var key = params[i].substring(0, pos);
19549
19550 if (key === options.lookupQuerystring) {
19551 found = params[i].substring(pos + 1);
19552 }
19553 }
19554 }
19555 }
19556
19557 return found;
19558 }
19559 };
19560
19561 var hasLocalStorageSupport;
19562
19563 try {
19564 hasLocalStorageSupport = window !== 'undefined' && window.localStorage !== null;
19565 var testKey = 'i18next.translate.boo';
19566 window.localStorage.setItem(testKey, 'foo');
19567 window.localStorage.removeItem(testKey);
19568 } catch (e) {
19569 hasLocalStorageSupport = false;
19570 }
19571
19572 var localStorage = {
19573 name: 'localStorage',
19574 lookup: function lookup(options) {
19575 var found;
19576
19577 if (options.lookupLocalStorage && hasLocalStorageSupport) {
19578 var lng = window.localStorage.getItem(options.lookupLocalStorage);
19579 if (lng) found = lng;
19580 }
19581
19582 return found;
19583 },
19584 cacheUserLanguage: function cacheUserLanguage(lng, options) {
19585 if (options.lookupLocalStorage && hasLocalStorageSupport) {
19586 window.localStorage.setItem(options.lookupLocalStorage, lng);
19587 }
19588 }
19589 };
19590
19591 var navigator$1 = {
19592 name: 'navigator',
19593 lookup: function lookup(options) {
19594 var found = [];
19595
19596 if (typeof navigator !== 'undefined') {
19597 if (navigator.languages) {
19598 // chrome only; not an array, so can't use .push.apply instead of iterating
19599 for (var i = 0; i < navigator.languages.length; i++) {
19600 found.push(navigator.languages[i]);
19601 }
19602 }
19603
19604 if (navigator.userLanguage) {
19605 found.push(navigator.userLanguage);
19606 }
19607
19608 if (navigator.language) {
19609 found.push(navigator.language);
19610 }
19611 }
19612
19613 return found.length > 0 ? found : undefined;
19614 }
19615 };
19616
19617 var htmlTag = {
19618 name: 'htmlTag',
19619 lookup: function lookup(options) {
19620 var found;
19621 var htmlTag =
19622 options.htmlTag ||
19623 (typeof document !== 'undefined' ? document.documentElement : null);
19624
19625 if (htmlTag && typeof htmlTag.getAttribute === 'function') {
19626 found = htmlTag.getAttribute('lang');
19627 }
19628
19629 return found;
19630 }
19631 };
19632
19633 var path = {
19634 name: 'path',
19635 lookup: function lookup(options) {
19636 var found;
19637
19638 if (typeof window !== 'undefined') {
19639 var language = window.location.pathname.match(/\/([a-zA-Z-]*)/g);
19640
19641 if (language instanceof Array) {
19642 if (typeof options.lookupFromPathIndex === 'number') {
19643 if (typeof language[options.lookupFromPathIndex] !== 'string') {
19644 return undefined;
19645 }
19646
19647 found = language[options.lookupFromPathIndex].replace('/', '');
19648 } else {
19649 found = language[0].replace('/', '');
19650 }
19651 }
19652 }
19653
19654 return found;
19655 }
19656 };
19657
19658 var subdomain = {
19659 name: 'subdomain',
19660 lookup: function lookup(options) {
19661 var found;
19662
19663 if (typeof window !== 'undefined') {
19664 var language = window.location.href.match(
19665 /(?:http[s]*\:\/\/)*(.*?)\.(?=[^\/]*\..{2,5})/gi
19666 );
19667
19668 if (language instanceof Array) {
19669 if (typeof options.lookupFromSubdomainIndex === 'number') {
19670 found = language[options.lookupFromSubdomainIndex]
19671 .replace('http://', '')
19672 .replace('https://', '')
19673 .replace('.', '');
19674 } else {
19675 found = language[0]
19676 .replace('http://', '')
19677 .replace('https://', '')
19678 .replace('.', '');
19679 }
19680 }
19681 }
19682
19683 return found;
19684 }
19685 };
19686
19687 function getDefaults() {
19688 return {
19689 order: ['querystring', 'cookie', 'localStorage', 'navigator', 'htmlTag'],
19690 lookupQuerystring: 'lng',
19691 lookupCookie: 'i18next',
19692 lookupLocalStorage: 'i18nextLng',
19693 // cache user language
19694 caches: ['localStorage'],
19695 excludeCacheFor: ['cimode'],
19696 //cookieMinutes: 10,
19697 //cookieDomain: 'myDomain'
19698 checkWhitelist: true
19699 };
19700 }
19701
19702 var Browser =
19703 /*#__PURE__*/
19704 (function() {
19705 function Browser(services) {
19706 var options =
19707 arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
19708
19709 _classCallCheck(this, Browser);
19710
19711 this.type = 'languageDetector';
19712 this.detectors = {};
19713 this.init(services, options);
19714 }
19715
19716 _createClass(Browser, [
19717 {
19718 key: 'init',
19719 value: function init(services) {
19720 var options =
19721 arguments.length > 1 && arguments[1] !== undefined
19722 ? arguments[1]
19723 : {};
19724 var i18nOptions =
19725 arguments.length > 2 && arguments[2] !== undefined
19726 ? arguments[2]
19727 : {};
19728 this.services = services;
19729 this.options = defaults(options, this.options || {}, getDefaults()); // backwards compatibility
19730
19731 if (this.options.lookupFromUrlIndex)
19732 this.options.lookupFromPathIndex = this.options.lookupFromUrlIndex;
19733 this.i18nOptions = i18nOptions;
19734 this.addDetector(cookie$1);
19735 this.addDetector(querystring);
19736 this.addDetector(localStorage);
19737 this.addDetector(navigator$1);
19738 this.addDetector(htmlTag);
19739 this.addDetector(path);
19740 this.addDetector(subdomain);
19741 }
19742 },
19743 {
19744 key: 'addDetector',
19745 value: function addDetector(detector) {
19746 this.detectors[detector.name] = detector;
19747 }
19748 },
19749 {
19750 key: 'detect',
19751 value: function detect(detectionOrder) {
19752 var _this = this;
19753
19754 if (!detectionOrder) detectionOrder = this.options.order;
19755 var detected = [];
19756 detectionOrder.forEach(function(detectorName) {
19757 if (_this.detectors[detectorName]) {
19758 var lookup = _this.detectors[detectorName].lookup(_this.options);
19759
19760 if (lookup && typeof lookup === 'string') lookup = [lookup];
19761 if (lookup) detected = detected.concat(lookup);
19762 }
19763 });
19764 var found;
19765 detected.forEach(function(lng) {
19766 if (found) return;
19767
19768 var cleanedLng = _this.services.languageUtils.formatLanguageCode(lng);
19769
19770 if (
19771 !_this.options.checkWhitelist ||
19772 _this.services.languageUtils.isWhitelisted(cleanedLng)
19773 )
19774 found = cleanedLng;
19775 });
19776
19777 if (!found) {
19778 var fallbacks = this.i18nOptions.fallbackLng;
19779 if (typeof fallbacks === 'string') fallbacks = [fallbacks];
19780 if (!fallbacks) fallbacks = [];
19781
19782 if (Object.prototype.toString.apply(fallbacks) === '[object Array]') {
19783 found = fallbacks[0];
19784 } else {
19785 found =
19786 fallbacks[0] || (fallbacks['default'] && fallbacks['default'][0]);
19787 }
19788 }
19789
19790 return found;
19791 }
19792 },
19793 {
19794 key: 'cacheUserLanguage',
19795 value: function cacheUserLanguage(lng, caches) {
19796 var _this2 = this;
19797
19798 if (!caches) caches = this.options.caches;
19799 if (!caches) return;
19800 if (
19801 this.options.excludeCacheFor &&
19802 this.options.excludeCacheFor.indexOf(lng) > -1
19803 )
19804 return;
19805 caches.forEach(function(cacheName) {
19806 if (_this2.detectors[cacheName])
19807 _this2.detectors[cacheName].cacheUserLanguage(lng, _this2.options);
19808 });
19809 }
19810 }
19811 ]);
19812
19813 return Browser;
19814 })();
19815
19816 Browser.type = 'languageDetector';
19817
19818 module.exports = Browser;
19819 },
19820 {
19821 '@babel/runtime/helpers/classCallCheck': 28,
19822 '@babel/runtime/helpers/createClass': 29
19823 }
19824 ],
19825 28: [
19826 function(_dereq_, module, exports) {
19827 arguments[4][5][0].apply(exports, arguments);
19828 },
19829 { dup: 5 }
19830 ],
19831 29: [
19832 function(_dereq_, module, exports) {
19833 arguments[4][6][0].apply(exports, arguments);
19834 },
19835 { dup: 6 }
19836 ],
19837 30: [
19838 function(_dereq_, module, exports) {
19839 'use strict';
19840
19841 function _interopDefault(ex) {
19842 return ex && typeof ex === 'object' && 'default' in ex ? ex['default'] : ex;
19843 }
19844
19845 var _typeof = _interopDefault(_dereq_('@babel/runtime/helpers/typeof'));
19846 var _objectSpread = _interopDefault(
19847 _dereq_('@babel/runtime/helpers/objectSpread')
19848 );
19849 var _classCallCheck = _interopDefault(
19850 _dereq_('@babel/runtime/helpers/classCallCheck')
19851 );
19852 var _createClass = _interopDefault(_dereq_('@babel/runtime/helpers/createClass'));
19853 var _possibleConstructorReturn = _interopDefault(
19854 _dereq_('@babel/runtime/helpers/possibleConstructorReturn')
19855 );
19856 var _getPrototypeOf = _interopDefault(
19857 _dereq_('@babel/runtime/helpers/getPrototypeOf')
19858 );
19859 var _assertThisInitialized = _interopDefault(
19860 _dereq_('@babel/runtime/helpers/assertThisInitialized')
19861 );
19862 var _inherits = _interopDefault(_dereq_('@babel/runtime/helpers/inherits'));
19863 var _toConsumableArray = _interopDefault(
19864 _dereq_('@babel/runtime/helpers/toConsumableArray')
19865 );
19866 var _slicedToArray = _interopDefault(
19867 _dereq_('@babel/runtime/helpers/slicedToArray')
19868 );
19869
19870 var consoleLogger = {
19871 type: 'logger',
19872 log: function log(args) {
19873 this.output('log', args);
19874 },
19875 warn: function warn(args) {
19876 this.output('warn', args);
19877 },
19878 error: function error(args) {
19879 this.output('error', args);
19880 },
19881 output: function output(type, args) {
19882 var _console;
19883
19884 /* eslint no-console: 0 */
19885 if (console && console[type])
19886 (_console = console)[type].apply(_console, _toConsumableArray(args));
19887 }
19888 };
19889
19890 var Logger =
19891 /*#__PURE__*/
19892 (function() {
19893 function Logger(concreteLogger) {
19894 var options =
19895 arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
19896
19897 _classCallCheck(this, Logger);
19898
19899 this.init(concreteLogger, options);
19900 }
19901
19902 _createClass(Logger, [
19903 {
19904 key: 'init',
19905 value: function init(concreteLogger) {
19906 var options =
19907 arguments.length > 1 && arguments[1] !== undefined
19908 ? arguments[1]
19909 : {};
19910 this.prefix = options.prefix || 'i18next:';
19911 this.logger = concreteLogger || consoleLogger;
19912 this.options = options;
19913 this.debug = options.debug;
19914 }
19915 },
19916 {
19917 key: 'setDebug',
19918 value: function setDebug(bool) {
19919 this.debug = bool;
19920 }
19921 },
19922 {
19923 key: 'log',
19924 value: function log() {
19925 for (
19926 var _len = arguments.length, args = new Array(_len), _key = 0;
19927 _key < _len;
19928 _key++
19929 ) {
19930 args[_key] = arguments[_key];
19931 }
19932
19933 return this.forward(args, 'log', '', true);
19934 }
19935 },
19936 {
19937 key: 'warn',
19938 value: function warn() {
19939 for (
19940 var _len2 = arguments.length, args = new Array(_len2), _key2 = 0;
19941 _key2 < _len2;
19942 _key2++
19943 ) {
19944 args[_key2] = arguments[_key2];
19945 }
19946
19947 return this.forward(args, 'warn', '', true);
19948 }
19949 },
19950 {
19951 key: 'error',
19952 value: function error() {
19953 for (
19954 var _len3 = arguments.length, args = new Array(_len3), _key3 = 0;
19955 _key3 < _len3;
19956 _key3++
19957 ) {
19958 args[_key3] = arguments[_key3];
19959 }
19960
19961 return this.forward(args, 'error', '');
19962 }
19963 },
19964 {
19965 key: 'deprecate',
19966 value: function deprecate() {
19967 for (
19968 var _len4 = arguments.length, args = new Array(_len4), _key4 = 0;
19969 _key4 < _len4;
19970 _key4++
19971 ) {
19972 args[_key4] = arguments[_key4];
19973 }
19974
19975 return this.forward(args, 'warn', 'WARNING DEPRECATED: ', true);
19976 }
19977 },
19978 {
19979 key: 'forward',
19980 value: function forward(args, lvl, prefix, debugOnly) {
19981 if (debugOnly && !this.debug) return null;
19982 if (typeof args[0] === 'string')
19983 args[0] = ''
19984 .concat(prefix)
19985 .concat(this.prefix, ' ')
19986 .concat(args[0]);
19987 return this.logger[lvl](args);
19988 }
19989 },
19990 {
19991 key: 'create',
19992 value: function create(moduleName) {
19993 return new Logger(
19994 this.logger,
19995 _objectSpread(
19996 {},
19997 {
19998 prefix: ''.concat(this.prefix, ':').concat(moduleName, ':')
19999 },
20000 this.options
20001 )
20002 );
20003 }
20004 }
20005 ]);
20006
20007 return Logger;
20008 })();
20009
20010 var baseLogger = new Logger();
20011
20012 var EventEmitter =
20013 /*#__PURE__*/
20014 (function() {
20015 function EventEmitter() {
20016 _classCallCheck(this, EventEmitter);
20017
20018 this.observers = {};
20019 }
20020
20021 _createClass(EventEmitter, [
20022 {
20023 key: 'on',
20024 value: function on(events, listener) {
20025 var _this = this;
20026
20027 events.split(' ').forEach(function(event) {
20028 _this.observers[event] = _this.observers[event] || [];
20029
20030 _this.observers[event].push(listener);
20031 });
20032 return this;
20033 }
20034 },
20035 {
20036 key: 'off',
20037 value: function off(event, listener) {
20038 if (!this.observers[event]) return;
20039
20040 if (!listener) {
20041 delete this.observers[event];
20042 return;
20043 }
20044
20045 this.observers[event] = this.observers[event].filter(function(l) {
20046 return l !== listener;
20047 });
20048 }
20049 },
20050 {
20051 key: 'emit',
20052 value: function emit(event) {
20053 for (
20054 var _len = arguments.length,
20055 args = new Array(_len > 1 ? _len - 1 : 0),
20056 _key = 1;
20057 _key < _len;
20058 _key++
20059 ) {
20060 args[_key - 1] = arguments[_key];
20061 }
20062
20063 if (this.observers[event]) {
20064 var cloned = [].concat(this.observers[event]);
20065 cloned.forEach(function(observer) {
20066 observer.apply(void 0, args);
20067 });
20068 }
20069
20070 if (this.observers['*']) {
20071 var _cloned = [].concat(this.observers['*']);
20072
20073 _cloned.forEach(function(observer) {
20074 observer.apply(observer, [event].concat(args));
20075 });
20076 }
20077 }
20078 }
20079 ]);
20080
20081 return EventEmitter;
20082 })();
20083
20084 // http://lea.verou.me/2016/12/resolve-promises-externally-with-this-one-weird-trick/
20085 function defer() {
20086 var res;
20087 var rej;
20088 var promise = new Promise(function(resolve, reject) {
20089 res = resolve;
20090 rej = reject;
20091 });
20092 promise.resolve = res;
20093 promise.reject = rej;
20094 return promise;
20095 }
20096 function makeString(object) {
20097 if (object == null) return '';
20098 /* eslint prefer-template: 0 */
20099
20100 return '' + object;
20101 }
20102 function copy(a, s, t) {
20103 a.forEach(function(m) {
20104 if (s[m]) t[m] = s[m];
20105 });
20106 }
20107
20108 function getLastOfPath(object, path, Empty) {
20109 function cleanKey(key) {
20110 return key && key.indexOf('###') > -1 ? key.replace(/###/g, '.') : key;
20111 }
20112
20113 function canNotTraverseDeeper() {
20114 return !object || typeof object === 'string';
20115 }
20116
20117 var stack = typeof path !== 'string' ? [].concat(path) : path.split('.');
20118
20119 while (stack.length > 1) {
20120 if (canNotTraverseDeeper()) return {};
20121 var key = cleanKey(stack.shift());
20122 if (!object[key] && Empty) object[key] = new Empty();
20123 object = object[key];
20124 }
20125
20126 if (canNotTraverseDeeper()) return {};
20127 return {
20128 obj: object,
20129 k: cleanKey(stack.shift())
20130 };
20131 }
20132
20133 function setPath(object, path, newValue) {
20134 var _getLastOfPath = getLastOfPath(object, path, Object),
20135 obj = _getLastOfPath.obj,
20136 k = _getLastOfPath.k;
20137
20138 obj[k] = newValue;
20139 }
20140 function pushPath(object, path, newValue, concat) {
20141 var _getLastOfPath2 = getLastOfPath(object, path, Object),
20142 obj = _getLastOfPath2.obj,
20143 k = _getLastOfPath2.k;
20144
20145 obj[k] = obj[k] || [];
20146 if (concat) obj[k] = obj[k].concat(newValue);
20147 if (!concat) obj[k].push(newValue);
20148 }
20149 function getPath(object, path) {
20150 var _getLastOfPath3 = getLastOfPath(object, path),
20151 obj = _getLastOfPath3.obj,
20152 k = _getLastOfPath3.k;
20153
20154 if (!obj) return undefined;
20155 return obj[k];
20156 }
20157 function getPathWithDefaults(data, defaultData, key) {
20158 var value = getPath(data, key);
20159
20160 if (value !== undefined) {
20161 return value;
20162 } // Fallback to default values
20163
20164 return getPath(defaultData, key);
20165 }
20166 function deepExtend(target, source, overwrite) {
20167 /* eslint no-restricted-syntax: 0 */
20168 for (var prop in source) {
20169 if (prop in target) {
20170 // If we reached a leaf string in target or source then replace with source or skip depending on the 'overwrite' switch
20171 if (
20172 typeof target[prop] === 'string' ||
20173 target[prop] instanceof String ||
20174 typeof source[prop] === 'string' ||
20175 source[prop] instanceof String
20176 ) {
20177 if (overwrite) target[prop] = source[prop];
20178 } else {
20179 deepExtend(target[prop], source[prop], overwrite);
20180 }
20181 } else {
20182 target[prop] = source[prop];
20183 }
20184 }
20185
20186 return target;
20187 }
20188 function regexEscape(str) {
20189 /* eslint no-useless-escape: 0 */
20190 return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
20191 }
20192 /* eslint-disable */
20193
20194 var _entityMap = {
20195 '&': '&amp;',
20196 '<': '&lt;',
20197 '>': '&gt;',
20198 '"': '&quot;',
20199 "'": '&#39;',
20200 '/': '&#x2F;'
20201 };
20202 /* eslint-enable */
20203
20204 function escape(data) {
20205 if (typeof data === 'string') {
20206 return data.replace(/[&<>"'\/]/g, function(s) {
20207 return _entityMap[s];
20208 });
20209 }
20210
20211 return data;
20212 }
20213
20214 var ResourceStore =
20215 /*#__PURE__*/
20216 (function(_EventEmitter) {
20217 _inherits(ResourceStore, _EventEmitter);
20218
20219 function ResourceStore(data) {
20220 var _this;
20221
20222 var options =
20223 arguments.length > 1 && arguments[1] !== undefined
20224 ? arguments[1]
20225 : {
20226 ns: ['translation'],
20227 defaultNS: 'translation'
20228 };
20229
20230 _classCallCheck(this, ResourceStore);
20231
20232 _this = _possibleConstructorReturn(
20233 this,
20234 _getPrototypeOf(ResourceStore).call(this)
20235 );
20236 EventEmitter.call(_assertThisInitialized(_this)); // <=IE10 fix (unable to call parent constructor)
20237
20238 _this.data = data || {};
20239 _this.options = options;
20240
20241 if (_this.options.keySeparator === undefined) {
20242 _this.options.keySeparator = '.';
20243 }
20244
20245 return _this;
20246 }
20247
20248 _createClass(ResourceStore, [
20249 {
20250 key: 'addNamespaces',
20251 value: function addNamespaces(ns) {
20252 if (this.options.ns.indexOf(ns) < 0) {
20253 this.options.ns.push(ns);
20254 }
20255 }
20256 },
20257 {
20258 key: 'removeNamespaces',
20259 value: function removeNamespaces(ns) {
20260 var index = this.options.ns.indexOf(ns);
20261
20262 if (index > -1) {
20263 this.options.ns.splice(index, 1);
20264 }
20265 }
20266 },
20267 {
20268 key: 'getResource',
20269 value: function getResource(lng, ns, key) {
20270 var options =
20271 arguments.length > 3 && arguments[3] !== undefined
20272 ? arguments[3]
20273 : {};
20274 var keySeparator =
20275 options.keySeparator !== undefined
20276 ? options.keySeparator
20277 : this.options.keySeparator;
20278 var path = [lng, ns];
20279 if (key && typeof key !== 'string') path = path.concat(key);
20280 if (key && typeof key === 'string')
20281 path = path.concat(keySeparator ? key.split(keySeparator) : key);
20282
20283 if (lng.indexOf('.') > -1) {
20284 path = lng.split('.');
20285 }
20286
20287 return getPath(this.data, path);
20288 }
20289 },
20290 {
20291 key: 'addResource',
20292 value: function addResource(lng, ns, key, value) {
20293 var options =
20294 arguments.length > 4 && arguments[4] !== undefined
20295 ? arguments[4]
20296 : {
20297 silent: false
20298 };
20299 var keySeparator = this.options.keySeparator;
20300 if (keySeparator === undefined) keySeparator = '.';
20301 var path = [lng, ns];
20302 if (key)
20303 path = path.concat(keySeparator ? key.split(keySeparator) : key);
20304
20305 if (lng.indexOf('.') > -1) {
20306 path = lng.split('.');
20307 value = ns;
20308 ns = path[1];
20309 }
20310
20311 this.addNamespaces(ns);
20312 setPath(this.data, path, value);
20313 if (!options.silent) this.emit('added', lng, ns, key, value);
20314 }
20315 },
20316 {
20317 key: 'addResources',
20318 value: function addResources(lng, ns, resources) {
20319 var options =
20320 arguments.length > 3 && arguments[3] !== undefined
20321 ? arguments[3]
20322 : {
20323 silent: false
20324 };
20325
20326 /* eslint no-restricted-syntax: 0 */
20327 for (var m in resources) {
20328 if (
20329 typeof resources[m] === 'string' ||
20330 Object.prototype.toString.apply(resources[m]) === '[object Array]'
20331 )
20332 this.addResource(lng, ns, m, resources[m], {
20333 silent: true
20334 });
20335 }
20336
20337 if (!options.silent) this.emit('added', lng, ns, resources);
20338 }
20339 },
20340 {
20341 key: 'addResourceBundle',
20342 value: function addResourceBundle(lng, ns, resources, deep, overwrite) {
20343 var options =
20344 arguments.length > 5 && arguments[5] !== undefined
20345 ? arguments[5]
20346 : {
20347 silent: false
20348 };
20349 var path = [lng, ns];
20350
20351 if (lng.indexOf('.') > -1) {
20352 path = lng.split('.');
20353 deep = resources;
20354 resources = ns;
20355 ns = path[1];
20356 }
20357
20358 this.addNamespaces(ns);
20359 var pack = getPath(this.data, path) || {};
20360
20361 if (deep) {
20362 deepExtend(pack, resources, overwrite);
20363 } else {
20364 pack = _objectSpread({}, pack, resources);
20365 }
20366
20367 setPath(this.data, path, pack);
20368 if (!options.silent) this.emit('added', lng, ns, resources);
20369 }
20370 },
20371 {
20372 key: 'removeResourceBundle',
20373 value: function removeResourceBundle(lng, ns) {
20374 if (this.hasResourceBundle(lng, ns)) {
20375 delete this.data[lng][ns];
20376 }
20377
20378 this.removeNamespaces(ns);
20379 this.emit('removed', lng, ns);
20380 }
20381 },
20382 {
20383 key: 'hasResourceBundle',
20384 value: function hasResourceBundle(lng, ns) {
20385 return this.getResource(lng, ns) !== undefined;
20386 }
20387 },
20388 {
20389 key: 'getResourceBundle',
20390 value: function getResourceBundle(lng, ns) {
20391 if (!ns) ns = this.options.defaultNS; // COMPATIBILITY: remove extend in v2.1.0
20392
20393 if (this.options.compatibilityAPI === 'v1')
20394 return _objectSpread({}, {}, this.getResource(lng, ns));
20395 return this.getResource(lng, ns);
20396 }
20397 },
20398 {
20399 key: 'getDataByLanguage',
20400 value: function getDataByLanguage(lng) {
20401 return this.data[lng];
20402 }
20403 },
20404 {
20405 key: 'toJSON',
20406 value: function toJSON() {
20407 return this.data;
20408 }
20409 }
20410 ]);
20411
20412 return ResourceStore;
20413 })(EventEmitter);
20414
20415 var postProcessor = {
20416 processors: {},
20417 addPostProcessor: function addPostProcessor(module) {
20418 this.processors[module.name] = module;
20419 },
20420 handle: function handle(processors, value, key, options, translator) {
20421 var _this = this;
20422
20423 processors.forEach(function(processor) {
20424 if (_this.processors[processor])
20425 value = _this.processors[processor].process(
20426 value,
20427 key,
20428 options,
20429 translator
20430 );
20431 });
20432 return value;
20433 }
20434 };
20435
20436 var checkedLoadedFor = {};
20437
20438 var Translator =
20439 /*#__PURE__*/
20440 (function(_EventEmitter) {
20441 _inherits(Translator, _EventEmitter);
20442
20443 function Translator(services) {
20444 var _this;
20445
20446 var options =
20447 arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
20448
20449 _classCallCheck(this, Translator);
20450
20451 _this = _possibleConstructorReturn(
20452 this,
20453 _getPrototypeOf(Translator).call(this)
20454 );
20455 EventEmitter.call(_assertThisInitialized(_this)); // <=IE10 fix (unable to call parent constructor)
20456
20457 copy(
20458 [
20459 'resourceStore',
20460 'languageUtils',
20461 'pluralResolver',
20462 'interpolator',
20463 'backendConnector',
20464 'i18nFormat',
20465 'utils'
20466 ],
20467 services,
20468 _assertThisInitialized(_this)
20469 );
20470 _this.options = options;
20471
20472 if (_this.options.keySeparator === undefined) {
20473 _this.options.keySeparator = '.';
20474 }
20475
20476 _this.logger = baseLogger.create('translator');
20477 return _this;
20478 }
20479
20480 _createClass(Translator, [
20481 {
20482 key: 'changeLanguage',
20483 value: function changeLanguage(lng) {
20484 if (lng) this.language = lng;
20485 }
20486 },
20487 {
20488 key: 'exists',
20489 value: function exists(key) {
20490 var options =
20491 arguments.length > 1 && arguments[1] !== undefined
20492 ? arguments[1]
20493 : {
20494 interpolation: {}
20495 };
20496 var resolved = this.resolve(key, options);
20497 return resolved && resolved.res !== undefined;
20498 }
20499 },
20500 {
20501 key: 'extractFromKey',
20502 value: function extractFromKey(key, options) {
20503 var nsSeparator = options.nsSeparator || this.options.nsSeparator;
20504 if (nsSeparator === undefined) nsSeparator = ':';
20505 var keySeparator =
20506 options.keySeparator !== undefined
20507 ? options.keySeparator
20508 : this.options.keySeparator;
20509 var namespaces = options.ns || this.options.defaultNS;
20510
20511 if (nsSeparator && key.indexOf(nsSeparator) > -1) {
20512 var parts = key.split(nsSeparator);
20513 if (
20514 nsSeparator !== keySeparator ||
20515 (nsSeparator === keySeparator &&
20516 this.options.ns.indexOf(parts[0]) > -1)
20517 )
20518 namespaces = parts.shift();
20519 key = parts.join(keySeparator);
20520 }
20521
20522 if (typeof namespaces === 'string') namespaces = [namespaces];
20523 return {
20524 key: key,
20525 namespaces: namespaces
20526 };
20527 }
20528 },
20529 {
20530 key: 'translate',
20531 value: function translate(keys, options) {
20532 var _this2 = this;
20533
20534 if (
20535 _typeof(options) !== 'object' &&
20536 this.options.overloadTranslationOptionHandler
20537 ) {
20538 /* eslint prefer-rest-params: 0 */
20539 options = this.options.overloadTranslationOptionHandler(arguments);
20540 }
20541
20542 if (!options) options = {}; // non valid keys handling
20543
20544 if (
20545 keys === undefined ||
20546 keys === null
20547 /* || keys === ''*/
20548 )
20549 return '';
20550 if (!Array.isArray(keys)) keys = [String(keys)]; // separators
20551
20552 var keySeparator =
20553 options.keySeparator !== undefined
20554 ? options.keySeparator
20555 : this.options.keySeparator; // get namespace(s)
20556
20557 var _this$extractFromKey = this.extractFromKey(
20558 keys[keys.length - 1],
20559 options
20560 ),
20561 key = _this$extractFromKey.key,
20562 namespaces = _this$extractFromKey.namespaces;
20563
20564 var namespace = namespaces[namespaces.length - 1]; // return key on CIMode
20565
20566 var lng = options.lng || this.language;
20567 var appendNamespaceToCIMode =
20568 options.appendNamespaceToCIMode ||
20569 this.options.appendNamespaceToCIMode;
20570
20571 if (lng && lng.toLowerCase() === 'cimode') {
20572 if (appendNamespaceToCIMode) {
20573 var nsSeparator = options.nsSeparator || this.options.nsSeparator;
20574 return namespace + nsSeparator + key;
20575 }
20576
20577 return key;
20578 } // resolve from store
20579
20580 var resolved = this.resolve(keys, options);
20581 var res = resolved && resolved.res;
20582 var resUsedKey = (resolved && resolved.usedKey) || key;
20583 var resExactUsedKey = (resolved && resolved.exactUsedKey) || key;
20584 var resType = Object.prototype.toString.apply(res);
20585 var noObject = [
20586 '[object Number]',
20587 '[object Function]',
20588 '[object RegExp]'
20589 ];
20590 var joinArrays =
20591 options.joinArrays !== undefined
20592 ? options.joinArrays
20593 : this.options.joinArrays; // object
20594
20595 var handleAsObjectInI18nFormat =
20596 !this.i18nFormat || this.i18nFormat.handleAsObject;
20597 var handleAsObject =
20598 typeof res !== 'string' &&
20599 typeof res !== 'boolean' &&
20600 typeof res !== 'number';
20601
20602 if (
20603 handleAsObjectInI18nFormat &&
20604 res &&
20605 handleAsObject &&
20606 noObject.indexOf(resType) < 0 &&
20607 !(typeof joinArrays === 'string' && resType === '[object Array]')
20608 ) {
20609 if (!options.returnObjects && !this.options.returnObjects) {
20610 this.logger.warn(
20611 'accessing an object - but returnObjects options is not enabled!'
20612 );
20613 return this.options.returnedObjectHandler
20614 ? this.options.returnedObjectHandler(resUsedKey, res, options)
20615 : "key '"
20616 .concat(key, ' (')
20617 .concat(
20618 this.language,
20619 ")' returned an object instead of string."
20620 );
20621 } // if we got a separator we loop over children - else we just return object as is
20622 // as having it set to false means no hierarchy so no lookup for nested values
20623
20624 if (keySeparator) {
20625 var resTypeIsArray = resType === '[object Array]';
20626 var copy$$1 = resTypeIsArray ? [] : {}; // apply child translation on a copy
20627
20628 /* eslint no-restricted-syntax: 0 */
20629
20630 var newKeyToUse = resTypeIsArray ? resExactUsedKey : resUsedKey;
20631
20632 for (var m in res) {
20633 if (Object.prototype.hasOwnProperty.call(res, m)) {
20634 var deepKey = ''
20635 .concat(newKeyToUse)
20636 .concat(keySeparator)
20637 .concat(m);
20638 copy$$1[m] = this.translate(
20639 deepKey,
20640 _objectSpread({}, options, {
20641 joinArrays: false,
20642 ns: namespaces
20643 })
20644 );
20645 if (copy$$1[m] === deepKey) copy$$1[m] = res[m]; // if nothing found use orginal value as fallback
20646 }
20647 }
20648
20649 res = copy$$1;
20650 }
20651 } else if (
20652 handleAsObjectInI18nFormat &&
20653 typeof joinArrays === 'string' &&
20654 resType === '[object Array]'
20655 ) {
20656 // array special treatment
20657 res = res.join(joinArrays);
20658 if (res) res = this.extendTranslation(res, keys, options);
20659 } else {
20660 // string, empty or null
20661 var usedDefault = false;
20662 var usedKey = false; // fallback value
20663
20664 if (!this.isValidLookup(res) && options.defaultValue !== undefined) {
20665 usedDefault = true;
20666
20667 if (options.count !== undefined) {
20668 var suffix = this.pluralResolver.getSuffix(lng, options.count);
20669 res = options['defaultValue'.concat(suffix)];
20670 }
20671
20672 if (!res) res = options.defaultValue;
20673 }
20674
20675 if (!this.isValidLookup(res)) {
20676 usedKey = true;
20677 res = key;
20678 } // save missing
20679
20680 var updateMissing =
20681 options.defaultValue &&
20682 options.defaultValue !== res &&
20683 this.options.updateMissing;
20684
20685 if (usedKey || usedDefault || updateMissing) {
20686 this.logger.log(
20687 updateMissing ? 'updateKey' : 'missingKey',
20688 lng,
20689 namespace,
20690 key,
20691 updateMissing ? options.defaultValue : res
20692 );
20693 var lngs = [];
20694 var fallbackLngs = this.languageUtils.getFallbackCodes(
20695 this.options.fallbackLng,
20696 options.lng || this.language
20697 );
20698
20699 if (
20700 this.options.saveMissingTo === 'fallback' &&
20701 fallbackLngs &&
20702 fallbackLngs[0]
20703 ) {
20704 for (var i = 0; i < fallbackLngs.length; i++) {
20705 lngs.push(fallbackLngs[i]);
20706 }
20707 } else if (this.options.saveMissingTo === 'all') {
20708 lngs = this.languageUtils.toResolveHierarchy(
20709 options.lng || this.language
20710 );
20711 } else {
20712 lngs.push(options.lng || this.language);
20713 }
20714
20715 var send = function send(l, k) {
20716 if (_this2.options.missingKeyHandler) {
20717 _this2.options.missingKeyHandler(
20718 l,
20719 namespace,
20720 k,
20721 updateMissing ? options.defaultValue : res,
20722 updateMissing,
20723 options
20724 );
20725 } else if (
20726 _this2.backendConnector &&
20727 _this2.backendConnector.saveMissing
20728 ) {
20729 _this2.backendConnector.saveMissing(
20730 l,
20731 namespace,
20732 k,
20733 updateMissing ? options.defaultValue : res,
20734 updateMissing,
20735 options
20736 );
20737 }
20738
20739 _this2.emit('missingKey', l, namespace, k, res);
20740 };
20741
20742 if (this.options.saveMissing) {
20743 var needsPluralHandling =
20744 options.count !== undefined &&
20745 typeof options.count !== 'string';
20746
20747 if (this.options.saveMissingPlurals && needsPluralHandling) {
20748 lngs.forEach(function(l) {
20749 var plurals = _this2.pluralResolver.getPluralFormsOfKey(
20750 l,
20751 key
20752 );
20753
20754 plurals.forEach(function(p) {
20755 return send([l], p);
20756 });
20757 });
20758 } else {
20759 send(lngs, key);
20760 }
20761 }
20762 } // extend
20763
20764 res = this.extendTranslation(res, keys, options, resolved); // append namespace if still key
20765
20766 if (
20767 usedKey &&
20768 res === key &&
20769 this.options.appendNamespaceToMissingKey
20770 )
20771 res = ''.concat(namespace, ':').concat(key); // parseMissingKeyHandler
20772
20773 if (usedKey && this.options.parseMissingKeyHandler)
20774 res = this.options.parseMissingKeyHandler(res);
20775 } // return
20776
20777 return res;
20778 }
20779 },
20780 {
20781 key: 'extendTranslation',
20782 value: function extendTranslation(res, key, options, resolved) {
20783 var _this3 = this;
20784
20785 if (this.i18nFormat && this.i18nFormat.parse) {
20786 res = this.i18nFormat.parse(
20787 res,
20788 options,
20789 resolved.usedLng,
20790 resolved.usedNS,
20791 resolved.usedKey,
20792 {
20793 resolved: resolved
20794 }
20795 );
20796 } else if (!options.skipInterpolation) {
20797 // i18next.parsing
20798 if (options.interpolation)
20799 this.interpolator.init(
20800 _objectSpread({}, options, {
20801 interpolation: _objectSpread(
20802 {},
20803 this.options.interpolation,
20804 options.interpolation
20805 )
20806 })
20807 ); // interpolate
20808
20809 var data =
20810 options.replace && typeof options.replace !== 'string'
20811 ? options.replace
20812 : options;
20813 if (this.options.interpolation.defaultVariables)
20814 data = _objectSpread(
20815 {},
20816 this.options.interpolation.defaultVariables,
20817 data
20818 );
20819 res = this.interpolator.interpolate(
20820 res,
20821 data,
20822 options.lng || this.language,
20823 options
20824 ); // nesting
20825
20826 if (options.nest !== false)
20827 res = this.interpolator.nest(
20828 res,
20829 function() {
20830 return _this3.translate.apply(_this3, arguments);
20831 },
20832 options
20833 );
20834 if (options.interpolation) this.interpolator.reset();
20835 } // post process
20836
20837 var postProcess = options.postProcess || this.options.postProcess;
20838 var postProcessorNames =
20839 typeof postProcess === 'string' ? [postProcess] : postProcess;
20840
20841 if (
20842 res !== undefined &&
20843 res !== null &&
20844 postProcessorNames &&
20845 postProcessorNames.length &&
20846 options.applyPostProcessor !== false
20847 ) {
20848 res = postProcessor.handle(
20849 postProcessorNames,
20850 res,
20851 key,
20852 this.options && this.options.postProcessPassResolved
20853 ? _objectSpread(
20854 {
20855 i18nResolved: resolved
20856 },
20857 options
20858 )
20859 : options,
20860 this
20861 );
20862 }
20863
20864 return res;
20865 }
20866 },
20867 {
20868 key: 'resolve',
20869 value: function resolve(keys) {
20870 var _this4 = this;
20871
20872 var options =
20873 arguments.length > 1 && arguments[1] !== undefined
20874 ? arguments[1]
20875 : {};
20876 var found;
20877 var usedKey; // plain key
20878
20879 var exactUsedKey; // key with context / plural
20880
20881 var usedLng;
20882 var usedNS;
20883 if (typeof keys === 'string') keys = [keys]; // forEach possible key
20884
20885 keys.forEach(function(k) {
20886 if (_this4.isValidLookup(found)) return;
20887
20888 var extracted = _this4.extractFromKey(k, options);
20889
20890 var key = extracted.key;
20891 usedKey = key;
20892 var namespaces = extracted.namespaces;
20893 if (_this4.options.fallbackNS)
20894 namespaces = namespaces.concat(_this4.options.fallbackNS);
20895 var needsPluralHandling =
20896 options.count !== undefined && typeof options.count !== 'string';
20897 var needsContextHandling =
20898 options.context !== undefined &&
20899 typeof options.context === 'string' &&
20900 options.context !== '';
20901 var codes = options.lngs
20902 ? options.lngs
20903 : _this4.languageUtils.toResolveHierarchy(
20904 options.lng || _this4.language,
20905 options.fallbackLng
20906 );
20907 namespaces.forEach(function(ns) {
20908 if (_this4.isValidLookup(found)) return;
20909 usedNS = ns;
20910
20911 if (
20912 !checkedLoadedFor[''.concat(codes[0], '-').concat(ns)] &&
20913 _this4.utils &&
20914 _this4.utils.hasLoadedNamespace &&
20915 !_this4.utils.hasLoadedNamespace(usedNS)
20916 ) {
20917 checkedLoadedFor[''.concat(codes[0], '-').concat(ns)] = true;
20918
20919 _this4.logger.warn(
20920 'key "'
20921 .concat(usedKey, '" for namespace "')
20922 .concat(usedNS, '" for languages "')
20923 .concat(
20924 codes.join(', '),
20925 '" won\'t get resolved as namespace was not yet loaded'
20926 ),
20927 'This means something IS WRONG in your application setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!'
20928 );
20929 }
20930
20931 codes.forEach(function(code) {
20932 if (_this4.isValidLookup(found)) return;
20933 usedLng = code;
20934 var finalKey = key;
20935 var finalKeys = [finalKey];
20936
20937 if (_this4.i18nFormat && _this4.i18nFormat.addLookupKeys) {
20938 _this4.i18nFormat.addLookupKeys(
20939 finalKeys,
20940 key,
20941 code,
20942 ns,
20943 options
20944 );
20945 } else {
20946 var pluralSuffix;
20947 if (needsPluralHandling)
20948 pluralSuffix = _this4.pluralResolver.getSuffix(
20949 code,
20950 options.count
20951 ); // fallback for plural if context not found
20952
20953 if (needsPluralHandling && needsContextHandling)
20954 finalKeys.push(finalKey + pluralSuffix); // get key for context if needed
20955
20956 if (needsContextHandling)
20957 finalKeys.push(
20958 (finalKey += ''
20959 .concat(_this4.options.contextSeparator)
20960 .concat(options.context))
20961 ); // get key for plural if needed
20962
20963 if (needsPluralHandling)
20964 finalKeys.push((finalKey += pluralSuffix));
20965 } // iterate over finalKeys starting with most specific pluralkey (-> contextkey only) -> singularkey only
20966
20967 var possibleKey;
20968 /* eslint no-cond-assign: 0 */
20969
20970 while ((possibleKey = finalKeys.pop())) {
20971 if (!_this4.isValidLookup(found)) {
20972 exactUsedKey = possibleKey;
20973 found = _this4.getResource(code, ns, possibleKey, options);
20974 }
20975 }
20976 });
20977 });
20978 });
20979 return {
20980 res: found,
20981 usedKey: usedKey,
20982 exactUsedKey: exactUsedKey,
20983 usedLng: usedLng,
20984 usedNS: usedNS
20985 };
20986 }
20987 },
20988 {
20989 key: 'isValidLookup',
20990 value: function isValidLookup(res) {
20991 return (
20992 res !== undefined &&
20993 !(!this.options.returnNull && res === null) &&
20994 !(!this.options.returnEmptyString && res === '')
20995 );
20996 }
20997 },
20998 {
20999 key: 'getResource',
21000 value: function getResource(code, ns, key) {
21001 var options =
21002 arguments.length > 3 && arguments[3] !== undefined
21003 ? arguments[3]
21004 : {};
21005 if (this.i18nFormat && this.i18nFormat.getResource)
21006 return this.i18nFormat.getResource(code, ns, key, options);
21007 return this.resourceStore.getResource(code, ns, key, options);
21008 }
21009 }
21010 ]);
21011
21012 return Translator;
21013 })(EventEmitter);
21014
21015 function capitalize(string) {
21016 return string.charAt(0).toUpperCase() + string.slice(1);
21017 }
21018
21019 var LanguageUtil =
21020 /*#__PURE__*/
21021 (function() {
21022 function LanguageUtil(options) {
21023 _classCallCheck(this, LanguageUtil);
21024
21025 this.options = options;
21026 this.whitelist = this.options.whitelist || false;
21027 this.logger = baseLogger.create('languageUtils');
21028 }
21029
21030 _createClass(LanguageUtil, [
21031 {
21032 key: 'getScriptPartFromCode',
21033 value: function getScriptPartFromCode(code) {
21034 if (!code || code.indexOf('-') < 0) return null;
21035 var p = code.split('-');
21036 if (p.length === 2) return null;
21037 p.pop();
21038 return this.formatLanguageCode(p.join('-'));
21039 }
21040 },
21041 {
21042 key: 'getLanguagePartFromCode',
21043 value: function getLanguagePartFromCode(code) {
21044 if (!code || code.indexOf('-') < 0) return code;
21045 var p = code.split('-');
21046 return this.formatLanguageCode(p[0]);
21047 }
21048 },
21049 {
21050 key: 'formatLanguageCode',
21051 value: function formatLanguageCode(code) {
21052 // http://www.iana.org/assignments/language-tags/language-tags.xhtml
21053 if (typeof code === 'string' && code.indexOf('-') > -1) {
21054 var specialCases = [
21055 'hans',
21056 'hant',
21057 'latn',
21058 'cyrl',
21059 'cans',
21060 'mong',
21061 'arab'
21062 ];
21063 var p = code.split('-');
21064
21065 if (this.options.lowerCaseLng) {
21066 p = p.map(function(part) {
21067 return part.toLowerCase();
21068 });
21069 } else if (p.length === 2) {
21070 p[0] = p[0].toLowerCase();
21071 p[1] = p[1].toUpperCase();
21072 if (specialCases.indexOf(p[1].toLowerCase()) > -1)
21073 p[1] = capitalize(p[1].toLowerCase());
21074 } else if (p.length === 3) {
21075 p[0] = p[0].toLowerCase(); // if lenght 2 guess it's a country
21076
21077 if (p[1].length === 2) p[1] = p[1].toUpperCase();
21078 if (p[0] !== 'sgn' && p[2].length === 2) p[2] = p[2].toUpperCase();
21079 if (specialCases.indexOf(p[1].toLowerCase()) > -1)
21080 p[1] = capitalize(p[1].toLowerCase());
21081 if (specialCases.indexOf(p[2].toLowerCase()) > -1)
21082 p[2] = capitalize(p[2].toLowerCase());
21083 }
21084
21085 return p.join('-');
21086 }
21087
21088 return this.options.cleanCode || this.options.lowerCaseLng
21089 ? code.toLowerCase()
21090 : code;
21091 }
21092 },
21093 {
21094 key: 'isWhitelisted',
21095 value: function isWhitelisted(code) {
21096 if (
21097 this.options.load === 'languageOnly' ||
21098 this.options.nonExplicitWhitelist
21099 ) {
21100 code = this.getLanguagePartFromCode(code);
21101 }
21102
21103 return (
21104 !this.whitelist ||
21105 !this.whitelist.length ||
21106 this.whitelist.indexOf(code) > -1
21107 );
21108 }
21109 },
21110 {
21111 key: 'getFallbackCodes',
21112 value: function getFallbackCodes(fallbacks, code) {
21113 if (!fallbacks) return [];
21114 if (typeof fallbacks === 'string') fallbacks = [fallbacks];
21115 if (Object.prototype.toString.apply(fallbacks) === '[object Array]')
21116 return fallbacks;
21117 if (!code) return fallbacks['default'] || []; // asume we have an object defining fallbacks
21118
21119 var found = fallbacks[code];
21120 if (!found) found = fallbacks[this.getScriptPartFromCode(code)];
21121 if (!found) found = fallbacks[this.formatLanguageCode(code)];
21122 if (!found) found = fallbacks['default'];
21123 return found || [];
21124 }
21125 },
21126 {
21127 key: 'toResolveHierarchy',
21128 value: function toResolveHierarchy(code, fallbackCode) {
21129 var _this = this;
21130
21131 var fallbackCodes = this.getFallbackCodes(
21132 fallbackCode || this.options.fallbackLng || [],
21133 code
21134 );
21135 var codes = [];
21136
21137 var addCode = function addCode(c) {
21138 if (!c) return;
21139
21140 if (_this.isWhitelisted(c)) {
21141 codes.push(c);
21142 } else {
21143 _this.logger.warn(
21144 'rejecting non-whitelisted language code: '.concat(c)
21145 );
21146 }
21147 };
21148
21149 if (typeof code === 'string' && code.indexOf('-') > -1) {
21150 if (this.options.load !== 'languageOnly')
21151 addCode(this.formatLanguageCode(code));
21152 if (
21153 this.options.load !== 'languageOnly' &&
21154 this.options.load !== 'currentOnly'
21155 )
21156 addCode(this.getScriptPartFromCode(code));
21157 if (this.options.load !== 'currentOnly')
21158 addCode(this.getLanguagePartFromCode(code));
21159 } else if (typeof code === 'string') {
21160 addCode(this.formatLanguageCode(code));
21161 }
21162
21163 fallbackCodes.forEach(function(fc) {
21164 if (codes.indexOf(fc) < 0) addCode(_this.formatLanguageCode(fc));
21165 });
21166 return codes;
21167 }
21168 }
21169 ]);
21170
21171 return LanguageUtil;
21172 })();
21173
21174 /* eslint-disable */
21175
21176 var sets = [
21177 {
21178 lngs: [
21179 'ach',
21180 'ak',
21181 'am',
21182 'arn',
21183 'br',
21184 'fil',
21185 'gun',
21186 'ln',
21187 'mfe',
21188 'mg',
21189 'mi',
21190 'oc',
21191 'pt',
21192 'pt-BR',
21193 'tg',
21194 'ti',
21195 'tr',
21196 'uz',
21197 'wa'
21198 ],
21199 nr: [1, 2],
21200 fc: 1
21201 },
21202 {
21203 lngs: [
21204 'af',
21205 'an',
21206 'ast',
21207 'az',
21208 'bg',
21209 'bn',
21210 'ca',
21211 'da',
21212 'de',
21213 'dev',
21214 'el',
21215 'en',
21216 'eo',
21217 'es',
21218 'et',
21219 'eu',
21220 'fi',
21221 'fo',
21222 'fur',
21223 'fy',
21224 'gl',
21225 'gu',
21226 'ha',
21227 'hi',
21228 'hu',
21229 'hy',
21230 'ia',
21231 'it',
21232 'kn',
21233 'ku',
21234 'lb',
21235 'mai',
21236 'ml',
21237 'mn',
21238 'mr',
21239 'nah',
21240 'nap',
21241 'nb',
21242 'ne',
21243 'nl',
21244 'nn',
21245 'no',
21246 'nso',
21247 'pa',
21248 'pap',
21249 'pms',
21250 'ps',
21251 'pt-PT',
21252 'rm',
21253 'sco',
21254 'se',
21255 'si',
21256 'so',
21257 'son',
21258 'sq',
21259 'sv',
21260 'sw',
21261 'ta',
21262 'te',
21263 'tk',
21264 'ur',
21265 'yo'
21266 ],
21267 nr: [1, 2],
21268 fc: 2
21269 },
21270 {
21271 lngs: [
21272 'ay',
21273 'bo',
21274 'cgg',
21275 'fa',
21276 'id',
21277 'ja',
21278 'jbo',
21279 'ka',
21280 'kk',
21281 'km',
21282 'ko',
21283 'ky',
21284 'lo',
21285 'ms',
21286 'sah',
21287 'su',
21288 'th',
21289 'tt',
21290 'ug',
21291 'vi',
21292 'wo',
21293 'zh'
21294 ],
21295 nr: [1],
21296 fc: 3
21297 },
21298 {
21299 lngs: ['be', 'bs', 'cnr', 'dz', 'hr', 'ru', 'sr', 'uk'],
21300 nr: [1, 2, 5],
21301 fc: 4
21302 },
21303 {
21304 lngs: ['ar'],
21305 nr: [0, 1, 2, 3, 11, 100],
21306 fc: 5
21307 },
21308 {
21309 lngs: ['cs', 'sk'],
21310 nr: [1, 2, 5],
21311 fc: 6
21312 },
21313 {
21314 lngs: ['csb', 'pl'],
21315 nr: [1, 2, 5],
21316 fc: 7
21317 },
21318 {
21319 lngs: ['cy'],
21320 nr: [1, 2, 3, 8],
21321 fc: 8
21322 },
21323 {
21324 lngs: ['fr'],
21325 nr: [1, 2],
21326 fc: 9
21327 },
21328 {
21329 lngs: ['ga'],
21330 nr: [1, 2, 3, 7, 11],
21331 fc: 10
21332 },
21333 {
21334 lngs: ['gd'],
21335 nr: [1, 2, 3, 20],
21336 fc: 11
21337 },
21338 {
21339 lngs: ['is'],
21340 nr: [1, 2],
21341 fc: 12
21342 },
21343 {
21344 lngs: ['jv'],
21345 nr: [0, 1],
21346 fc: 13
21347 },
21348 {
21349 lngs: ['kw'],
21350 nr: [1, 2, 3, 4],
21351 fc: 14
21352 },
21353 {
21354 lngs: ['lt'],
21355 nr: [1, 2, 10],
21356 fc: 15
21357 },
21358 {
21359 lngs: ['lv'],
21360 nr: [1, 2, 0],
21361 fc: 16
21362 },
21363 {
21364 lngs: ['mk'],
21365 nr: [1, 2],
21366 fc: 17
21367 },
21368 {
21369 lngs: ['mnk'],
21370 nr: [0, 1, 2],
21371 fc: 18
21372 },
21373 {
21374 lngs: ['mt'],
21375 nr: [1, 2, 11, 20],
21376 fc: 19
21377 },
21378 {
21379 lngs: ['or'],
21380 nr: [2, 1],
21381 fc: 2
21382 },
21383 {
21384 lngs: ['ro'],
21385 nr: [1, 2, 20],
21386 fc: 20
21387 },
21388 {
21389 lngs: ['sl'],
21390 nr: [5, 1, 2, 3],
21391 fc: 21
21392 },
21393 {
21394 lngs: ['he'],
21395 nr: [1, 2, 20, 21],
21396 fc: 22
21397 }
21398 ];
21399 var _rulesPluralsTypes = {
21400 1: function _(n) {
21401 return Number(n > 1);
21402 },
21403 2: function _(n) {
21404 return Number(n != 1);
21405 },
21406 3: function _(n) {
21407 return 0;
21408 },
21409 4: function _(n) {
21410 return Number(
21411 n % 10 == 1 && n % 100 != 11
21412 ? 0
21413 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2
21414 );
21415 },
21416 5: function _(n) {
21417 return Number(
21418 n === 0
21419 ? 0
21420 : n == 1
21421 ? 1
21422 : n == 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 ? 4 : 5
21423 );
21424 },
21425 6: function _(n) {
21426 return Number(n == 1 ? 0 : n >= 2 && n <= 4 ? 1 : 2);
21427 },
21428 7: function _(n) {
21429 return Number(
21430 n == 1
21431 ? 0
21432 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2
21433 );
21434 },
21435 8: function _(n) {
21436 return Number(n == 1 ? 0 : n == 2 ? 1 : n != 8 && n != 11 ? 2 : 3);
21437 },
21438 9: function _(n) {
21439 return Number(n >= 2);
21440 },
21441 10: function _(n) {
21442 return Number(n == 1 ? 0 : n == 2 ? 1 : n < 7 ? 2 : n < 11 ? 3 : 4);
21443 },
21444 11: function _(n) {
21445 return Number(
21446 n == 1 || n == 11 ? 0 : n == 2 || n == 12 ? 1 : n > 2 && n < 20 ? 2 : 3
21447 );
21448 },
21449 12: function _(n) {
21450 return Number(n % 10 != 1 || n % 100 == 11);
21451 },
21452 13: function _(n) {
21453 return Number(n !== 0);
21454 },
21455 14: function _(n) {
21456 return Number(n == 1 ? 0 : n == 2 ? 1 : n == 3 ? 2 : 3);
21457 },
21458 15: function _(n) {
21459 return Number(
21460 n % 10 == 1 && n % 100 != 11
21461 ? 0
21462 : n % 10 >= 2 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2
21463 );
21464 },
21465 16: function _(n) {
21466 return Number(n % 10 == 1 && n % 100 != 11 ? 0 : n !== 0 ? 1 : 2);
21467 },
21468 17: function _(n) {
21469 return Number(n == 1 || n % 10 == 1 ? 0 : 1);
21470 },
21471 18: function _(n) {
21472 return Number(n == 0 ? 0 : n == 1 ? 1 : 2);
21473 },
21474 19: function _(n) {
21475 return Number(
21476 n == 1
21477 ? 0
21478 : n === 0 || (n % 100 > 1 && n % 100 < 11)
21479 ? 1
21480 : n % 100 > 10 && n % 100 < 20 ? 2 : 3
21481 );
21482 },
21483 20: function _(n) {
21484 return Number(n == 1 ? 0 : n === 0 || (n % 100 > 0 && n % 100 < 20) ? 1 : 2);
21485 },
21486 21: function _(n) {
21487 return Number(
21488 n % 100 == 1 ? 1 : n % 100 == 2 ? 2 : n % 100 == 3 || n % 100 == 4 ? 3 : 0
21489 );
21490 },
21491 22: function _(n) {
21492 return Number(
21493 n === 1 ? 0 : n === 2 ? 1 : (n < 0 || n > 10) && n % 10 == 0 ? 2 : 3
21494 );
21495 }
21496 };
21497 /* eslint-enable */
21498
21499 function createRules() {
21500 var rules = {};
21501 sets.forEach(function(set) {
21502 set.lngs.forEach(function(l) {
21503 rules[l] = {
21504 numbers: set.nr,
21505 plurals: _rulesPluralsTypes[set.fc]
21506 };
21507 });
21508 });
21509 return rules;
21510 }
21511
21512 var PluralResolver =
21513 /*#__PURE__*/
21514 (function() {
21515 function PluralResolver(languageUtils) {
21516 var options =
21517 arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
21518
21519 _classCallCheck(this, PluralResolver);
21520
21521 this.languageUtils = languageUtils;
21522 this.options = options;
21523 this.logger = baseLogger.create('pluralResolver');
21524 this.rules = createRules();
21525 }
21526
21527 _createClass(PluralResolver, [
21528 {
21529 key: 'addRule',
21530 value: function addRule(lng, obj) {
21531 this.rules[lng] = obj;
21532 }
21533 },
21534 {
21535 key: 'getRule',
21536 value: function getRule(code) {
21537 return (
21538 this.rules[code] ||
21539 this.rules[this.languageUtils.getLanguagePartFromCode(code)]
21540 );
21541 }
21542 },
21543 {
21544 key: 'needsPlural',
21545 value: function needsPlural(code) {
21546 var rule = this.getRule(code);
21547 return rule && rule.numbers.length > 1;
21548 }
21549 },
21550 {
21551 key: 'getPluralFormsOfKey',
21552 value: function getPluralFormsOfKey(code, key) {
21553 var _this = this;
21554
21555 var ret = [];
21556 var rule = this.getRule(code);
21557 if (!rule) return ret;
21558 rule.numbers.forEach(function(n) {
21559 var suffix = _this.getSuffix(code, n);
21560
21561 ret.push(''.concat(key).concat(suffix));
21562 });
21563 return ret;
21564 }
21565 },
21566 {
21567 key: 'getSuffix',
21568 value: function getSuffix(code, count) {
21569 var _this2 = this;
21570
21571 var rule = this.getRule(code);
21572
21573 if (rule) {
21574 // if (rule.numbers.length === 1) return ''; // only singular
21575 var idx = rule.noAbs
21576 ? rule.plurals(count)
21577 : rule.plurals(Math.abs(count));
21578 var suffix = rule.numbers[idx]; // special treatment for lngs only having singular and plural
21579
21580 if (
21581 this.options.simplifyPluralSuffix &&
21582 rule.numbers.length === 2 &&
21583 rule.numbers[0] === 1
21584 ) {
21585 if (suffix === 2) {
21586 suffix = 'plural';
21587 } else if (suffix === 1) {
21588 suffix = '';
21589 }
21590 }
21591
21592 var returnSuffix = function returnSuffix() {
21593 return _this2.options.prepend && suffix.toString()
21594 ? _this2.options.prepend + suffix.toString()
21595 : suffix.toString();
21596 }; // COMPATIBILITY JSON
21597 // v1
21598
21599 if (this.options.compatibilityJSON === 'v1') {
21600 if (suffix === 1) return '';
21601 if (typeof suffix === 'number')
21602 return '_plural_'.concat(suffix.toString());
21603 return returnSuffix();
21604 } else if (
21605 /* v2 */
21606 this.options.compatibilityJSON === 'v2'
21607 ) {
21608 return returnSuffix();
21609 } else if (
21610 /* v3 - gettext index */
21611 this.options.simplifyPluralSuffix &&
21612 rule.numbers.length === 2 &&
21613 rule.numbers[0] === 1
21614 ) {
21615 return returnSuffix();
21616 }
21617
21618 return this.options.prepend && idx.toString()
21619 ? this.options.prepend + idx.toString()
21620 : idx.toString();
21621 }
21622
21623 this.logger.warn('no plural rule found for: '.concat(code));
21624 return '';
21625 }
21626 }
21627 ]);
21628
21629 return PluralResolver;
21630 })();
21631
21632 var Interpolator =
21633 /*#__PURE__*/
21634 (function() {
21635 function Interpolator() {
21636 var options =
21637 arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
21638
21639 _classCallCheck(this, Interpolator);
21640
21641 this.logger = baseLogger.create('interpolator');
21642 this.options = options;
21643
21644 this.format =
21645 (options.interpolation && options.interpolation.format) ||
21646 function(value) {
21647 return value;
21648 };
21649
21650 this.init(options);
21651 }
21652 /* eslint no-param-reassign: 0 */
21653
21654 _createClass(Interpolator, [
21655 {
21656 key: 'init',
21657 value: function init() {
21658 var options =
21659 arguments.length > 0 && arguments[0] !== undefined
21660 ? arguments[0]
21661 : {};
21662 if (!options.interpolation)
21663 options.interpolation = {
21664 escapeValue: true
21665 };
21666 var iOpts = options.interpolation;
21667 this.escape = iOpts.escape !== undefined ? iOpts.escape : escape;
21668 this.escapeValue =
21669 iOpts.escapeValue !== undefined ? iOpts.escapeValue : true;
21670 this.useRawValueToEscape =
21671 iOpts.useRawValueToEscape !== undefined
21672 ? iOpts.useRawValueToEscape
21673 : false;
21674 this.prefix = iOpts.prefix
21675 ? regexEscape(iOpts.prefix)
21676 : iOpts.prefixEscaped || '{{';
21677 this.suffix = iOpts.suffix
21678 ? regexEscape(iOpts.suffix)
21679 : iOpts.suffixEscaped || '}}';
21680 this.formatSeparator = iOpts.formatSeparator
21681 ? iOpts.formatSeparator
21682 : iOpts.formatSeparator || ',';
21683 this.unescapePrefix = iOpts.unescapeSuffix
21684 ? ''
21685 : iOpts.unescapePrefix || '-';
21686 this.unescapeSuffix = this.unescapePrefix
21687 ? ''
21688 : iOpts.unescapeSuffix || '';
21689 this.nestingPrefix = iOpts.nestingPrefix
21690 ? regexEscape(iOpts.nestingPrefix)
21691 : iOpts.nestingPrefixEscaped || regexEscape('$t(');
21692 this.nestingSuffix = iOpts.nestingSuffix
21693 ? regexEscape(iOpts.nestingSuffix)
21694 : iOpts.nestingSuffixEscaped || regexEscape(')');
21695 this.maxReplaces = iOpts.maxReplaces ? iOpts.maxReplaces : 1000; // the regexp
21696
21697 this.resetRegExp();
21698 }
21699 },
21700 {
21701 key: 'reset',
21702 value: function reset() {
21703 if (this.options) this.init(this.options);
21704 }
21705 },
21706 {
21707 key: 'resetRegExp',
21708 value: function resetRegExp() {
21709 // the regexp
21710 var regexpStr = ''.concat(this.prefix, '(.+?)').concat(this.suffix);
21711 this.regexp = new RegExp(regexpStr, 'g');
21712 var regexpUnescapeStr = ''
21713 .concat(this.prefix)
21714 .concat(this.unescapePrefix, '(.+?)')
21715 .concat(this.unescapeSuffix)
21716 .concat(this.suffix);
21717 this.regexpUnescape = new RegExp(regexpUnescapeStr, 'g');
21718 var nestingRegexpStr = ''
21719 .concat(this.nestingPrefix, '(.+?)')
21720 .concat(this.nestingSuffix);
21721 this.nestingRegexp = new RegExp(nestingRegexpStr, 'g');
21722 }
21723 },
21724 {
21725 key: 'interpolate',
21726 value: function interpolate(str, data, lng, options) {
21727 var _this = this;
21728
21729 var match;
21730 var value;
21731 var replaces;
21732 var defaultData =
21733 (this.options &&
21734 this.options.interpolation &&
21735 this.options.interpolation.defaultVariables) ||
21736 {};
21737
21738 function regexSafe(val) {
21739 return val.replace(/\$/g, '$$$$');
21740 }
21741
21742 var handleFormat = function handleFormat(key) {
21743 if (key.indexOf(_this.formatSeparator) < 0) {
21744 return getPathWithDefaults(data, defaultData, key);
21745 }
21746
21747 var p = key.split(_this.formatSeparator);
21748 var k = p.shift().trim();
21749 var f = p.join(_this.formatSeparator).trim();
21750 return _this.format(
21751 getPathWithDefaults(data, defaultData, k),
21752 f,
21753 lng
21754 );
21755 };
21756
21757 this.resetRegExp();
21758 var missingInterpolationHandler =
21759 (options && options.missingInterpolationHandler) ||
21760 this.options.missingInterpolationHandler;
21761 replaces = 0; // unescape if has unescapePrefix/Suffix
21762
21763 /* eslint no-cond-assign: 0 */
21764
21765 while ((match = this.regexpUnescape.exec(str))) {
21766 value = handleFormat(match[1].trim());
21767
21768 if (value === undefined) {
21769 if (typeof missingInterpolationHandler === 'function') {
21770 var temp = missingInterpolationHandler(str, match, options);
21771 value = typeof temp === 'string' ? temp : '';
21772 } else {
21773 this.logger.warn(
21774 'missed to pass in variable '
21775 .concat(match[1], ' for interpolating ')
21776 .concat(str)
21777 );
21778 value = '';
21779 }
21780 } else if (typeof value !== 'string' && !this.useRawValueToEscape) {
21781 value = makeString(value);
21782 }
21783
21784 str = str.replace(match[0], regexSafe(value));
21785 this.regexpUnescape.lastIndex = 0;
21786 replaces++;
21787
21788 if (replaces >= this.maxReplaces) {
21789 break;
21790 }
21791 }
21792
21793 replaces = 0; // regular escape on demand
21794
21795 while ((match = this.regexp.exec(str))) {
21796 value = handleFormat(match[1].trim());
21797
21798 if (value === undefined) {
21799 if (typeof missingInterpolationHandler === 'function') {
21800 var _temp = missingInterpolationHandler(str, match, options);
21801
21802 value = typeof _temp === 'string' ? _temp : '';
21803 } else {
21804 this.logger.warn(
21805 'missed to pass in variable '
21806 .concat(match[1], ' for interpolating ')
21807 .concat(str)
21808 );
21809 value = '';
21810 }
21811 } else if (typeof value !== 'string' && !this.useRawValueToEscape) {
21812 value = makeString(value);
21813 }
21814
21815 value = this.escapeValue
21816 ? regexSafe(this.escape(value))
21817 : regexSafe(value);
21818 str = str.replace(match[0], value);
21819 this.regexp.lastIndex = 0;
21820 replaces++;
21821
21822 if (replaces >= this.maxReplaces) {
21823 break;
21824 }
21825 }
21826
21827 return str;
21828 }
21829 },
21830 {
21831 key: 'nest',
21832 value: function nest(str, fc) {
21833 var options =
21834 arguments.length > 2 && arguments[2] !== undefined
21835 ? arguments[2]
21836 : {};
21837 var match;
21838 var value;
21839
21840 var clonedOptions = _objectSpread({}, options);
21841
21842 clonedOptions.applyPostProcessor = false; // avoid post processing on nested lookup
21843
21844 delete clonedOptions.defaultValue; // assert we do not get a endless loop on interpolating defaultValue again and again
21845 // if value is something like "myKey": "lorem $(anotherKey, { "count": {{aValueInOptions}} })"
21846
21847 function handleHasOptions(key, inheritedOptions) {
21848 if (key.indexOf(',') < 0) return key;
21849 var p = key.split(',');
21850 key = p.shift();
21851 var optionsString = p.join(',');
21852 optionsString = this.interpolate(optionsString, clonedOptions);
21853 optionsString = optionsString.replace(/'/g, '"');
21854
21855 try {
21856 clonedOptions = JSON.parse(optionsString);
21857 if (inheritedOptions)
21858 clonedOptions = _objectSpread(
21859 {},
21860 inheritedOptions,
21861 clonedOptions
21862 );
21863 } catch (e) {
21864 this.logger.error(
21865 'failed parsing options string in nesting for key '.concat(key),
21866 e
21867 );
21868 } // assert we do not get a endless loop on interpolating defaultValue again and again
21869
21870 delete clonedOptions.defaultValue;
21871 return key;
21872 } // regular escape on demand
21873
21874 while ((match = this.nestingRegexp.exec(str))) {
21875 value = fc(
21876 handleHasOptions.call(this, match[1].trim(), clonedOptions),
21877 clonedOptions
21878 ); // is only the nesting key (key1 = '$(key2)') return the value without stringify
21879
21880 if (value && match[0] === str && typeof value !== 'string')
21881 return value; // no string to include or empty
21882
21883 if (typeof value !== 'string') value = makeString(value);
21884
21885 if (!value) {
21886 this.logger.warn(
21887 'missed to resolve '.concat(match[1], ' for nesting ').concat(str)
21888 );
21889 value = '';
21890 } // Nested keys should not be escaped by default #854
21891 // value = this.escapeValue ? regexSafe(utils.escape(value)) : regexSafe(value);
21892
21893 str = str.replace(match[0], value);
21894 this.regexp.lastIndex = 0;
21895 }
21896
21897 return str;
21898 }
21899 }
21900 ]);
21901
21902 return Interpolator;
21903 })();
21904
21905 function remove(arr, what) {
21906 var found = arr.indexOf(what);
21907
21908 while (found !== -1) {
21909 arr.splice(found, 1);
21910 found = arr.indexOf(what);
21911 }
21912 }
21913
21914 var Connector =
21915 /*#__PURE__*/
21916 (function(_EventEmitter) {
21917 _inherits(Connector, _EventEmitter);
21918
21919 function Connector(backend, store, services) {
21920 var _this;
21921
21922 var options =
21923 arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
21924
21925 _classCallCheck(this, Connector);
21926
21927 _this = _possibleConstructorReturn(
21928 this,
21929 _getPrototypeOf(Connector).call(this)
21930 );
21931 EventEmitter.call(_assertThisInitialized(_this)); // <=IE10 fix (unable to call parent constructor)
21932
21933 _this.backend = backend;
21934 _this.store = store;
21935 _this.services = services;
21936 _this.languageUtils = services.languageUtils;
21937 _this.options = options;
21938 _this.logger = baseLogger.create('backendConnector');
21939 _this.state = {};
21940 _this.queue = [];
21941
21942 if (_this.backend && _this.backend.init) {
21943 _this.backend.init(services, options.backend, options);
21944 }
21945
21946 return _this;
21947 }
21948
21949 _createClass(Connector, [
21950 {
21951 key: 'queueLoad',
21952 value: function queueLoad(languages, namespaces, options, callback) {
21953 var _this2 = this;
21954
21955 // find what needs to be loaded
21956 var toLoad = [];
21957 var pending = [];
21958 var toLoadLanguages = [];
21959 var toLoadNamespaces = [];
21960 languages.forEach(function(lng) {
21961 var hasAllNamespaces = true;
21962 namespaces.forEach(function(ns) {
21963 var name = ''.concat(lng, '|').concat(ns);
21964
21965 if (!options.reload && _this2.store.hasResourceBundle(lng, ns)) {
21966 _this2.state[name] = 2; // loaded
21967 } else if (_this2.state[name] < 0);
21968 else if (_this2.state[name] === 1) {
21969 if (pending.indexOf(name) < 0) pending.push(name);
21970 } else {
21971 _this2.state[name] = 1; // pending
21972
21973 hasAllNamespaces = false;
21974 if (pending.indexOf(name) < 0) pending.push(name);
21975 if (toLoad.indexOf(name) < 0) toLoad.push(name);
21976 if (toLoadNamespaces.indexOf(ns) < 0) toLoadNamespaces.push(ns);
21977 }
21978 });
21979 if (!hasAllNamespaces) toLoadLanguages.push(lng);
21980 });
21981
21982 if (toLoad.length || pending.length) {
21983 this.queue.push({
21984 pending: pending,
21985 loaded: {},
21986 errors: [],
21987 callback: callback
21988 });
21989 }
21990
21991 return {
21992 toLoad: toLoad,
21993 pending: pending,
21994 toLoadLanguages: toLoadLanguages,
21995 toLoadNamespaces: toLoadNamespaces
21996 };
21997 }
21998 },
21999 {
22000 key: 'loaded',
22001 value: function loaded(name, err, data) {
22002 var _name$split = name.split('|'),
22003 _name$split2 = _slicedToArray(_name$split, 2),
22004 lng = _name$split2[0],
22005 ns = _name$split2[1];
22006
22007 if (err) this.emit('failedLoading', lng, ns, err);
22008
22009 if (data) {
22010 this.store.addResourceBundle(lng, ns, data);
22011 } // set loaded
22012
22013 this.state[name] = err ? -1 : 2; // consolidated loading done in this run - only emit once for a loaded namespace
22014
22015 var loaded = {}; // callback if ready
22016
22017 this.queue.forEach(function(q) {
22018 pushPath(q.loaded, [lng], ns);
22019 remove(q.pending, name);
22020 if (err) q.errors.push(err);
22021
22022 if (q.pending.length === 0 && !q.done) {
22023 // only do once per loaded -> this.emit('loaded', q.loaded);
22024 Object.keys(q.loaded).forEach(function(l) {
22025 if (!loaded[l]) loaded[l] = [];
22026
22027 if (q.loaded[l].length) {
22028 q.loaded[l].forEach(function(ns) {
22029 if (loaded[l].indexOf(ns) < 0) loaded[l].push(ns);
22030 });
22031 }
22032 });
22033 /* eslint no-param-reassign: 0 */
22034
22035 q.done = true;
22036
22037 if (q.errors.length) {
22038 q.callback(q.errors);
22039 } else {
22040 q.callback();
22041 }
22042 }
22043 }); // emit consolidated loaded event
22044
22045 this.emit('loaded', loaded); // remove done load requests
22046
22047 this.queue = this.queue.filter(function(q) {
22048 return !q.done;
22049 });
22050 }
22051 },
22052 {
22053 key: 'read',
22054 value: function read(lng, ns, fcName) {
22055 var _this3 = this;
22056
22057 var tried =
22058 arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
22059 var wait =
22060 arguments.length > 4 && arguments[4] !== undefined
22061 ? arguments[4]
22062 : 250;
22063 var callback = arguments.length > 5 ? arguments[5] : undefined;
22064 if (!lng.length) return callback(null, {}); // noting to load
22065
22066 return this.backend[fcName](lng, ns, function(err, data) {
22067 if (
22068 err &&
22069 data &&
22070 /* = retryFlag */
22071 tried < 5
22072 ) {
22073 setTimeout(function() {
22074 _this3.read.call(
22075 _this3,
22076 lng,
22077 ns,
22078 fcName,
22079 tried + 1,
22080 wait * 2,
22081 callback
22082 );
22083 }, wait);
22084 return;
22085 }
22086
22087 callback(err, data);
22088 });
22089 }
22090 /* eslint consistent-return: 0 */
22091 },
22092 {
22093 key: 'prepareLoading',
22094 value: function prepareLoading(languages, namespaces) {
22095 var _this4 = this;
22096
22097 var options =
22098 arguments.length > 2 && arguments[2] !== undefined
22099 ? arguments[2]
22100 : {};
22101 var callback = arguments.length > 3 ? arguments[3] : undefined;
22102
22103 if (!this.backend) {
22104 this.logger.warn(
22105 'No backend was added via i18next.use. Will not load resources.'
22106 );
22107 return callback && callback();
22108 }
22109
22110 if (typeof languages === 'string')
22111 languages = this.languageUtils.toResolveHierarchy(languages);
22112 if (typeof namespaces === 'string') namespaces = [namespaces];
22113 var toLoad = this.queueLoad(languages, namespaces, options, callback);
22114
22115 if (!toLoad.toLoad.length) {
22116 if (!toLoad.pending.length) callback(); // nothing to load and no pendings...callback now
22117
22118 return null; // pendings will trigger callback
22119 }
22120
22121 toLoad.toLoad.forEach(function(name) {
22122 _this4.loadOne(name);
22123 });
22124 }
22125 },
22126 {
22127 key: 'load',
22128 value: function load(languages, namespaces, callback) {
22129 this.prepareLoading(languages, namespaces, {}, callback);
22130 }
22131 },
22132 {
22133 key: 'reload',
22134 value: function reload(languages, namespaces, callback) {
22135 this.prepareLoading(
22136 languages,
22137 namespaces,
22138 {
22139 reload: true
22140 },
22141 callback
22142 );
22143 }
22144 },
22145 {
22146 key: 'loadOne',
22147 value: function loadOne(name) {
22148 var _this5 = this;
22149
22150 var prefix =
22151 arguments.length > 1 && arguments[1] !== undefined
22152 ? arguments[1]
22153 : '';
22154
22155 var _name$split3 = name.split('|'),
22156 _name$split4 = _slicedToArray(_name$split3, 2),
22157 lng = _name$split4[0],
22158 ns = _name$split4[1];
22159
22160 this.read(lng, ns, 'read', null, null, function(err, data) {
22161 if (err)
22162 _this5.logger.warn(
22163 ''
22164 .concat(prefix, 'loading namespace ')
22165 .concat(ns, ' for language ')
22166 .concat(lng, ' failed'),
22167 err
22168 );
22169 if (!err && data)
22170 _this5.logger.log(
22171 ''
22172 .concat(prefix, 'loaded namespace ')
22173 .concat(ns, ' for language ')
22174 .concat(lng),
22175 data
22176 );
22177
22178 _this5.loaded(name, err, data);
22179 });
22180 }
22181 },
22182 {
22183 key: 'saveMissing',
22184 value: function saveMissing(
22185 languages,
22186 namespace,
22187 key,
22188 fallbackValue,
22189 isUpdate
22190 ) {
22191 var options =
22192 arguments.length > 5 && arguments[5] !== undefined
22193 ? arguments[5]
22194 : {};
22195
22196 if (
22197 this.services.utils &&
22198 this.services.utils.hasLoadedNamespace &&
22199 !this.services.utils.hasLoadedNamespace(namespace)
22200 ) {
22201 this.logger.warn(
22202 'did not save key "'
22203 .concat(key, '" for namespace "')
22204 .concat(namespace, '" as the namespace was not yet loaded'),
22205 'This means something IS WRONG in your application setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!'
22206 );
22207 return;
22208 } // ignore non valid keys
22209
22210 if (key === undefined || key === null || key === '') return;
22211
22212 if (this.backend && this.backend.create) {
22213 this.backend.create(
22214 languages,
22215 namespace,
22216 key,
22217 fallbackValue,
22218 null,
22219 /* unused callback */
22220 _objectSpread({}, options, {
22221 isUpdate: isUpdate
22222 })
22223 );
22224 } // write to store to avoid resending
22225
22226 if (!languages || !languages[0]) return;
22227 this.store.addResource(languages[0], namespace, key, fallbackValue);
22228 }
22229 }
22230 ]);
22231
22232 return Connector;
22233 })(EventEmitter);
22234
22235 function get() {
22236 return {
22237 debug: false,
22238 initImmediate: true,
22239 ns: ['translation'],
22240 defaultNS: ['translation'],
22241 fallbackLng: ['dev'],
22242 fallbackNS: false,
22243 // string or array of namespaces
22244 whitelist: false,
22245 // array with whitelisted languages
22246 nonExplicitWhitelist: false,
22247 load: 'all',
22248 // | currentOnly | languageOnly
22249 preload: false,
22250 // array with preload languages
22251 simplifyPluralSuffix: true,
22252 keySeparator: '.',
22253 nsSeparator: ':',
22254 pluralSeparator: '_',
22255 contextSeparator: '_',
22256 partialBundledLanguages: false,
22257 // allow bundling certain languages that are not remotely fetched
22258 saveMissing: false,
22259 // enable to send missing values
22260 updateMissing: false,
22261 // enable to update default values if different from translated value (only useful on initial development, or when keeping code as source of truth)
22262 saveMissingTo: 'fallback',
22263 // 'current' || 'all'
22264 saveMissingPlurals: true,
22265 // will save all forms not only singular key
22266 missingKeyHandler: false,
22267 // function(lng, ns, key, fallbackValue) -> override if prefer on handling
22268 missingInterpolationHandler: false,
22269 // function(str, match)
22270 postProcess: false,
22271 // string or array of postProcessor names
22272 postProcessPassResolved: false,
22273 // pass resolved object into 'options.i18nResolved' for postprocessor
22274 returnNull: true,
22275 // allows null value as valid translation
22276 returnEmptyString: true,
22277 // allows empty string value as valid translation
22278 returnObjects: false,
22279 joinArrays: false,
22280 // or string to join array
22281 returnedObjectHandler: false,
22282 // function(key, value, options) triggered if key returns object but returnObjects is set to false
22283 parseMissingKeyHandler: false,
22284 // function(key) parsed a key that was not found in t() before returning
22285 appendNamespaceToMissingKey: false,
22286 appendNamespaceToCIMode: false,
22287 overloadTranslationOptionHandler: function handle(args) {
22288 var ret = {};
22289 if (_typeof(args[1]) === 'object') ret = args[1];
22290 if (typeof args[1] === 'string') ret.defaultValue = args[1];
22291 if (typeof args[2] === 'string') ret.tDescription = args[2];
22292
22293 if (_typeof(args[2]) === 'object' || _typeof(args[3]) === 'object') {
22294 var options = args[3] || args[2];
22295 Object.keys(options).forEach(function(key) {
22296 ret[key] = options[key];
22297 });
22298 }
22299
22300 return ret;
22301 },
22302 interpolation: {
22303 escapeValue: true,
22304 format: function format(value, _format, lng) {
22305 return value;
22306 },
22307 prefix: '{{',
22308 suffix: '}}',
22309 formatSeparator: ',',
22310 // prefixEscaped: '{{',
22311 // suffixEscaped: '}}',
22312 // unescapeSuffix: '',
22313 unescapePrefix: '-',
22314 nestingPrefix: '$t(',
22315 nestingSuffix: ')',
22316 // nestingPrefixEscaped: '$t(',
22317 // nestingSuffixEscaped: ')',
22318 // defaultVariables: undefined // object that can have values to interpolate on - extends passed in interpolation data
22319 maxReplaces: 1000 // max replaces to prevent endless loop
22320 }
22321 };
22322 }
22323 /* eslint no-param-reassign: 0 */
22324
22325 function transformOptions(options) {
22326 // create namespace object if namespace is passed in as string
22327 if (typeof options.ns === 'string') options.ns = [options.ns];
22328 if (typeof options.fallbackLng === 'string')
22329 options.fallbackLng = [options.fallbackLng];
22330 if (typeof options.fallbackNS === 'string')
22331 options.fallbackNS = [options.fallbackNS]; // extend whitelist with cimode
22332
22333 if (options.whitelist && options.whitelist.indexOf('cimode') < 0) {
22334 options.whitelist = options.whitelist.concat(['cimode']);
22335 }
22336
22337 return options;
22338 }
22339
22340 function noop() {}
22341
22342 var I18n =
22343 /*#__PURE__*/
22344 (function(_EventEmitter) {
22345 _inherits(I18n, _EventEmitter);
22346
22347 function I18n() {
22348 var _this;
22349
22350 var options =
22351 arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
22352 var callback = arguments.length > 1 ? arguments[1] : undefined;
22353
22354 _classCallCheck(this, I18n);
22355
22356 _this = _possibleConstructorReturn(this, _getPrototypeOf(I18n).call(this));
22357 EventEmitter.call(_assertThisInitialized(_this)); // <=IE10 fix (unable to call parent constructor)
22358
22359 _this.options = transformOptions(options);
22360 _this.services = {};
22361 _this.logger = baseLogger;
22362 _this.modules = {
22363 external: []
22364 };
22365
22366 if (callback && !_this.isInitialized && !options.isClone) {
22367 // https://github.com/i18next/i18next/issues/879
22368 if (!_this.options.initImmediate) {
22369 _this.init(options, callback);
22370
22371 return _possibleConstructorReturn(_this, _assertThisInitialized(_this));
22372 }
22373
22374 setTimeout(function() {
22375 _this.init(options, callback);
22376 }, 0);
22377 }
22378
22379 return _this;
22380 }
22381
22382 _createClass(I18n, [
22383 {
22384 key: 'init',
22385 value: function init() {
22386 var _this2 = this;
22387
22388 var options =
22389 arguments.length > 0 && arguments[0] !== undefined
22390 ? arguments[0]
22391 : {};
22392 var callback = arguments.length > 1 ? arguments[1] : undefined;
22393
22394 if (typeof options === 'function') {
22395 callback = options;
22396 options = {};
22397 }
22398
22399 this.options = _objectSpread(
22400 {},
22401 get(),
22402 this.options,
22403 transformOptions(options)
22404 );
22405 this.format = this.options.interpolation.format;
22406 if (!callback) callback = noop;
22407
22408 function createClassOnDemand(ClassOrObject) {
22409 if (!ClassOrObject) return null;
22410 if (typeof ClassOrObject === 'function') return new ClassOrObject();
22411 return ClassOrObject;
22412 } // init services
22413
22414 if (!this.options.isClone) {
22415 if (this.modules.logger) {
22416 baseLogger.init(
22417 createClassOnDemand(this.modules.logger),
22418 this.options
22419 );
22420 } else {
22421 baseLogger.init(null, this.options);
22422 }
22423
22424 var lu = new LanguageUtil(this.options);
22425 this.store = new ResourceStore(this.options.resources, this.options);
22426 var s = this.services;
22427 s.logger = baseLogger;
22428 s.resourceStore = this.store;
22429 s.languageUtils = lu;
22430 s.pluralResolver = new PluralResolver(lu, {
22431 prepend: this.options.pluralSeparator,
22432 compatibilityJSON: this.options.compatibilityJSON,
22433 simplifyPluralSuffix: this.options.simplifyPluralSuffix
22434 });
22435 s.interpolator = new Interpolator(this.options);
22436 s.utils = {
22437 hasLoadedNamespace: this.hasLoadedNamespace.bind(this)
22438 };
22439 s.backendConnector = new Connector(
22440 createClassOnDemand(this.modules.backend),
22441 s.resourceStore,
22442 s,
22443 this.options
22444 ); // pipe events from backendConnector
22445
22446 s.backendConnector.on('*', function(event) {
22447 for (
22448 var _len = arguments.length,
22449 args = new Array(_len > 1 ? _len - 1 : 0),
22450 _key = 1;
22451 _key < _len;
22452 _key++
22453 ) {
22454 args[_key - 1] = arguments[_key];
22455 }
22456
22457 _this2.emit.apply(_this2, [event].concat(args));
22458 });
22459
22460 if (this.modules.languageDetector) {
22461 s.languageDetector = createClassOnDemand(
22462 this.modules.languageDetector
22463 );
22464 s.languageDetector.init(s, this.options.detection, this.options);
22465 }
22466
22467 if (this.modules.i18nFormat) {
22468 s.i18nFormat = createClassOnDemand(this.modules.i18nFormat);
22469 if (s.i18nFormat.init) s.i18nFormat.init(this);
22470 }
22471
22472 this.translator = new Translator(this.services, this.options); // pipe events from translator
22473
22474 this.translator.on('*', function(event) {
22475 for (
22476 var _len2 = arguments.length,
22477 args = new Array(_len2 > 1 ? _len2 - 1 : 0),
22478 _key2 = 1;
22479 _key2 < _len2;
22480 _key2++
22481 ) {
22482 args[_key2 - 1] = arguments[_key2];
22483 }
22484
22485 _this2.emit.apply(_this2, [event].concat(args));
22486 });
22487 this.modules.external.forEach(function(m) {
22488 if (m.init) m.init(_this2);
22489 });
22490 } // append api
22491
22492 var storeApi = [
22493 'getResource',
22494 'addResource',
22495 'addResources',
22496 'addResourceBundle',
22497 'removeResourceBundle',
22498 'hasResourceBundle',
22499 'getResourceBundle',
22500 'getDataByLanguage'
22501 ];
22502 storeApi.forEach(function(fcName) {
22503 _this2[fcName] = function() {
22504 var _this2$store;
22505
22506 return (_this2$store = _this2.store)[fcName].apply(
22507 _this2$store,
22508 arguments
22509 );
22510 };
22511 });
22512 var deferred = defer();
22513
22514 var load = function load() {
22515 _this2.changeLanguage(_this2.options.lng, function(err, t) {
22516 _this2.isInitialized = true;
22517
22518 _this2.logger.log('initialized', _this2.options);
22519
22520 _this2.emit('initialized', _this2.options);
22521
22522 deferred.resolve(t); // not rejecting on err (as err is only a loading translation failed warning)
22523
22524 callback(err, t);
22525 });
22526 };
22527
22528 if (this.options.resources || !this.options.initImmediate) {
22529 load();
22530 } else {
22531 setTimeout(load, 0);
22532 }
22533
22534 return deferred;
22535 }
22536 /* eslint consistent-return: 0 */
22537 },
22538 {
22539 key: 'loadResources',
22540 value: function loadResources(language) {
22541 var _this3 = this;
22542
22543 var callback =
22544 arguments.length > 1 && arguments[1] !== undefined
22545 ? arguments[1]
22546 : noop;
22547 var usedCallback = callback;
22548 var usedLng = typeof language === 'string' ? language : this.language;
22549 if (typeof language === 'function') usedCallback = language;
22550
22551 if (!this.options.resources || this.options.partialBundledLanguages) {
22552 if (usedLng && usedLng.toLowerCase() === 'cimode')
22553 return usedCallback(); // avoid loading resources for cimode
22554
22555 var toLoad = [];
22556
22557 var append = function append(lng) {
22558 if (!lng) return;
22559
22560 var lngs = _this3.services.languageUtils.toResolveHierarchy(lng);
22561
22562 lngs.forEach(function(l) {
22563 if (toLoad.indexOf(l) < 0) toLoad.push(l);
22564 });
22565 };
22566
22567 if (!usedLng) {
22568 // at least load fallbacks in this case
22569 var fallbacks = this.services.languageUtils.getFallbackCodes(
22570 this.options.fallbackLng
22571 );
22572 fallbacks.forEach(function(l) {
22573 return append(l);
22574 });
22575 } else {
22576 append(usedLng);
22577 }
22578
22579 if (this.options.preload) {
22580 this.options.preload.forEach(function(l) {
22581 return append(l);
22582 });
22583 }
22584
22585 this.services.backendConnector.load(
22586 toLoad,
22587 this.options.ns,
22588 usedCallback
22589 );
22590 } else {
22591 usedCallback(null);
22592 }
22593 }
22594 },
22595 {
22596 key: 'reloadResources',
22597 value: function reloadResources(lngs, ns, callback) {
22598 var deferred = defer();
22599 if (!lngs) lngs = this.languages;
22600 if (!ns) ns = this.options.ns;
22601 if (!callback) callback = noop;
22602 this.services.backendConnector.reload(lngs, ns, function(err) {
22603 deferred.resolve(); // not rejecting on err (as err is only a loading translation failed warning)
22604
22605 callback(err);
22606 });
22607 return deferred;
22608 }
22609 },
22610 {
22611 key: 'use',
22612 value: function use(module) {
22613 if (module.type === 'backend') {
22614 this.modules.backend = module;
22615 }
22616
22617 if (
22618 module.type === 'logger' ||
22619 (module.log && module.warn && module.error)
22620 ) {
22621 this.modules.logger = module;
22622 }
22623
22624 if (module.type === 'languageDetector') {
22625 this.modules.languageDetector = module;
22626 }
22627
22628 if (module.type === 'i18nFormat') {
22629 this.modules.i18nFormat = module;
22630 }
22631
22632 if (module.type === 'postProcessor') {
22633 postProcessor.addPostProcessor(module);
22634 }
22635
22636 if (module.type === '3rdParty') {
22637 this.modules.external.push(module);
22638 }
22639
22640 return this;
22641 }
22642 },
22643 {
22644 key: 'changeLanguage',
22645 value: function changeLanguage(lng, callback) {
22646 var _this4 = this;
22647
22648 this.isLanguageChangingTo = lng;
22649 var deferred = defer();
22650 this.emit('languageChanging', lng);
22651
22652 var done = function done(err, l) {
22653 if (l) {
22654 _this4.language = l;
22655 _this4.languages = _this4.services.languageUtils.toResolveHierarchy(
22656 l
22657 );
22658
22659 _this4.translator.changeLanguage(l);
22660
22661 _this4.isLanguageChangingTo = undefined;
22662
22663 _this4.emit('languageChanged', l);
22664
22665 _this4.logger.log('languageChanged', l);
22666 } else {
22667 _this4.isLanguageChangingTo = undefined;
22668 }
22669
22670 deferred.resolve(function() {
22671 return _this4.t.apply(_this4, arguments);
22672 });
22673 if (callback)
22674 callback(err, function() {
22675 return _this4.t.apply(_this4, arguments);
22676 });
22677 };
22678
22679 var setLng = function setLng(l) {
22680 if (l) {
22681 if (!_this4.language) {
22682 _this4.language = l;
22683 _this4.languages = _this4.services.languageUtils.toResolveHierarchy(
22684 l
22685 );
22686 }
22687
22688 if (!_this4.translator.language)
22689 _this4.translator.changeLanguage(l);
22690 if (_this4.services.languageDetector)
22691 _this4.services.languageDetector.cacheUserLanguage(l);
22692 }
22693
22694 _this4.loadResources(l, function(err) {
22695 done(err, l);
22696 });
22697 };
22698
22699 if (
22700 !lng &&
22701 this.services.languageDetector &&
22702 !this.services.languageDetector.async
22703 ) {
22704 setLng(this.services.languageDetector.detect());
22705 } else if (
22706 !lng &&
22707 this.services.languageDetector &&
22708 this.services.languageDetector.async
22709 ) {
22710 this.services.languageDetector.detect(setLng);
22711 } else {
22712 setLng(lng);
22713 }
22714
22715 return deferred;
22716 }
22717 },
22718 {
22719 key: 'getFixedT',
22720 value: function getFixedT(lng, ns) {
22721 var _this5 = this;
22722
22723 var fixedT = function fixedT(key, opts) {
22724 var options;
22725
22726 if (_typeof(opts) !== 'object') {
22727 for (
22728 var _len3 = arguments.length,
22729 rest = new Array(_len3 > 2 ? _len3 - 2 : 0),
22730 _key3 = 2;
22731 _key3 < _len3;
22732 _key3++
22733 ) {
22734 rest[_key3 - 2] = arguments[_key3];
22735 }
22736
22737 options = _this5.options.overloadTranslationOptionHandler(
22738 [key, opts].concat(rest)
22739 );
22740 } else {
22741 options = _objectSpread({}, opts);
22742 }
22743
22744 options.lng = options.lng || fixedT.lng;
22745 options.lngs = options.lngs || fixedT.lngs;
22746 options.ns = options.ns || fixedT.ns;
22747 return _this5.t(key, options);
22748 };
22749
22750 if (typeof lng === 'string') {
22751 fixedT.lng = lng;
22752 } else {
22753 fixedT.lngs = lng;
22754 }
22755
22756 fixedT.ns = ns;
22757 return fixedT;
22758 }
22759 },
22760 {
22761 key: 't',
22762 value: function t() {
22763 var _this$translator;
22764
22765 return (
22766 this.translator &&
22767 (_this$translator = this.translator).translate.apply(
22768 _this$translator,
22769 arguments
22770 )
22771 );
22772 }
22773 },
22774 {
22775 key: 'exists',
22776 value: function exists() {
22777 var _this$translator2;
22778
22779 return (
22780 this.translator &&
22781 (_this$translator2 = this.translator).exists.apply(
22782 _this$translator2,
22783 arguments
22784 )
22785 );
22786 }
22787 },
22788 {
22789 key: 'setDefaultNamespace',
22790 value: function setDefaultNamespace(ns) {
22791 this.options.defaultNS = ns;
22792 }
22793 },
22794 {
22795 key: 'hasLoadedNamespace',
22796 value: function hasLoadedNamespace(ns) {
22797 var _this6 = this;
22798
22799 if (!this.isInitialized) {
22800 this.logger.warn(
22801 'hasLoadedNamespace: i18next was not initialized',
22802 this.languages
22803 );
22804 return false;
22805 }
22806
22807 if (!this.languages || !this.languages.length) {
22808 this.logger.warn(
22809 'hasLoadedNamespace: i18n.languages were undefined or empty',
22810 this.languages
22811 );
22812 return false;
22813 }
22814
22815 var lng = this.languages[0];
22816 var fallbackLng = this.options ? this.options.fallbackLng : false;
22817 var lastLng = this.languages[this.languages.length - 1]; // we're in cimode so this shall pass
22818
22819 if (lng.toLowerCase() === 'cimode') return true;
22820
22821 var loadNotPending = function loadNotPending(l, n) {
22822 var loadState =
22823 _this6.services.backendConnector.state[''.concat(l, '|').concat(n)];
22824
22825 return loadState === -1 || loadState === 2;
22826 }; // loaded -> SUCCESS
22827
22828 if (this.hasResourceBundle(lng, ns)) return true; // were not loading at all -> SEMI SUCCESS
22829
22830 if (!this.services.backendConnector.backend) return true; // failed loading ns - but at least fallback is not pending -> SEMI SUCCESS
22831
22832 if (
22833 loadNotPending(lng, ns) &&
22834 (!fallbackLng || loadNotPending(lastLng, ns))
22835 )
22836 return true;
22837 return false;
22838 }
22839 },
22840 {
22841 key: 'loadNamespaces',
22842 value: function loadNamespaces(ns, callback) {
22843 var _this7 = this;
22844
22845 var deferred = defer();
22846
22847 if (!this.options.ns) {
22848 callback && callback();
22849 return Promise.resolve();
22850 }
22851
22852 if (typeof ns === 'string') ns = [ns];
22853 ns.forEach(function(n) {
22854 if (_this7.options.ns.indexOf(n) < 0) _this7.options.ns.push(n);
22855 });
22856 this.loadResources(function(err) {
22857 deferred.resolve();
22858 if (callback) callback(err);
22859 });
22860 return deferred;
22861 }
22862 },
22863 {
22864 key: 'loadLanguages',
22865 value: function loadLanguages(lngs, callback) {
22866 var deferred = defer();
22867 if (typeof lngs === 'string') lngs = [lngs];
22868 var preloaded = this.options.preload || [];
22869 var newLngs = lngs.filter(function(lng) {
22870 return preloaded.indexOf(lng) < 0;
22871 }); // Exit early if all given languages are already preloaded
22872
22873 if (!newLngs.length) {
22874 if (callback) callback();
22875 return Promise.resolve();
22876 }
22877
22878 this.options.preload = preloaded.concat(newLngs);
22879 this.loadResources(function(err) {
22880 deferred.resolve();
22881 if (callback) callback(err);
22882 });
22883 return deferred;
22884 }
22885 },
22886 {
22887 key: 'dir',
22888 value: function dir(lng) {
22889 if (!lng)
22890 lng =
22891 this.languages && this.languages.length > 0
22892 ? this.languages[0]
22893 : this.language;
22894 if (!lng) return 'rtl';
22895 var rtlLngs = [
22896 'ar',
22897 'shu',
22898 'sqr',
22899 'ssh',
22900 'xaa',
22901 'yhd',
22902 'yud',
22903 'aao',
22904 'abh',
22905 'abv',
22906 'acm',
22907 'acq',
22908 'acw',
22909 'acx',
22910 'acy',
22911 'adf',
22912 'ads',
22913 'aeb',
22914 'aec',
22915 'afb',
22916 'ajp',
22917 'apc',
22918 'apd',
22919 'arb',
22920 'arq',
22921 'ars',
22922 'ary',
22923 'arz',
22924 'auz',
22925 'avl',
22926 'ayh',
22927 'ayl',
22928 'ayn',
22929 'ayp',
22930 'bbz',
22931 'pga',
22932 'he',
22933 'iw',
22934 'ps',
22935 'pbt',
22936 'pbu',
22937 'pst',
22938 'prp',
22939 'prd',
22940 'ur',
22941 'ydd',
22942 'yds',
22943 'yih',
22944 'ji',
22945 'yi',
22946 'hbo',
22947 'men',
22948 'xmn',
22949 'fa',
22950 'jpr',
22951 'peo',
22952 'pes',
22953 'prs',
22954 'dv',
22955 'sam'
22956 ];
22957 return rtlLngs.indexOf(
22958 this.services.languageUtils.getLanguagePartFromCode(lng)
22959 ) >= 0
22960 ? 'rtl'
22961 : 'ltr';
22962 }
22963 /* eslint class-methods-use-this: 0 */
22964 },
22965 {
22966 key: 'createInstance',
22967 value: function createInstance() {
22968 var options =
22969 arguments.length > 0 && arguments[0] !== undefined
22970 ? arguments[0]
22971 : {};
22972 var callback = arguments.length > 1 ? arguments[1] : undefined;
22973 return new I18n(options, callback);
22974 }
22975 },
22976 {
22977 key: 'cloneInstance',
22978 value: function cloneInstance() {
22979 var _this8 = this;
22980
22981 var options =
22982 arguments.length > 0 && arguments[0] !== undefined
22983 ? arguments[0]
22984 : {};
22985 var callback =
22986 arguments.length > 1 && arguments[1] !== undefined
22987 ? arguments[1]
22988 : noop;
22989
22990 var mergedOptions = _objectSpread({}, this.options, options, {
22991 isClone: true
22992 });
22993
22994 var clone = new I18n(mergedOptions);
22995 var membersToCopy = ['store', 'services', 'language'];
22996 membersToCopy.forEach(function(m) {
22997 clone[m] = _this8[m];
22998 });
22999 clone.translator = new Translator(clone.services, clone.options);
23000 clone.translator.on('*', function(event) {
23001 for (
23002 var _len4 = arguments.length,
23003 args = new Array(_len4 > 1 ? _len4 - 1 : 0),
23004 _key4 = 1;
23005 _key4 < _len4;
23006 _key4++
23007 ) {
23008 args[_key4 - 1] = arguments[_key4];
23009 }
23010
23011 clone.emit.apply(clone, [event].concat(args));
23012 });
23013 clone.init(mergedOptions, callback);
23014 clone.translator.options = clone.options; // sync options
23015
23016 return clone;
23017 }
23018 }
23019 ]);
23020
23021 return I18n;
23022 })(EventEmitter);
23023
23024 var i18next = new I18n();
23025
23026 module.exports = i18next;
23027 },
23028 {
23029 '@babel/runtime/helpers/assertThisInitialized': 4,
23030 '@babel/runtime/helpers/classCallCheck': 5,
23031 '@babel/runtime/helpers/createClass': 6,
23032 '@babel/runtime/helpers/getPrototypeOf': 8,
23033 '@babel/runtime/helpers/inherits': 9,
23034 '@babel/runtime/helpers/objectSpread': 14,
23035 '@babel/runtime/helpers/possibleConstructorReturn': 15,
23036 '@babel/runtime/helpers/slicedToArray': 17,
23037 '@babel/runtime/helpers/toConsumableArray': 18,
23038 '@babel/runtime/helpers/typeof': 19
23039 }
23040 ],
23041 31: [
23042 function(_dereq_, module, exports) {
23043 exports.read = function(buffer, offset, isLE, mLen, nBytes) {
23044 var e, m;
23045 var eLen = nBytes * 8 - mLen - 1;
23046 var eMax = (1 << eLen) - 1;
23047 var eBias = eMax >> 1;
23048 var nBits = -7;
23049 var i = isLE ? nBytes - 1 : 0;
23050 var d = isLE ? -1 : 1;
23051 var s = buffer[offset + i];
23052
23053 i += d;
23054
23055 e = s & ((1 << -nBits) - 1);
23056 s >>= -nBits;
23057 nBits += eLen;
23058 for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {}
23059
23060 m = e & ((1 << -nBits) - 1);
23061 e >>= -nBits;
23062 nBits += mLen;
23063 for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {}
23064
23065 if (e === 0) {
23066 e = 1 - eBias;
23067 } else if (e === eMax) {
23068 return m ? NaN : (s ? -1 : 1) * Infinity;
23069 } else {
23070 m = m + Math.pow(2, mLen);
23071 e = e - eBias;
23072 }
23073 return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
23074 };
23075
23076 exports.write = function(buffer, value, offset, isLE, mLen, nBytes) {
23077 var e, m, c;
23078 var eLen = nBytes * 8 - mLen - 1;
23079 var eMax = (1 << eLen) - 1;
23080 var eBias = eMax >> 1;
23081 var rt = mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0;
23082 var i = isLE ? 0 : nBytes - 1;
23083 var d = isLE ? 1 : -1;
23084 var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;
23085
23086 value = Math.abs(value);
23087
23088 if (isNaN(value) || value === Infinity) {
23089 m = isNaN(value) ? 1 : 0;
23090 e = eMax;
23091 } else {
23092 e = Math.floor(Math.log(value) / Math.LN2);
23093 if (value * (c = Math.pow(2, -e)) < 1) {
23094 e--;
23095 c *= 2;
23096 }
23097 if (e + eBias >= 1) {
23098 value += rt / c;
23099 } else {
23100 value += rt * Math.pow(2, 1 - eBias);
23101 }
23102 if (value * c >= 2) {
23103 e++;
23104 c /= 2;
23105 }
23106
23107 if (e + eBias >= eMax) {
23108 m = 0;
23109 e = eMax;
23110 } else if (e + eBias >= 1) {
23111 m = (value * c - 1) * Math.pow(2, mLen);
23112 e = e + eBias;
23113 } else {
23114 m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
23115 e = 0;
23116 }
23117 }
23118
23119 for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
23120
23121 e = (e << mLen) | m;
23122 eLen += mLen;
23123 for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
23124
23125 buffer[offset + i - d] |= s * 128;
23126 };
23127 },
23128 {}
23129 ],
23130 32: [
23131 function(_dereq_, module, exports) {
23132 /*
23133
23134 Copyright 2000, Silicon Graphics, Inc. All Rights Reserved.
23135 Copyright 2015, Google Inc. All Rights Reserved.
23136
23137 Permission is hereby granted, free of charge, to any person obtaining a copy
23138 of this software and associated documentation files (the "Software"), to
23139 deal in the Software without restriction, including without limitation the
23140 rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
23141 sell copies of the Software, and to permit persons to whom the Software is
23142 furnished to do so, subject to the following conditions:
23143
23144 The above copyright notice including the dates of first publication and
23145 either this permission notice or a reference to http://oss.sgi.com/projects/FreeB/
23146 shall be included in all copies or substantial portions of the Software.
23147
23148 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23149 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23150 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23151 SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23152 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
23153 IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23154
23155 Original Code. The Original Code is: OpenGL Sample Implementation,
23156 Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
23157 Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
23158 Copyright in any portions created by third parties is as indicated
23159 elsewhere herein. All Rights Reserved.
23160*/
23161 'use strict';
23162 var n;
23163 function t(a, b) {
23164 return a.b === b.b && a.a === b.a;
23165 }
23166 function u(a, b) {
23167 return a.b < b.b || (a.b === b.b && a.a <= b.a);
23168 }
23169 function v(a, b, c) {
23170 var d = b.b - a.b,
23171 e = c.b - b.b;
23172 return 0 < d + e
23173 ? d < e
23174 ? b.a - a.a + d / (d + e) * (a.a - c.a)
23175 : b.a - c.a + e / (d + e) * (c.a - a.a)
23176 : 0;
23177 }
23178 function x(a, b, c) {
23179 var d = b.b - a.b,
23180 e = c.b - b.b;
23181 return 0 < d + e ? (b.a - c.a) * d + (b.a - a.a) * e : 0;
23182 }
23183 function z(a, b) {
23184 return a.a < b.a || (a.a === b.a && a.b <= b.b);
23185 }
23186 function aa(a, b, c) {
23187 var d = b.a - a.a,
23188 e = c.a - b.a;
23189 return 0 < d + e
23190 ? d < e
23191 ? b.b - a.b + d / (d + e) * (a.b - c.b)
23192 : b.b - c.b + e / (d + e) * (c.b - a.b)
23193 : 0;
23194 }
23195 function ba(a, b, c) {
23196 var d = b.a - a.a,
23197 e = c.a - b.a;
23198 return 0 < d + e ? (b.b - c.b) * d + (b.b - a.b) * e : 0;
23199 }
23200 function ca(a) {
23201 return u(a.b.a, a.a);
23202 }
23203 function da(a) {
23204 return u(a.a, a.b.a);
23205 }
23206 function A(a, b, c, d) {
23207 a = 0 > a ? 0 : a;
23208 c = 0 > c ? 0 : c;
23209 return a <= c
23210 ? 0 === c ? (b + d) / 2 : b + a / (a + c) * (d - b)
23211 : d + c / (a + c) * (b - d);
23212 }
23213 function ea(a) {
23214 var b = B(a.b);
23215 C(b, a.c);
23216 C(b.b, a.c);
23217 D(b, a.a);
23218 return b;
23219 }
23220 function E(a, b) {
23221 var c = !1,
23222 d = !1;
23223 a !== b &&
23224 (b.a !== a.a && ((d = !0), F(b.a, a.a)),
23225 b.d !== a.d && ((c = !0), G(b.d, a.d)),
23226 H(b, a),
23227 d || (C(b, a.a), (a.a.c = a)),
23228 c || (D(b, a.d), (a.d.a = a)));
23229 }
23230 function I(a) {
23231 var b = a.b,
23232 c = !1;
23233 a.d !== a.b.d && ((c = !0), G(a.d, a.b.d));
23234 a.c === a
23235 ? F(a.a, null)
23236 : ((a.b.d.a = J(a)), (a.a.c = a.c), H(a, J(a)), c || D(a, a.d));
23237 b.c === b
23238 ? (F(b.a, null), G(b.d, null))
23239 : ((a.d.a = J(b)), (b.a.c = b.c), H(b, J(b)));
23240 fa(a);
23241 }
23242 function K(a) {
23243 var b = B(a),
23244 c = b.b;
23245 H(b, a.e);
23246 b.a = a.b.a;
23247 C(c, b.a);
23248 b.d = c.d = a.d;
23249 b = b.b;
23250 H(a.b, J(a.b));
23251 H(a.b, b);
23252 a.b.a = b.a;
23253 b.b.a.c = b.b;
23254 b.b.d = a.b.d;
23255 b.f = a.f;
23256 b.b.f = a.b.f;
23257 return b;
23258 }
23259 function L(a, b) {
23260 var c = !1,
23261 d = B(a),
23262 e = d.b;
23263 b.d !== a.d && ((c = !0), G(b.d, a.d));
23264 H(d, a.e);
23265 H(e, b);
23266 d.a = a.b.a;
23267 e.a = b.a;
23268 d.d = e.d = a.d;
23269 a.d.a = e;
23270 c || D(d, a.d);
23271 return d;
23272 }
23273 function B(a) {
23274 var b = new M(),
23275 c = new M(),
23276 d = a.b.h;
23277 c.h = d;
23278 d.b.h = b;
23279 b.h = a;
23280 a.b.h = c;
23281 b.b = c;
23282 b.c = b;
23283 b.e = c;
23284 c.b = b;
23285 c.c = c;
23286 return (c.e = b);
23287 }
23288 function H(a, b) {
23289 var c = a.c,
23290 d = b.c;
23291 c.b.e = b;
23292 d.b.e = a;
23293 a.c = d;
23294 b.c = c;
23295 }
23296 function C(a, b) {
23297 var c = b.f,
23298 d = new N(b, c);
23299 c.e = d;
23300 b.f = d;
23301 c = d.c = a;
23302 do (c.a = d), (c = c.c);
23303 while (c !== a);
23304 }
23305 function D(a, b) {
23306 var c = b.d,
23307 d = new ga(b, c);
23308 c.b = d;
23309 b.d = d;
23310 d.a = a;
23311 d.c = b.c;
23312 c = a;
23313 do (c.d = d), (c = c.e);
23314 while (c !== a);
23315 }
23316 function fa(a) {
23317 var b = a.h;
23318 a = a.b.h;
23319 b.b.h = a;
23320 a.b.h = b;
23321 }
23322 function F(a, b) {
23323 var c = a.c,
23324 d = c;
23325 do (d.a = b), (d = d.c);
23326 while (d !== c);
23327 c = a.f;
23328 d = a.e;
23329 d.f = c;
23330 c.e = d;
23331 }
23332 function G(a, b) {
23333 var c = a.a,
23334 d = c;
23335 do (d.d = b), (d = d.e);
23336 while (d !== c);
23337 c = a.d;
23338 d = a.b;
23339 d.d = c;
23340 c.b = d;
23341 }
23342 function ha(a) {
23343 var b = 0;
23344 Math.abs(a[1]) > Math.abs(a[0]) && (b = 1);
23345 Math.abs(a[2]) > Math.abs(a[b]) && (b = 2);
23346 return b;
23347 }
23348 var O = 4 * 1e150;
23349 function P(a, b) {
23350 a.f += b.f;
23351 a.b.f += b.b.f;
23352 }
23353 function ia(a, b, c) {
23354 a = a.a;
23355 b = b.a;
23356 c = c.a;
23357 if (b.b.a === a)
23358 return c.b.a === a
23359 ? u(b.a, c.a) ? 0 >= x(c.b.a, b.a, c.a) : 0 <= x(b.b.a, c.a, b.a)
23360 : 0 >= x(c.b.a, a, c.a);
23361 if (c.b.a === a) return 0 <= x(b.b.a, a, b.a);
23362 b = v(b.b.a, a, b.a);
23363 a = v(c.b.a, a, c.a);
23364 return b >= a;
23365 }
23366 function Q(a) {
23367 a.a.i = null;
23368 var b = a.e;
23369 b.a.c = b.c;
23370 b.c.a = b.a;
23371 a.e = null;
23372 }
23373 function ja(a, b) {
23374 I(a.a);
23375 a.c = !1;
23376 a.a = b;
23377 b.i = a;
23378 }
23379 function ka(a) {
23380 var b = a.a.a;
23381 do a = R(a);
23382 while (a.a.a === b);
23383 a.c && ((b = L(S(a).a.b, a.a.e)), ja(a, b), (a = R(a)));
23384 return a;
23385 }
23386 function la(a, b, c) {
23387 var d = new ma();
23388 d.a = c;
23389 d.e = na(a.f, b.e, d);
23390 return (c.i = d);
23391 }
23392 function oa(a, b) {
23393 switch (a.s) {
23394 case 100130:
23395 return 0 !== (b & 1);
23396 case 100131:
23397 return 0 !== b;
23398 case 100132:
23399 return 0 < b;
23400 case 100133:
23401 return 0 > b;
23402 case 100134:
23403 return 2 <= b || -2 >= b;
23404 }
23405 return !1;
23406 }
23407 function pa(a) {
23408 var b = a.a,
23409 c = b.d;
23410 c.c = a.d;
23411 c.a = b;
23412 Q(a);
23413 }
23414 function T(a, b, c) {
23415 a = b;
23416 for (b = b.a; a !== c; ) {
23417 a.c = !1;
23418 var d = S(a),
23419 e = d.a;
23420 if (e.a !== b.a) {
23421 if (!d.c) {
23422 pa(a);
23423 break;
23424 }
23425 e = L(b.c.b, e.b);
23426 ja(d, e);
23427 }
23428 b.c !== e && (E(J(e), e), E(b, e));
23429 pa(a);
23430 b = d.a;
23431 a = d;
23432 }
23433 return b;
23434 }
23435 function U(a, b, c, d, e, f) {
23436 var g = !0;
23437 do la(a, b, c.b), (c = c.c);
23438 while (c !== d);
23439 for (null === e && (e = S(b).a.b.c); ; ) {
23440 d = S(b);
23441 c = d.a.b;
23442 if (c.a !== e.a) break;
23443 c.c !== e && (E(J(c), c), E(J(e), c));
23444 d.f = b.f - c.f;
23445 d.d = oa(a, d.f);
23446 b.b = !0;
23447 !g && qa(a, b) && (P(c, e), Q(b), I(e));
23448 g = !1;
23449 b = d;
23450 e = c;
23451 }
23452 b.b = !0;
23453 f && ra(a, b);
23454 }
23455 function sa(a, b, c, d, e) {
23456 var f = [b.g[0], b.g[1], b.g[2]];
23457 b.d = null;
23458 b.d = a.o ? a.o(f, c, d, a.c) || null : null;
23459 null === b.d && (e ? a.n || (V(a, 100156), (a.n = !0)) : (b.d = c[0]));
23460 }
23461 function ta(a, b, c) {
23462 var d = [null, null, null, null];
23463 d[0] = b.a.d;
23464 d[1] = c.a.d;
23465 sa(a, b.a, d, [0.5, 0.5, 0, 0], !1);
23466 E(b, c);
23467 }
23468 function ua(a, b, c, d, e) {
23469 var f = Math.abs(b.b - a.b) + Math.abs(b.a - a.a),
23470 g = Math.abs(c.b - a.b) + Math.abs(c.a - a.a),
23471 h = e + 1;
23472 d[e] = 0.5 * g / (f + g);
23473 d[h] = 0.5 * f / (f + g);
23474 a.g[0] += d[e] * b.g[0] + d[h] * c.g[0];
23475 a.g[1] += d[e] * b.g[1] + d[h] * c.g[1];
23476 a.g[2] += d[e] * b.g[2] + d[h] * c.g[2];
23477 }
23478 function qa(a, b) {
23479 var c = S(b),
23480 d = b.a,
23481 e = c.a;
23482 if (u(d.a, e.a)) {
23483 if (0 < x(e.b.a, d.a, e.a)) return !1;
23484 if (!t(d.a, e.a)) K(e.b), E(d, J(e)), (b.b = c.b = !0);
23485 else if (d.a !== e.a) {
23486 var c = a.e,
23487 f = d.a.h;
23488 if (0 <= f) {
23489 var c = c.b,
23490 g = c.d,
23491 h = c.e,
23492 k = c.c,
23493 l = k[f];
23494 g[l] = g[c.a];
23495 k[g[l]] = l;
23496 l <= --c.a &&
23497 (1 >= l ? W(c, l) : u(h[g[l >> 1]], h[g[l]]) ? W(c, l) : va(c, l));
23498 h[f] = null;
23499 k[f] = c.b;
23500 c.b = f;
23501 } else
23502 for (c.c[-(f + 1)] = null; 0 < c.a && null === c.c[c.d[c.a - 1]]; ) --c.a;
23503 ta(a, J(e), d);
23504 }
23505 } else {
23506 if (0 > x(d.b.a, e.a, d.a)) return !1;
23507 R(b).b = b.b = !0;
23508 K(d.b);
23509 E(J(e), d);
23510 }
23511 return !0;
23512 }
23513 function wa(a, b) {
23514 var c = S(b),
23515 d = b.a,
23516 e = c.a,
23517 f = d.a,
23518 g = e.a,
23519 h = d.b.a,
23520 k = e.b.a,
23521 l = new N();
23522 x(h, a.a, f);
23523 x(k, a.a, g);
23524 if (f === g || Math.min(f.a, h.a) > Math.max(g.a, k.a)) return !1;
23525 if (u(f, g)) {
23526 if (0 < x(k, f, g)) return !1;
23527 } else if (0 > x(h, g, f)) return !1;
23528 var r = h,
23529 p = f,
23530 q = k,
23531 y = g,
23532 m,
23533 w;
23534 u(r, p) || ((m = r), (r = p), (p = m));
23535 u(q, y) || ((m = q), (q = y), (y = m));
23536 u(r, q) || ((m = r), (r = q), (q = m), (m = p), (p = y), (y = m));
23537 u(q, p)
23538 ? u(p, y)
23539 ? ((m = v(r, q, p)),
23540 (w = v(q, p, y)),
23541 0 > m + w && ((m = -m), (w = -w)),
23542 (l.b = A(m, q.b, w, p.b)))
23543 : ((m = x(r, q, p)),
23544 (w = -x(r, y, p)),
23545 0 > m + w && ((m = -m), (w = -w)),
23546 (l.b = A(m, q.b, w, y.b)))
23547 : (l.b = (q.b + p.b) / 2);
23548 z(r, p) || ((m = r), (r = p), (p = m));
23549 z(q, y) || ((m = q), (q = y), (y = m));
23550 z(r, q) || ((m = r), (r = q), (q = m), (m = p), (p = y), (y = m));
23551 z(q, p)
23552 ? z(p, y)
23553 ? ((m = aa(r, q, p)),
23554 (w = aa(q, p, y)),
23555 0 > m + w && ((m = -m), (w = -w)),
23556 (l.a = A(m, q.a, w, p.a)))
23557 : ((m = ba(r, q, p)),
23558 (w = -ba(r, y, p)),
23559 0 > m + w && ((m = -m), (w = -w)),
23560 (l.a = A(m, q.a, w, y.a)))
23561 : (l.a = (q.a + p.a) / 2);
23562 u(l, a.a) && ((l.b = a.a.b), (l.a = a.a.a));
23563 r = u(f, g) ? f : g;
23564 u(r, l) && ((l.b = r.b), (l.a = r.a));
23565 if (t(l, f) || t(l, g)) return qa(a, b), !1;
23566 if ((!t(h, a.a) && 0 <= x(h, a.a, l)) || (!t(k, a.a) && 0 >= x(k, a.a, l))) {
23567 if (k === a.a)
23568 return (
23569 K(d.b),
23570 E(e.b, d),
23571 (b = ka(b)),
23572 (d = S(b).a),
23573 T(a, S(b), c),
23574 U(a, b, J(d), d, d, !0),
23575 !0
23576 );
23577 if (h === a.a) {
23578 K(e.b);
23579 E(d.e, J(e));
23580 f = c = b;
23581 g = f.a.b.a;
23582 do f = R(f);
23583 while (f.a.b.a === g);
23584 b = f;
23585 f = S(b).a.b.c;
23586 c.a = J(e);
23587 e = T(a, c, null);
23588 U(a, b, e.c, d.b.c, f, !0);
23589 return !0;
23590 }
23591 0 <= x(h, a.a, l) &&
23592 ((R(b).b = b.b = !0), K(d.b), (d.a.b = a.a.b), (d.a.a = a.a.a));
23593 0 >= x(k, a.a, l) &&
23594 ((b.b = c.b = !0), K(e.b), (e.a.b = a.a.b), (e.a.a = a.a.a));
23595 return !1;
23596 }
23597 K(d.b);
23598 K(e.b);
23599 E(J(e), d);
23600 d.a.b = l.b;
23601 d.a.a = l.a;
23602 d.a.h = xa(a.e, d.a);
23603 d = d.a;
23604 e = [0, 0, 0, 0];
23605 l = [f.d, h.d, g.d, k.d];
23606 d.g[0] = d.g[1] = d.g[2] = 0;
23607 ua(d, f, h, e, 0);
23608 ua(d, g, k, e, 2);
23609 sa(a, d, l, e, !0);
23610 R(b).b = b.b = c.b = !0;
23611 return !1;
23612 }
23613 function ra(a, b) {
23614 for (var c = S(b); ; ) {
23615 for (; c.b; ) (b = c), (c = S(c));
23616 if (!b.b && ((c = b), (b = R(b)), null === b || !b.b)) break;
23617 b.b = !1;
23618 var d = b.a,
23619 e = c.a,
23620 f;
23621 if ((f = d.b.a !== e.b.a))
23622 a: {
23623 f = b;
23624 var g = S(f),
23625 h = f.a,
23626 k = g.a,
23627 l = void 0;
23628 if (u(h.b.a, k.b.a)) {
23629 if (0 > x(h.b.a, k.b.a, h.a)) {
23630 f = !1;
23631 break a;
23632 }
23633 R(f).b = f.b = !0;
23634 l = K(h);
23635 E(k.b, l);
23636 l.d.c = f.d;
23637 } else {
23638 if (0 < x(k.b.a, h.b.a, k.a)) {
23639 f = !1;
23640 break a;
23641 }
23642 f.b = g.b = !0;
23643 l = K(k);
23644 E(h.e, k.b);
23645 l.b.d.c = f.d;
23646 }
23647 f = !0;
23648 }
23649 f &&
23650 (c.c
23651 ? (Q(c), I(e), (c = S(b)), (e = c.a))
23652 : b.c && (Q(b), I(d), (b = R(c)), (d = b.a)));
23653 if (d.a !== e.a)
23654 if (d.b.a === e.b.a || b.c || c.c || (d.b.a !== a.a && e.b.a !== a.a))
23655 qa(a, b);
23656 else if (wa(a, b)) break;
23657 d.a === e.a && d.b.a === e.b.a && (P(e, d), Q(b), I(d), (b = R(c)));
23658 }
23659 }
23660 function ya(a, b) {
23661 a.a = b;
23662 for (var c = b.c; null === c.i; )
23663 if (((c = c.c), c === b.c)) {
23664 var c = a,
23665 d = b,
23666 e = new ma();
23667 e.a = d.c.b;
23668 var f = c.f,
23669 g = f.a;
23670 do g = g.a;
23671 while (null !== g.b && !f.c(f.b, e, g.b));
23672 var f = g.b,
23673 h = S(f),
23674 e = f.a,
23675 g = h.a;
23676 if (0 === x(e.b.a, d, e.a))
23677 (e = f.a),
23678 t(e.a, d) ||
23679 t(e.b.a, d) ||
23680 (K(e.b), f.c && (I(e.c), (f.c = !1)), E(d.c, e), ya(c, d));
23681 else {
23682 var k = u(g.b.a, e.b.a) ? f : h,
23683 h = void 0;
23684 f.d || k.c
23685 ? (k === f ? (h = L(d.c.b, e.e)) : (h = L(g.b.c.b, d.c).b),
23686 k.c
23687 ? ja(k, h)
23688 : ((e = c),
23689 (f = la(c, f, h)),
23690 (f.f = R(f).f + f.a.f),
23691 (f.d = oa(e, f.f))),
23692 ya(c, d))
23693 : U(c, f, d.c, d.c, null, !0);
23694 }
23695 return;
23696 }
23697 c = ka(c.i);
23698 e = S(c);
23699 f = e.a;
23700 e = T(a, e, null);
23701 if (e.c === f) {
23702 var f = e,
23703 e = f.c,
23704 g = S(c),
23705 h = c.a,
23706 k = g.a,
23707 l = !1;
23708 h.b.a !== k.b.a && wa(a, c);
23709 t(h.a, a.a) &&
23710 (E(J(e), h), (c = ka(c)), (e = S(c).a), T(a, S(c), g), (l = !0));
23711 t(k.a, a.a) && (E(f, J(k)), (f = T(a, g, null)), (l = !0));
23712 l
23713 ? U(a, c, f.c, e, e, !0)
23714 : (u(k.a, h.a) ? (d = J(k)) : (d = h),
23715 (d = L(f.c.b, d)),
23716 U(a, c, d, d.c, d.c, !1),
23717 (d.b.i.c = !0),
23718 ra(a, c));
23719 } else U(a, c, e.c, f, f, !0);
23720 }
23721 function za(a, b) {
23722 var c = new ma(),
23723 d = ea(a.b);
23724 d.a.b = O;
23725 d.a.a = b;
23726 d.b.a.b = -O;
23727 d.b.a.a = b;
23728 a.a = d.b.a;
23729 c.a = d;
23730 c.f = 0;
23731 c.d = !1;
23732 c.c = !1;
23733 c.h = !0;
23734 c.b = !1;
23735 d = a.f;
23736 d = na(d, d.a, c);
23737 c.e = d;
23738 }
23739 function Aa(a) {
23740 this.a = new Ba();
23741 this.b = a;
23742 this.c = ia;
23743 }
23744 function na(a, b, c) {
23745 do b = b.c;
23746 while (null !== b.b && !a.c(a.b, b.b, c));
23747 a = new Ba(c, b.a, b);
23748 b.a.c = a;
23749 return (b.a = a);
23750 }
23751 function Ba(a, b, c) {
23752 this.b = a || null;
23753 this.a = b || this;
23754 this.c = c || this;
23755 }
23756 function X() {
23757 this.d = Y;
23758 this.p = this.b = this.q = null;
23759 this.j = [0, 0, 0];
23760 this.s = 100130;
23761 this.n = !1;
23762 this.o = this.a = this.e = this.f = null;
23763 this.m = !1;
23764 this.c = this.r = this.i = this.k = this.l = this.h = null;
23765 }
23766 var Y = 0;
23767 n = X.prototype;
23768 n.x = function() {
23769 Z(this, Y);
23770 };
23771 n.B = function(a, b) {
23772 switch (a) {
23773 case 100142:
23774 return;
23775 case 100140:
23776 switch (b) {
23777 case 100130:
23778 case 100131:
23779 case 100132:
23780 case 100133:
23781 case 100134:
23782 this.s = b;
23783 return;
23784 }
23785 break;
23786 case 100141:
23787 this.m = !!b;
23788 return;
23789 default:
23790 V(this, 100900);
23791 return;
23792 }
23793 V(this, 100901);
23794 };
23795 n.y = function(a) {
23796 switch (a) {
23797 case 100142:
23798 return 0;
23799 case 100140:
23800 return this.s;
23801 case 100141:
23802 return this.m;
23803 default:
23804 V(this, 100900);
23805 }
23806 return !1;
23807 };
23808 n.A = function(a, b, c) {
23809 this.j[0] = a;
23810 this.j[1] = b;
23811 this.j[2] = c;
23812 };
23813 n.z = function(a, b) {
23814 var c = b ? b : null;
23815 switch (a) {
23816 case 100100:
23817 case 100106:
23818 this.h = c;
23819 break;
23820 case 100104:
23821 case 100110:
23822 this.l = c;
23823 break;
23824 case 100101:
23825 case 100107:
23826 this.k = c;
23827 break;
23828 case 100102:
23829 case 100108:
23830 this.i = c;
23831 break;
23832 case 100103:
23833 case 100109:
23834 this.p = c;
23835 break;
23836 case 100105:
23837 case 100111:
23838 this.o = c;
23839 break;
23840 case 100112:
23841 this.r = c;
23842 break;
23843 default:
23844 V(this, 100900);
23845 }
23846 };
23847 n.C = function(a, b) {
23848 var c = !1,
23849 d = [0, 0, 0];
23850 Z(this, 2);
23851 for (var e = 0; 3 > e; ++e) {
23852 var f = a[e];
23853 -1e150 > f && ((f = -1e150), (c = !0));
23854 1e150 < f && ((f = 1e150), (c = !0));
23855 d[e] = f;
23856 }
23857 c && V(this, 100155);
23858 c = this.q;
23859 null === c ? ((c = ea(this.b)), E(c, c.b)) : (K(c), (c = c.e));
23860 c.a.d = b;
23861 c.a.g[0] = d[0];
23862 c.a.g[1] = d[1];
23863 c.a.g[2] = d[2];
23864 c.f = 1;
23865 c.b.f = -1;
23866 this.q = c;
23867 };
23868 n.u = function(a) {
23869 Z(this, Y);
23870 this.d = 1;
23871 this.b = new Ca();
23872 this.c = a;
23873 };
23874 n.t = function() {
23875 Z(this, 1);
23876 this.d = 2;
23877 this.q = null;
23878 };
23879 n.v = function() {
23880 Z(this, 2);
23881 this.d = 1;
23882 };
23883 n.w = function() {
23884 Z(this, 1);
23885 this.d = Y;
23886 var a = this.j[0],
23887 b = this.j[1],
23888 c = this.j[2],
23889 d = !1,
23890 e = [a, b, c];
23891 if (0 === a && 0 === b && 0 === c) {
23892 for (
23893 var b = [-2 * 1e150, -2 * 1e150, -2 * 1e150],
23894 f = [2 * 1e150, 2 * 1e150, 2 * 1e150],
23895 c = [],
23896 g = [],
23897 d = this.b.c,
23898 a = d.e;
23899 a !== d;
23900 a = a.e
23901 )
23902 for (var h = 0; 3 > h; ++h) {
23903 var k = a.g[h];
23904 k < f[h] && ((f[h] = k), (g[h] = a));
23905 k > b[h] && ((b[h] = k), (c[h] = a));
23906 }
23907 a = 0;
23908 b[1] - f[1] > b[0] - f[0] && (a = 1);
23909 b[2] - f[2] > b[a] - f[a] && (a = 2);
23910 if (f[a] >= b[a]) (e[0] = 0), (e[1] = 0), (e[2] = 1);
23911 else {
23912 b = 0;
23913 f = g[a];
23914 c = c[a];
23915 g = [0, 0, 0];
23916 f = [f.g[0] - c.g[0], f.g[1] - c.g[1], f.g[2] - c.g[2]];
23917 h = [0, 0, 0];
23918 for (a = d.e; a !== d; a = a.e)
23919 (h[0] = a.g[0] - c.g[0]),
23920 (h[1] = a.g[1] - c.g[1]),
23921 (h[2] = a.g[2] - c.g[2]),
23922 (g[0] = f[1] * h[2] - f[2] * h[1]),
23923 (g[1] = f[2] * h[0] - f[0] * h[2]),
23924 (g[2] = f[0] * h[1] - f[1] * h[0]),
23925 (k = g[0] * g[0] + g[1] * g[1] + g[2] * g[2]),
23926 k > b && ((b = k), (e[0] = g[0]), (e[1] = g[1]), (e[2] = g[2]));
23927 0 >= b && ((e[0] = e[1] = e[2] = 0), (e[ha(f)] = 1));
23928 }
23929 d = !0;
23930 }
23931 g = ha(e);
23932 a = this.b.c;
23933 b = (g + 1) % 3;
23934 c = (g + 2) % 3;
23935 g = 0 < e[g] ? 1 : -1;
23936 for (e = a.e; e !== a; e = e.e) (e.b = e.g[b]), (e.a = g * e.g[c]);
23937 if (d) {
23938 e = 0;
23939 d = this.b.a;
23940 for (a = d.b; a !== d; a = a.b)
23941 if (((b = a.a), !(0 >= b.f))) {
23942 do (e += (b.a.b - b.b.a.b) * (b.a.a + b.b.a.a)), (b = b.e);
23943 while (b !== a.a);
23944 }
23945 if (0 > e) for (e = this.b.c, d = e.e; d !== e; d = d.e) d.a = -d.a;
23946 }
23947 this.n = !1;
23948 e = this.b.b;
23949 for (a = e.h; a !== e; a = d)
23950 if (
23951 ((d = a.h),
23952 (b = a.e),
23953 t(a.a, a.b.a) && a.e.e !== a && (ta(this, b, a), I(a), (a = b), (b = a.e)),
23954 b.e === a)
23955 ) {
23956 if (b !== a) {
23957 if (b === d || b === d.b) d = d.h;
23958 I(b);
23959 }
23960 if (a === d || a === d.b) d = d.h;
23961 I(a);
23962 }
23963 this.e = e = new Da();
23964 d = this.b.c;
23965 for (a = d.e; a !== d; a = a.e) a.h = xa(e, a);
23966 Ea(e);
23967 this.f = new Aa(this);
23968 za(this, -O);
23969 for (za(this, O); null !== (e = Fa(this.e)); ) {
23970 for (;;) {
23971 a: if (((a = this.e), 0 === a.a)) d = Ga(a.b);
23972 else if (
23973 ((d = a.c[a.d[a.a - 1]]), 0 !== a.b.a && ((a = Ga(a.b)), u(a, d)))
23974 ) {
23975 d = a;
23976 break a;
23977 }
23978 if (null === d || !t(d, e)) break;
23979 d = Fa(this.e);
23980 ta(this, e.c, d.c);
23981 }
23982 ya(this, e);
23983 }
23984 this.a = this.f.a.a.b.a.a;
23985 for (e = 0; null !== (d = this.f.a.a.b); ) d.h || ++e, Q(d);
23986 this.f = null;
23987 e = this.e;
23988 e.b = null;
23989 e.d = null;
23990 this.e = e.c = null;
23991 e = this.b;
23992 for (a = e.a.b; a !== e.a; a = d)
23993 (d = a.b), (a = a.a), a.e.e === a && (P(a.c, a), I(a));
23994 if (!this.n) {
23995 e = this.b;
23996 if (this.m)
23997 for (a = e.b.h; a !== e.b; a = d)
23998 (d = a.h), a.b.d.c !== a.d.c ? (a.f = a.d.c ? 1 : -1) : I(a);
23999 else
24000 for (a = e.a.b; a !== e.a; a = d)
24001 if (((d = a.b), a.c)) {
24002 for (a = a.a; u(a.b.a, a.a); a = a.c.b);
24003 for (; u(a.a, a.b.a); a = a.e);
24004 b = a.c.b;
24005 for (c = void 0; a.e !== b; )
24006 if (u(a.b.a, b.a)) {
24007 for (; b.e !== a && (ca(b.e) || 0 >= x(b.a, b.b.a, b.e.b.a)); )
24008 (c = L(b.e, b)), (b = c.b);
24009 b = b.c.b;
24010 } else {
24011 for (; b.e !== a && (da(a.c.b) || 0 <= x(a.b.a, a.a, a.c.b.a)); )
24012 (c = L(a, a.c.b)), (a = c.b);
24013 a = a.e;
24014 }
24015 for (; b.e.e !== a; ) (c = L(b.e, b)), (b = c.b);
24016 }
24017 if (this.h || this.i || this.k || this.l)
24018 if (this.m)
24019 for (e = this.b, d = e.a.b; d !== e.a; d = d.b) {
24020 if (d.c) {
24021 this.h && this.h(2, this.c);
24022 a = d.a;
24023 do this.k && this.k(a.a.d, this.c), (a = a.e);
24024 while (a !== d.a);
24025 this.i && this.i(this.c);
24026 }
24027 }
24028 else {
24029 e = this.b;
24030 d = !!this.l;
24031 a = !1;
24032 b = -1;
24033 for (c = e.a.d; c !== e.a; c = c.d)
24034 if (c.c) {
24035 a || (this.h && this.h(4, this.c), (a = !0));
24036 g = c.a;
24037 do
24038 d &&
24039 ((f = g.b.d.c ? 0 : 1),
24040 b !== f && ((b = f), this.l && this.l(!!b, this.c))),
24041 this.k && this.k(g.a.d, this.c),
24042 (g = g.e);
24043 while (g !== c.a);
24044 }
24045 a && this.i && this.i(this.c);
24046 }
24047 if (this.r) {
24048 e = this.b;
24049 for (a = e.a.b; a !== e.a; a = d)
24050 if (((d = a.b), !a.c)) {
24051 b = a.a;
24052 c = b.e;
24053 g = void 0;
24054 do
24055 (g = c),
24056 (c = g.e),
24057 (g.d = null),
24058 null === g.b.d &&
24059 (g.c === g ? F(g.a, null) : ((g.a.c = g.c), H(g, J(g))),
24060 (f = g.b),
24061 f.c === f ? F(f.a, null) : ((f.a.c = f.c), H(f, J(f))),
24062 fa(g));
24063 while (g !== b);
24064 b = a.d;
24065 a = a.b;
24066 a.d = b;
24067 b.b = a;
24068 }
24069 this.r(this.b);
24070 this.c = this.b = null;
24071 return;
24072 }
24073 }
24074 this.b = this.c = null;
24075 };
24076 function Z(a, b) {
24077 if (a.d !== b)
24078 for (; a.d !== b; )
24079 if (a.d < b)
24080 switch (a.d) {
24081 case Y:
24082 V(a, 100151);
24083 a.u(null);
24084 break;
24085 case 1:
24086 V(a, 100152), a.t();
24087 }
24088 else
24089 switch (a.d) {
24090 case 2:
24091 V(a, 100154);
24092 a.v();
24093 break;
24094 case 1:
24095 V(a, 100153), a.w();
24096 }
24097 }
24098 function V(a, b) {
24099 a.p && a.p(b, a.c);
24100 }
24101 function ga(a, b) {
24102 this.b = a || this;
24103 this.d = b || this;
24104 this.a = null;
24105 this.c = !1;
24106 }
24107 function M() {
24108 this.h = this;
24109 this.i = this.d = this.a = this.e = this.c = this.b = null;
24110 this.f = 0;
24111 }
24112 function J(a) {
24113 return a.b.e;
24114 }
24115 function Ca() {
24116 this.c = new N();
24117 this.a = new ga();
24118 this.b = new M();
24119 this.d = new M();
24120 this.b.b = this.d;
24121 this.d.b = this.b;
24122 }
24123 function N(a, b) {
24124 this.e = a || this;
24125 this.f = b || this;
24126 this.d = this.c = null;
24127 this.g = [0, 0, 0];
24128 this.h = this.a = this.b = 0;
24129 }
24130 function Da() {
24131 this.c = [];
24132 this.d = null;
24133 this.a = 0;
24134 this.e = !1;
24135 this.b = new Ha();
24136 }
24137 function Ea(a) {
24138 a.d = [];
24139 for (var b = 0; b < a.a; b++) a.d[b] = b;
24140 a.d.sort(
24141 (function(a) {
24142 return function(b, e) {
24143 return u(a[b], a[e]) ? 1 : -1;
24144 };
24145 })(a.c)
24146 );
24147 a.e = !0;
24148 Ia(a.b);
24149 }
24150 function xa(a, b) {
24151 if (a.e) {
24152 var c = a.b,
24153 d = ++c.a;
24154 2 * d > c.f && ((c.f *= 2), (c.c = Ja(c.c, c.f + 1)));
24155 var e;
24156 0 === c.b ? (e = d) : ((e = c.b), (c.b = c.c[c.b]));
24157 c.e[e] = b;
24158 c.c[e] = d;
24159 c.d[d] = e;
24160 c.h && va(c, d);
24161 return e;
24162 }
24163 c = a.a++;
24164 a.c[c] = b;
24165 return -(c + 1);
24166 }
24167 function Fa(a) {
24168 if (0 === a.a) return Ka(a.b);
24169 var b = a.c[a.d[a.a - 1]];
24170 if (0 !== a.b.a && u(Ga(a.b), b)) return Ka(a.b);
24171 do --a.a;
24172 while (0 < a.a && null === a.c[a.d[a.a - 1]]);
24173 return b;
24174 }
24175 function Ha() {
24176 this.d = Ja([0], 33);
24177 this.e = [null, null];
24178 this.c = [0, 0];
24179 this.a = 0;
24180 this.f = 32;
24181 this.b = 0;
24182 this.h = !1;
24183 this.d[1] = 1;
24184 }
24185 function Ja(a, b) {
24186 for (var c = Array(b), d = 0; d < a.length; d++) c[d] = a[d];
24187 for (; d < b; d++) c[d] = 0;
24188 return c;
24189 }
24190 function Ia(a) {
24191 for (var b = a.a; 1 <= b; --b) W(a, b);
24192 a.h = !0;
24193 }
24194 function Ga(a) {
24195 return a.e[a.d[1]];
24196 }
24197 function Ka(a) {
24198 var b = a.d,
24199 c = a.e,
24200 d = a.c,
24201 e = b[1],
24202 f = c[e];
24203 0 < a.a &&
24204 ((b[1] = b[a.a]),
24205 (d[b[1]] = 1),
24206 (c[e] = null),
24207 (d[e] = a.b),
24208 (a.b = e),
24209 0 < --a.a && W(a, 1));
24210 return f;
24211 }
24212 function W(a, b) {
24213 for (var c = a.d, d = a.e, e = a.c, f = b, g = c[f]; ; ) {
24214 var h = f << 1;
24215 h < a.a && u(d[c[h + 1]], d[c[h]]) && (h += 1);
24216 var k = c[h];
24217 if (h > a.a || u(d[g], d[k])) {
24218 c[f] = g;
24219 e[g] = f;
24220 break;
24221 }
24222 c[f] = k;
24223 e[k] = f;
24224 f = h;
24225 }
24226 }
24227 function va(a, b) {
24228 for (var c = a.d, d = a.e, e = a.c, f = b, g = c[f]; ; ) {
24229 var h = f >> 1,
24230 k = c[h];
24231 if (0 === h || u(d[k], d[g])) {
24232 c[f] = g;
24233 e[g] = f;
24234 break;
24235 }
24236 c[f] = k;
24237 e[k] = f;
24238 f = h;
24239 }
24240 }
24241 function ma() {
24242 this.e = this.a = null;
24243 this.f = 0;
24244 this.c = this.b = this.h = this.d = !1;
24245 }
24246 function S(a) {
24247 return a.e.c.b;
24248 }
24249 function R(a) {
24250 return a.e.a.b;
24251 }
24252 this.libtess = {
24253 GluTesselator: X,
24254 windingRule: {
24255 GLU_TESS_WINDING_ODD: 100130,
24256 GLU_TESS_WINDING_NONZERO: 100131,
24257 GLU_TESS_WINDING_POSITIVE: 100132,
24258 GLU_TESS_WINDING_NEGATIVE: 100133,
24259 GLU_TESS_WINDING_ABS_GEQ_TWO: 100134
24260 },
24261 primitiveType: {
24262 GL_LINE_LOOP: 2,
24263 GL_TRIANGLES: 4,
24264 GL_TRIANGLE_STRIP: 5,
24265 GL_TRIANGLE_FAN: 6
24266 },
24267 errorType: {
24268 GLU_TESS_MISSING_BEGIN_POLYGON: 100151,
24269 GLU_TESS_MISSING_END_POLYGON: 100153,
24270 GLU_TESS_MISSING_BEGIN_CONTOUR: 100152,
24271 GLU_TESS_MISSING_END_CONTOUR: 100154,
24272 GLU_TESS_COORD_TOO_LARGE: 100155,
24273 GLU_TESS_NEED_COMBINE_CALLBACK: 100156
24274 },
24275 gluEnum: {
24276 GLU_TESS_MESH: 100112,
24277 GLU_TESS_TOLERANCE: 100142,
24278 GLU_TESS_WINDING_RULE: 100140,
24279 GLU_TESS_BOUNDARY_ONLY: 100141,
24280 GLU_INVALID_ENUM: 100900,
24281 GLU_INVALID_VALUE: 100901,
24282 GLU_TESS_BEGIN: 100100,
24283 GLU_TESS_VERTEX: 100101,
24284 GLU_TESS_END: 100102,
24285 GLU_TESS_ERROR: 100103,
24286 GLU_TESS_EDGE_FLAG: 100104,
24287 GLU_TESS_COMBINE: 100105,
24288 GLU_TESS_BEGIN_DATA: 100106,
24289 GLU_TESS_VERTEX_DATA: 100107,
24290 GLU_TESS_END_DATA: 100108,
24291 GLU_TESS_ERROR_DATA: 100109,
24292 GLU_TESS_EDGE_FLAG_DATA: 100110,
24293 GLU_TESS_COMBINE_DATA: 100111
24294 }
24295 };
24296 X.prototype.gluDeleteTess = X.prototype.x;
24297 X.prototype.gluTessProperty = X.prototype.B;
24298 X.prototype.gluGetTessProperty = X.prototype.y;
24299 X.prototype.gluTessNormal = X.prototype.A;
24300 X.prototype.gluTessCallback = X.prototype.z;
24301 X.prototype.gluTessVertex = X.prototype.C;
24302 X.prototype.gluTessBeginPolygon = X.prototype.u;
24303 X.prototype.gluTessBeginContour = X.prototype.t;
24304 X.prototype.gluTessEndContour = X.prototype.v;
24305 X.prototype.gluTessEndPolygon = X.prototype.w;
24306 if (typeof module !== 'undefined') {
24307 module.exports = this.libtess;
24308 }
24309 },
24310 {}
24311 ],
24312 33: [
24313 function(_dereq_, module, exports) {
24314 // (c) Dean McNamee <dean@gmail.com>, 2013.
24315 //
24316 // https://github.com/deanm/omggif
24317 //
24318 // Permission is hereby granted, free of charge, to any person obtaining a copy
24319 // of this software and associated documentation files (the "Software"), to
24320 // deal in the Software without restriction, including without limitation the
24321 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
24322 // sell copies of the Software, and to permit persons to whom the Software is
24323 // furnished to do so, subject to the following conditions:
24324 //
24325 // The above copyright notice and this permission notice shall be included in
24326 // all copies or substantial portions of the Software.
24327 //
24328 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24329 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24330 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24331 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24332 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24333 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24334 // IN THE SOFTWARE.
24335 //
24336 // omggif is a JavaScript implementation of a GIF 89a encoder and decoder,
24337 // including animation and compression. It does not rely on any specific
24338 // underlying system, so should run in the browser, Node, or Plask.
24339
24340 'use strict';
24341
24342 function GifWriter(buf, width, height, gopts) {
24343 var p = 0;
24344
24345 var gopts = gopts === undefined ? {} : gopts;
24346 var loop_count = gopts.loop === undefined ? null : gopts.loop;
24347 var global_palette = gopts.palette === undefined ? null : gopts.palette;
24348
24349 if (width <= 0 || height <= 0 || width > 65535 || height > 65535)
24350 throw new Error('Width/Height invalid.');
24351
24352 function check_palette_and_num_colors(palette) {
24353 var num_colors = palette.length;
24354 if (num_colors < 2 || num_colors > 256 || num_colors & (num_colors - 1)) {
24355 throw new Error(
24356 'Invalid code/color length, must be power of 2 and 2 .. 256.'
24357 );
24358 }
24359 return num_colors;
24360 }
24361
24362 // - Header.
24363 buf[p++] = 0x47;
24364 buf[p++] = 0x49;
24365 buf[p++] = 0x46; // GIF
24366 buf[p++] = 0x38;
24367 buf[p++] = 0x39;
24368 buf[p++] = 0x61; // 89a
24369
24370 // Handling of Global Color Table (palette) and background index.
24371 var gp_num_colors_pow2 = 0;
24372 var background = 0;
24373 if (global_palette !== null) {
24374 var gp_num_colors = check_palette_and_num_colors(global_palette);
24375 while ((gp_num_colors >>= 1)) ++gp_num_colors_pow2;
24376 gp_num_colors = 1 << gp_num_colors_pow2;
24377 --gp_num_colors_pow2;
24378 if (gopts.background !== undefined) {
24379 background = gopts.background;
24380 if (background >= gp_num_colors)
24381 throw new Error('Background index out of range.');
24382 // The GIF spec states that a background index of 0 should be ignored, so
24383 // this is probably a mistake and you really want to set it to another
24384 // slot in the palette. But actually in the end most browsers, etc end
24385 // up ignoring this almost completely (including for dispose background).
24386 if (background === 0)
24387 throw new Error('Background index explicitly passed as 0.');
24388 }
24389 }
24390
24391 // - Logical Screen Descriptor.
24392 // NOTE(deanm): w/h apparently ignored by implementations, but set anyway.
24393 buf[p++] = width & 0xff;
24394 buf[p++] = (width >> 8) & 0xff;
24395 buf[p++] = height & 0xff;
24396 buf[p++] = (height >> 8) & 0xff;
24397 // NOTE: Indicates 0-bpp original color resolution (unused?).
24398 buf[p++] =
24399 (global_palette !== null ? 0x80 : 0) | gp_num_colors_pow2; // Global Color Table Flag. // NOTE: No sort flag (unused?).
24400 buf[p++] = background; // Background Color Index.
24401 buf[p++] = 0; // Pixel aspect ratio (unused?).
24402
24403 // - Global Color Table
24404 if (global_palette !== null) {
24405 for (var i = 0, il = global_palette.length; i < il; ++i) {
24406 var rgb = global_palette[i];
24407 buf[p++] = (rgb >> 16) & 0xff;
24408 buf[p++] = (rgb >> 8) & 0xff;
24409 buf[p++] = rgb & 0xff;
24410 }
24411 }
24412
24413 if (loop_count !== null) {
24414 // Netscape block for looping.
24415 if (loop_count < 0 || loop_count > 65535)
24416 throw new Error('Loop count invalid.');
24417 // Extension code, label, and length.
24418 buf[p++] = 0x21;
24419 buf[p++] = 0xff;
24420 buf[p++] = 0x0b;
24421 // NETSCAPE2.0
24422 buf[p++] = 0x4e;
24423 buf[p++] = 0x45;
24424 buf[p++] = 0x54;
24425 buf[p++] = 0x53;
24426 buf[p++] = 0x43;
24427 buf[p++] = 0x41;
24428 buf[p++] = 0x50;
24429 buf[p++] = 0x45;
24430 buf[p++] = 0x32;
24431 buf[p++] = 0x2e;
24432 buf[p++] = 0x30;
24433 // Sub-block
24434 buf[p++] = 0x03;
24435 buf[p++] = 0x01;
24436 buf[p++] = loop_count & 0xff;
24437 buf[p++] = (loop_count >> 8) & 0xff;
24438 buf[p++] = 0x00; // Terminator.
24439 }
24440
24441 var ended = false;
24442
24443 this.addFrame = function(x, y, w, h, indexed_pixels, opts) {
24444 if (ended === true) {
24445 --p;
24446 ended = false;
24447 } // Un-end.
24448
24449 opts = opts === undefined ? {} : opts;
24450
24451 // TODO(deanm): Bounds check x, y. Do they need to be within the virtual
24452 // canvas width/height, I imagine?
24453 if (x < 0 || y < 0 || x > 65535 || y > 65535) throw new Error('x/y invalid.');
24454
24455 if (w <= 0 || h <= 0 || w > 65535 || h > 65535)
24456 throw new Error('Width/Height invalid.');
24457
24458 if (indexed_pixels.length < w * h)
24459 throw new Error('Not enough pixels for the frame size.');
24460
24461 var using_local_palette = true;
24462 var palette = opts.palette;
24463 if (palette === undefined || palette === null) {
24464 using_local_palette = false;
24465 palette = global_palette;
24466 }
24467
24468 if (palette === undefined || palette === null)
24469 throw new Error('Must supply either a local or global palette.');
24470
24471 var num_colors = check_palette_and_num_colors(palette);
24472
24473 // Compute the min_code_size (power of 2), destroying num_colors.
24474 var min_code_size = 0;
24475 while ((num_colors >>= 1)) ++min_code_size;
24476 num_colors = 1 << min_code_size; // Now we can easily get it back.
24477
24478 var delay = opts.delay === undefined ? 0 : opts.delay;
24479
24480 // From the spec:
24481 // 0 - No disposal specified. The decoder is
24482 // not required to take any action.
24483 // 1 - Do not dispose. The graphic is to be left
24484 // in place.
24485 // 2 - Restore to background color. The area used by the
24486 // graphic must be restored to the background color.
24487 // 3 - Restore to previous. The decoder is required to
24488 // restore the area overwritten by the graphic with
24489 // what was there prior to rendering the graphic.
24490 // 4-7 - To be defined.
24491 // NOTE(deanm): Dispose background doesn't really work, apparently most
24492 // browsers ignore the background palette index and clear to transparency.
24493 var disposal = opts.disposal === undefined ? 0 : opts.disposal;
24494 if (disposal < 0 || disposal > 3)
24495 // 4-7 is reserved.
24496 throw new Error('Disposal out of range.');
24497
24498 var use_transparency = false;
24499 var transparent_index = 0;
24500 if (opts.transparent !== undefined && opts.transparent !== null) {
24501 use_transparency = true;
24502 transparent_index = opts.transparent;
24503 if (transparent_index < 0 || transparent_index >= num_colors)
24504 throw new Error('Transparent color index.');
24505 }
24506
24507 if (disposal !== 0 || use_transparency || delay !== 0) {
24508 // - Graphics Control Extension
24509 buf[p++] = 0x21;
24510 buf[p++] = 0xf9; // Extension / Label.
24511 buf[p++] = 4; // Byte size.
24512
24513 buf[p++] = (disposal << 2) | (use_transparency === true ? 1 : 0);
24514 buf[p++] = delay & 0xff;
24515 buf[p++] = (delay >> 8) & 0xff;
24516 buf[p++] = transparent_index; // Transparent color index.
24517 buf[p++] = 0; // Block Terminator.
24518 }
24519
24520 // - Image Descriptor
24521 buf[p++] = 0x2c; // Image Seperator.
24522 buf[p++] = x & 0xff;
24523 buf[p++] = (x >> 8) & 0xff; // Left.
24524 buf[p++] = y & 0xff;
24525 buf[p++] = (y >> 8) & 0xff; // Top.
24526 buf[p++] = w & 0xff;
24527 buf[p++] = (w >> 8) & 0xff;
24528 buf[p++] = h & 0xff;
24529 buf[p++] = (h >> 8) & 0xff;
24530 // NOTE: No sort flag (unused?).
24531 // TODO(deanm): Support interlace.
24532 buf[p++] = using_local_palette === true ? 0x80 | (min_code_size - 1) : 0;
24533
24534 // - Local Color Table
24535 if (using_local_palette === true) {
24536 for (var i = 0, il = palette.length; i < il; ++i) {
24537 var rgb = palette[i];
24538 buf[p++] = (rgb >> 16) & 0xff;
24539 buf[p++] = (rgb >> 8) & 0xff;
24540 buf[p++] = rgb & 0xff;
24541 }
24542 }
24543
24544 p = GifWriterOutputLZWCodeStream(
24545 buf,
24546 p,
24547 min_code_size < 2 ? 2 : min_code_size,
24548 indexed_pixels
24549 );
24550
24551 return p;
24552 };
24553
24554 this.end = function() {
24555 if (ended === false) {
24556 buf[p++] = 0x3b; // Trailer.
24557 ended = true;
24558 }
24559 return p;
24560 };
24561
24562 this.getOutputBuffer = function() {
24563 return buf;
24564 };
24565 this.setOutputBuffer = function(v) {
24566 buf = v;
24567 };
24568 this.getOutputBufferPosition = function() {
24569 return p;
24570 };
24571 this.setOutputBufferPosition = function(v) {
24572 p = v;
24573 };
24574 }
24575
24576 // Main compression routine, palette indexes -> LZW code stream.
24577 // |index_stream| must have at least one entry.
24578 function GifWriterOutputLZWCodeStream(buf, p, min_code_size, index_stream) {
24579 buf[p++] = min_code_size;
24580 var cur_subblock = p++; // Pointing at the length field.
24581
24582 var clear_code = 1 << min_code_size;
24583 var code_mask = clear_code - 1;
24584 var eoi_code = clear_code + 1;
24585 var next_code = eoi_code + 1;
24586
24587 var cur_code_size = min_code_size + 1; // Number of bits per code.
24588 var cur_shift = 0;
24589 // We have at most 12-bit codes, so we should have to hold a max of 19
24590 // bits here (and then we would write out).
24591 var cur = 0;
24592
24593 function emit_bytes_to_buffer(bit_block_size) {
24594 while (cur_shift >= bit_block_size) {
24595 buf[p++] = cur & 0xff;
24596 cur >>= 8;
24597 cur_shift -= 8;
24598 if (p === cur_subblock + 256) {
24599 // Finished a subblock.
24600 buf[cur_subblock] = 255;
24601 cur_subblock = p++;
24602 }
24603 }
24604 }
24605
24606 function emit_code(c) {
24607 cur |= c << cur_shift;
24608 cur_shift += cur_code_size;
24609 emit_bytes_to_buffer(8);
24610 }
24611
24612 // I am not an expert on the topic, and I don't want to write a thesis.
24613 // However, it is good to outline here the basic algorithm and the few data
24614 // structures and optimizations here that make this implementation fast.
24615 // The basic idea behind LZW is to build a table of previously seen runs
24616 // addressed by a short id (herein called output code). All data is
24617 // referenced by a code, which represents one or more values from the
24618 // original input stream. All input bytes can be referenced as the same
24619 // value as an output code. So if you didn't want any compression, you
24620 // could more or less just output the original bytes as codes (there are
24621 // some details to this, but it is the idea). In order to achieve
24622 // compression, values greater then the input range (codes can be up to
24623 // 12-bit while input only 8-bit) represent a sequence of previously seen
24624 // inputs. The decompressor is able to build the same mapping while
24625 // decoding, so there is always a shared common knowledge between the
24626 // encoding and decoder, which is also important for "timing" aspects like
24627 // how to handle variable bit width code encoding.
24628 //
24629 // One obvious but very important consequence of the table system is there
24630 // is always a unique id (at most 12-bits) to map the runs. 'A' might be
24631 // 4, then 'AA' might be 10, 'AAA' 11, 'AAAA' 12, etc. This relationship
24632 // can be used for an effecient lookup strategy for the code mapping. We
24633 // need to know if a run has been seen before, and be able to map that run
24634 // to the output code. Since we start with known unique ids (input bytes),
24635 // and then from those build more unique ids (table entries), we can
24636 // continue this chain (almost like a linked list) to always have small
24637 // integer values that represent the current byte chains in the encoder.
24638 // This means instead of tracking the input bytes (AAAABCD) to know our
24639 // current state, we can track the table entry for AAAABC (it is guaranteed
24640 // to exist by the nature of the algorithm) and the next character D.
24641 // Therefor the tuple of (table_entry, byte) is guaranteed to also be
24642 // unique. This allows us to create a simple lookup key for mapping input
24643 // sequences to codes (table indices) without having to store or search
24644 // any of the code sequences. So if 'AAAA' has a table entry of 12, the
24645 // tuple of ('AAAA', K) for any input byte K will be unique, and can be our
24646 // key. This leads to a integer value at most 20-bits, which can always
24647 // fit in an SMI value and be used as a fast sparse array / object key.
24648
24649 // Output code for the current contents of the index buffer.
24650 var ib_code = index_stream[0] & code_mask; // Load first input index.
24651 var code_table = {}; // Key'd on our 20-bit "tuple".
24652
24653 emit_code(clear_code); // Spec says first code should be a clear code.
24654
24655 // First index already loaded, process the rest of the stream.
24656 for (var i = 1, il = index_stream.length; i < il; ++i) {
24657 var k = index_stream[i] & code_mask;
24658 var cur_key = (ib_code << 8) | k; // (prev, k) unique tuple.
24659 var cur_code = code_table[cur_key]; // buffer + k.
24660
24661 // Check if we have to create a new code table entry.
24662 if (cur_code === undefined) {
24663 // We don't have buffer + k.
24664 // Emit index buffer (without k).
24665 // This is an inline version of emit_code, because this is the core
24666 // writing routine of the compressor (and V8 cannot inline emit_code
24667 // because it is a closure here in a different context). Additionally
24668 // we can call emit_byte_to_buffer less often, because we can have
24669 // 30-bits (from our 31-bit signed SMI), and we know our codes will only
24670 // be 12-bits, so can safely have 18-bits there without overflow.
24671 // emit_code(ib_code);
24672 cur |= ib_code << cur_shift;
24673 cur_shift += cur_code_size;
24674 while (cur_shift >= 8) {
24675 buf[p++] = cur & 0xff;
24676 cur >>= 8;
24677 cur_shift -= 8;
24678 if (p === cur_subblock + 256) {
24679 // Finished a subblock.
24680 buf[cur_subblock] = 255;
24681 cur_subblock = p++;
24682 }
24683 }
24684
24685 if (next_code === 4096) {
24686 // Table full, need a clear.
24687 emit_code(clear_code);
24688 next_code = eoi_code + 1;
24689 cur_code_size = min_code_size + 1;
24690 code_table = {};
24691 } else {
24692 // Table not full, insert a new entry.
24693 // Increase our variable bit code sizes if necessary. This is a bit
24694 // tricky as it is based on "timing" between the encoding and
24695 // decoder. From the encoders perspective this should happen after
24696 // we've already emitted the index buffer and are about to create the
24697 // first table entry that would overflow our current code bit size.
24698 if (next_code >= 1 << cur_code_size) ++cur_code_size;
24699 code_table[cur_key] = next_code++; // Insert into code table.
24700 }
24701
24702 ib_code = k; // Index buffer to single input k.
24703 } else {
24704 ib_code = cur_code; // Index buffer to sequence in code table.
24705 }
24706 }
24707
24708 emit_code(ib_code); // There will still be something in the index buffer.
24709 emit_code(eoi_code); // End Of Information.
24710
24711 // Flush / finalize the sub-blocks stream to the buffer.
24712 emit_bytes_to_buffer(1);
24713
24714 // Finish the sub-blocks, writing out any unfinished lengths and
24715 // terminating with a sub-block of length 0. If we have already started
24716 // but not yet used a sub-block it can just become the terminator.
24717 if (cur_subblock + 1 === p) {
24718 // Started but unused.
24719 buf[cur_subblock] = 0;
24720 } else {
24721 // Started and used, write length and additional terminator block.
24722 buf[cur_subblock] = p - cur_subblock - 1;
24723 buf[p++] = 0;
24724 }
24725 return p;
24726 }
24727
24728 function GifReader(buf) {
24729 var p = 0;
24730
24731 // - Header (GIF87a or GIF89a).
24732 if (
24733 buf[p++] !== 0x47 ||
24734 buf[p++] !== 0x49 ||
24735 buf[p++] !== 0x46 ||
24736 buf[p++] !== 0x38 ||
24737 ((buf[p++] + 1) & 0xfd) !== 0x38 ||
24738 buf[p++] !== 0x61
24739 ) {
24740 throw new Error('Invalid GIF 87a/89a header.');
24741 }
24742
24743 // - Logical Screen Descriptor.
24744 var width = buf[p++] | (buf[p++] << 8);
24745 var height = buf[p++] | (buf[p++] << 8);
24746 var pf0 = buf[p++]; // <Packed Fields>.
24747 var global_palette_flag = pf0 >> 7;
24748 var num_global_colors_pow2 = pf0 & 0x7;
24749 var num_global_colors = 1 << (num_global_colors_pow2 + 1);
24750 var background = buf[p++];
24751 buf[p++]; // Pixel aspect ratio (unused?).
24752
24753 var global_palette_offset = null;
24754 var global_palette_size = null;
24755
24756 if (global_palette_flag) {
24757 global_palette_offset = p;
24758 global_palette_size = num_global_colors;
24759 p += num_global_colors * 3; // Seek past palette.
24760 }
24761
24762 var no_eof = true;
24763
24764 var frames = [];
24765
24766 var delay = 0;
24767 var transparent_index = null;
24768 var disposal = 0; // 0 - No disposal specified.
24769 var loop_count = null;
24770
24771 this.width = width;
24772 this.height = height;
24773
24774 while (no_eof && p < buf.length) {
24775 switch (buf[p++]) {
24776 case 0x21: // Graphics Control Extension Block
24777 switch (buf[p++]) {
24778 case 0xff: // Application specific block
24779 // Try if it's a Netscape block (with animation loop counter).
24780 if (
24781 buf[p] !== 0x0b || // 21 FF already read, check block size.
24782 // NETSCAPE2.0
24783 (buf[p + 1] == 0x4e &&
24784 buf[p + 2] == 0x45 &&
24785 buf[p + 3] == 0x54 &&
24786 buf[p + 4] == 0x53 &&
24787 buf[p + 5] == 0x43 &&
24788 buf[p + 6] == 0x41 &&
24789 buf[p + 7] == 0x50 &&
24790 buf[p + 8] == 0x45 &&
24791 buf[p + 9] == 0x32 &&
24792 buf[p + 10] == 0x2e &&
24793 buf[p + 11] == 0x30 &&
24794 // Sub-block
24795 buf[p + 12] == 0x03 &&
24796 buf[p + 13] == 0x01 &&
24797 buf[p + 16] == 0)
24798 ) {
24799 p += 14;
24800 loop_count = buf[p++] | (buf[p++] << 8);
24801 p++; // Skip terminator.
24802 } else {
24803 // We don't know what it is, just try to get past it.
24804 p += 12;
24805 while (true) {
24806 // Seek through subblocks.
24807 var block_size = buf[p++];
24808 // Bad block size (ex: undefined from an out of bounds read).
24809 if (!(block_size >= 0)) throw Error('Invalid block size');
24810 if (block_size === 0) break; // 0 size is terminator
24811 p += block_size;
24812 }
24813 }
24814 break;
24815
24816 case 0xf9: // Graphics Control Extension
24817 if (buf[p++] !== 0x4 || buf[p + 4] !== 0)
24818 throw new Error('Invalid graphics extension block.');
24819 var pf1 = buf[p++];
24820 delay = buf[p++] | (buf[p++] << 8);
24821 transparent_index = buf[p++];
24822 if ((pf1 & 1) === 0) transparent_index = null;
24823 disposal = (pf1 >> 2) & 0x7;
24824 p++; // Skip terminator.
24825 break;
24826
24827 case 0xfe: // Comment Extension.
24828 while (true) {
24829 // Seek through subblocks.
24830 var block_size = buf[p++];
24831 // Bad block size (ex: undefined from an out of bounds read).
24832 if (!(block_size >= 0)) throw Error('Invalid block size');
24833 if (block_size === 0) break; // 0 size is terminator
24834 // console.log(buf.slice(p, p+block_size).toString('ascii'));
24835 p += block_size;
24836 }
24837 break;
24838
24839 default:
24840 throw new Error(
24841 'Unknown graphic control label: 0x' + buf[p - 1].toString(16)
24842 );
24843 }
24844 break;
24845
24846 case 0x2c: // Image Descriptor.
24847 var x = buf[p++] | (buf[p++] << 8);
24848 var y = buf[p++] | (buf[p++] << 8);
24849 var w = buf[p++] | (buf[p++] << 8);
24850 var h = buf[p++] | (buf[p++] << 8);
24851 var pf2 = buf[p++];
24852 var local_palette_flag = pf2 >> 7;
24853 var interlace_flag = (pf2 >> 6) & 1;
24854 var num_local_colors_pow2 = pf2 & 0x7;
24855 var num_local_colors = 1 << (num_local_colors_pow2 + 1);
24856 var palette_offset = global_palette_offset;
24857 var palette_size = global_palette_size;
24858 var has_local_palette = false;
24859 if (local_palette_flag) {
24860 var has_local_palette = true;
24861 palette_offset = p; // Override with local palette.
24862 palette_size = num_local_colors;
24863 p += num_local_colors * 3; // Seek past palette.
24864 }
24865
24866 var data_offset = p;
24867
24868 p++; // codesize
24869 while (true) {
24870 var block_size = buf[p++];
24871 // Bad block size (ex: undefined from an out of bounds read).
24872 if (!(block_size >= 0)) throw Error('Invalid block size');
24873 if (block_size === 0) break; // 0 size is terminator
24874 p += block_size;
24875 }
24876
24877 frames.push({
24878 x: x,
24879 y: y,
24880 width: w,
24881 height: h,
24882 has_local_palette: has_local_palette,
24883 palette_offset: palette_offset,
24884 palette_size: palette_size,
24885 data_offset: data_offset,
24886 data_length: p - data_offset,
24887 transparent_index: transparent_index,
24888 interlaced: !!interlace_flag,
24889 delay: delay,
24890 disposal: disposal
24891 });
24892 break;
24893
24894 case 0x3b: // Trailer Marker (end of file).
24895 no_eof = false;
24896 break;
24897
24898 default:
24899 throw new Error('Unknown gif block: 0x' + buf[p - 1].toString(16));
24900 break;
24901 }
24902 }
24903
24904 this.numFrames = function() {
24905 return frames.length;
24906 };
24907
24908 this.loopCount = function() {
24909 return loop_count;
24910 };
24911
24912 this.frameInfo = function(frame_num) {
24913 if (frame_num < 0 || frame_num >= frames.length)
24914 throw new Error('Frame index out of range.');
24915 return frames[frame_num];
24916 };
24917
24918 this.decodeAndBlitFrameBGRA = function(frame_num, pixels) {
24919 var frame = this.frameInfo(frame_num);
24920 var num_pixels = frame.width * frame.height;
24921 var index_stream = new Uint8Array(num_pixels); // At most 8-bit indices.
24922 GifReaderLZWOutputIndexStream(
24923 buf,
24924 frame.data_offset,
24925 index_stream,
24926 num_pixels
24927 );
24928 var palette_offset = frame.palette_offset;
24929
24930 // NOTE(deanm): It seems to be much faster to compare index to 256 than
24931 // to === null. Not sure why, but CompareStub_EQ_STRICT shows up high in
24932 // the profile, not sure if it's related to using a Uint8Array.
24933 var trans = frame.transparent_index;
24934 if (trans === null) trans = 256;
24935
24936 // We are possibly just blitting to a portion of the entire frame.
24937 // That is a subrect within the framerect, so the additional pixels
24938 // must be skipped over after we finished a scanline.
24939 var framewidth = frame.width;
24940 var framestride = width - framewidth;
24941 var xleft = framewidth; // Number of subrect pixels left in scanline.
24942
24943 // Output indicies of the top left and bottom right corners of the subrect.
24944 var opbeg = (frame.y * width + frame.x) * 4;
24945 var opend = ((frame.y + frame.height) * width + frame.x) * 4;
24946 var op = opbeg;
24947
24948 var scanstride = framestride * 4;
24949
24950 // Use scanstride to skip past the rows when interlacing. This is skipping
24951 // 7 rows for the first two passes, then 3 then 1.
24952 if (frame.interlaced === true) {
24953 scanstride += width * 4 * 7; // Pass 1.
24954 }
24955
24956 var interlaceskip = 8; // Tracking the row interval in the current pass.
24957
24958 for (var i = 0, il = index_stream.length; i < il; ++i) {
24959 var index = index_stream[i];
24960
24961 if (xleft === 0) {
24962 // Beginning of new scan line
24963 op += scanstride;
24964 xleft = framewidth;
24965 if (op >= opend) {
24966 // Catch the wrap to switch passes when interlacing.
24967 scanstride = framestride * 4 + width * 4 * (interlaceskip - 1);
24968 // interlaceskip / 2 * 4 is interlaceskip << 1.
24969 op = opbeg + (framewidth + framestride) * (interlaceskip << 1);
24970 interlaceskip >>= 1;
24971 }
24972 }
24973
24974 if (index === trans) {
24975 op += 4;
24976 } else {
24977 var r = buf[palette_offset + index * 3];
24978 var g = buf[palette_offset + index * 3 + 1];
24979 var b = buf[palette_offset + index * 3 + 2];
24980 pixels[op++] = b;
24981 pixels[op++] = g;
24982 pixels[op++] = r;
24983 pixels[op++] = 255;
24984 }
24985 --xleft;
24986 }
24987 };
24988
24989 // I will go to copy and paste hell one day...
24990 this.decodeAndBlitFrameRGBA = function(frame_num, pixels) {
24991 var frame = this.frameInfo(frame_num);
24992 var num_pixels = frame.width * frame.height;
24993 var index_stream = new Uint8Array(num_pixels); // At most 8-bit indices.
24994 GifReaderLZWOutputIndexStream(
24995 buf,
24996 frame.data_offset,
24997 index_stream,
24998 num_pixels
24999 );
25000 var palette_offset = frame.palette_offset;
25001
25002 // NOTE(deanm): It seems to be much faster to compare index to 256 than
25003 // to === null. Not sure why, but CompareStub_EQ_STRICT shows up high in
25004 // the profile, not sure if it's related to using a Uint8Array.
25005 var trans = frame.transparent_index;
25006 if (trans === null) trans = 256;
25007
25008 // We are possibly just blitting to a portion of the entire frame.
25009 // That is a subrect within the framerect, so the additional pixels
25010 // must be skipped over after we finished a scanline.
25011 var framewidth = frame.width;
25012 var framestride = width - framewidth;
25013 var xleft = framewidth; // Number of subrect pixels left in scanline.
25014
25015 // Output indicies of the top left and bottom right corners of the subrect.
25016 var opbeg = (frame.y * width + frame.x) * 4;
25017 var opend = ((frame.y + frame.height) * width + frame.x) * 4;
25018 var op = opbeg;
25019
25020 var scanstride = framestride * 4;
25021
25022 // Use scanstride to skip past the rows when interlacing. This is skipping
25023 // 7 rows for the first two passes, then 3 then 1.
25024 if (frame.interlaced === true) {
25025 scanstride += width * 4 * 7; // Pass 1.
25026 }
25027
25028 var interlaceskip = 8; // Tracking the row interval in the current pass.
25029
25030 for (var i = 0, il = index_stream.length; i < il; ++i) {
25031 var index = index_stream[i];
25032
25033 if (xleft === 0) {
25034 // Beginning of new scan line
25035 op += scanstride;
25036 xleft = framewidth;
25037 if (op >= opend) {
25038 // Catch the wrap to switch passes when interlacing.
25039 scanstride = framestride * 4 + width * 4 * (interlaceskip - 1);
25040 // interlaceskip / 2 * 4 is interlaceskip << 1.
25041 op = opbeg + (framewidth + framestride) * (interlaceskip << 1);
25042 interlaceskip >>= 1;
25043 }
25044 }
25045
25046 if (index === trans) {
25047 op += 4;
25048 } else {
25049 var r = buf[palette_offset + index * 3];
25050 var g = buf[palette_offset + index * 3 + 1];
25051 var b = buf[palette_offset + index * 3 + 2];
25052 pixels[op++] = r;
25053 pixels[op++] = g;
25054 pixels[op++] = b;
25055 pixels[op++] = 255;
25056 }
25057 --xleft;
25058 }
25059 };
25060 }
25061
25062 function GifReaderLZWOutputIndexStream(code_stream, p, output, output_length) {
25063 var min_code_size = code_stream[p++];
25064
25065 var clear_code = 1 << min_code_size;
25066 var eoi_code = clear_code + 1;
25067 var next_code = eoi_code + 1;
25068
25069 var cur_code_size = min_code_size + 1; // Number of bits per code.
25070 // NOTE: This shares the same name as the encoder, but has a different
25071 // meaning here. Here this masks each code coming from the code stream.
25072 var code_mask = (1 << cur_code_size) - 1;
25073 var cur_shift = 0;
25074 var cur = 0;
25075
25076 var op = 0; // Output pointer.
25077
25078 var subblock_size = code_stream[p++];
25079
25080 // TODO(deanm): Would using a TypedArray be any faster? At least it would
25081 // solve the fast mode / backing store uncertainty.
25082 // var code_table = Array(4096);
25083 var code_table = new Int32Array(4096); // Can be signed, we only use 20 bits.
25084
25085 var prev_code = null; // Track code-1.
25086
25087 while (true) {
25088 // Read up to two bytes, making sure we always 12-bits for max sized code.
25089 while (cur_shift < 16) {
25090 if (subblock_size === 0) break; // No more data to be read.
25091
25092 cur |= code_stream[p++] << cur_shift;
25093 cur_shift += 8;
25094
25095 if (subblock_size === 1) {
25096 // Never let it get to 0 to hold logic above.
25097 subblock_size = code_stream[p++]; // Next subblock.
25098 } else {
25099 --subblock_size;
25100 }
25101 }
25102
25103 // TODO(deanm): We should never really get here, we should have received
25104 // and EOI.
25105 if (cur_shift < cur_code_size) break;
25106
25107 var code = cur & code_mask;
25108 cur >>= cur_code_size;
25109 cur_shift -= cur_code_size;
25110
25111 // TODO(deanm): Maybe should check that the first code was a clear code,
25112 // at least this is what you're supposed to do. But actually our encoder
25113 // now doesn't emit a clear code first anyway.
25114 if (code === clear_code) {
25115 // We don't actually have to clear the table. This could be a good idea
25116 // for greater error checking, but we don't really do any anyway. We
25117 // will just track it with next_code and overwrite old entries.
25118
25119 next_code = eoi_code + 1;
25120 cur_code_size = min_code_size + 1;
25121 code_mask = (1 << cur_code_size) - 1;
25122
25123 // Don't update prev_code ?
25124 prev_code = null;
25125 continue;
25126 } else if (code === eoi_code) {
25127 break;
25128 }
25129
25130 // We have a similar situation as the decoder, where we want to store
25131 // variable length entries (code table entries), but we want to do in a
25132 // faster manner than an array of arrays. The code below stores sort of a
25133 // linked list within the code table, and then "chases" through it to
25134 // construct the dictionary entries. When a new entry is created, just the
25135 // last byte is stored, and the rest (prefix) of the entry is only
25136 // referenced by its table entry. Then the code chases through the
25137 // prefixes until it reaches a single byte code. We have to chase twice,
25138 // first to compute the length, and then to actually copy the data to the
25139 // output (backwards, since we know the length). The alternative would be
25140 // storing something in an intermediate stack, but that doesn't make any
25141 // more sense. I implemented an approach where it also stored the length
25142 // in the code table, although it's a bit tricky because you run out of
25143 // bits (12 + 12 + 8), but I didn't measure much improvements (the table
25144 // entries are generally not the long). Even when I created benchmarks for
25145 // very long table entries the complexity did not seem worth it.
25146 // The code table stores the prefix entry in 12 bits and then the suffix
25147 // byte in 8 bits, so each entry is 20 bits.
25148
25149 var chase_code = code < next_code ? code : prev_code;
25150
25151 // Chase what we will output, either {CODE} or {CODE-1}.
25152 var chase_length = 0;
25153 var chase = chase_code;
25154 while (chase > clear_code) {
25155 chase = code_table[chase] >> 8;
25156 ++chase_length;
25157 }
25158
25159 var k = chase;
25160
25161 var op_end = op + chase_length + (chase_code !== code ? 1 : 0);
25162 if (op_end > output_length) {
25163 console.log('Warning, gif stream longer than expected.');
25164 return;
25165 }
25166
25167 // Already have the first byte from the chase, might as well write it fast.
25168 output[op++] = k;
25169
25170 op += chase_length;
25171 var b = op; // Track pointer, writing backwards.
25172
25173 if (chase_code !== code)
25174 // The case of emitting {CODE-1} + k.
25175 output[op++] = k;
25176
25177 chase = chase_code;
25178 while (chase_length--) {
25179 chase = code_table[chase];
25180 output[--b] = chase & 0xff; // Write backwards.
25181 chase >>= 8; // Pull down to the prefix code.
25182 }
25183
25184 if (prev_code !== null && next_code < 4096) {
25185 code_table[next_code++] = (prev_code << 8) | k;
25186 // TODO(deanm): Figure out this clearing vs code growth logic better. I
25187 // have an feeling that it should just happen somewhere else, for now it
25188 // is awkward between when we grow past the max and then hit a clear code.
25189 // For now just check if we hit the max 12-bits (then a clear code should
25190 // follow, also of course encoded in 12-bits).
25191 if (next_code >= code_mask + 1 && cur_code_size < 12) {
25192 ++cur_code_size;
25193 code_mask = (code_mask << 1) | 1;
25194 }
25195 }
25196
25197 prev_code = code;
25198 }
25199
25200 if (op !== output_length) {
25201 console.log('Warning, gif stream shorter than expected.');
25202 }
25203
25204 return output;
25205 }
25206
25207 // CommonJS.
25208 try {
25209 exports.GifWriter = GifWriter;
25210 exports.GifReader = GifReader;
25211 } catch (e) {}
25212 },
25213 {}
25214 ],
25215 34: [
25216 function(_dereq_, module, exports) {
25217 (function(Buffer) {
25218 /**
25219 * https://opentype.js.org v0.9.0 | (c) Frederik De Bleser and other contributors | MIT License | Uses tiny-inflate by Devon Govett and string.prototype.codepointat polyfill by Mathias Bynens
25220 */
25221
25222 (function(global, factory) {
25223 typeof exports === 'object' && typeof module !== 'undefined'
25224 ? factory(exports)
25225 : typeof define === 'function' && define.amd
25226 ? define(['exports'], factory)
25227 : factory((global.opentype = {}));
25228 })(this, function(exports) {
25229 'use strict';
25230
25231 /*! https://mths.be/codepointat v0.2.0 by @mathias */
25232 if (!String.prototype.codePointAt) {
25233 (function() {
25234 var defineProperty = (function() {
25235 // IE 8 only supports `Object.defineProperty` on DOM elements
25236 try {
25237 var object = {};
25238 var $defineProperty = Object.defineProperty;
25239 var result =
25240 $defineProperty(object, object, object) && $defineProperty;
25241 } catch (error) {}
25242 return result;
25243 })();
25244 var codePointAt = function(position) {
25245 if (this == null) {
25246 throw TypeError();
25247 }
25248 var string = String(this);
25249 var size = string.length;
25250 // `ToInteger`
25251 var index = position ? Number(position) : 0;
25252 if (index != index) {
25253 // better `isNaN`
25254 index = 0;
25255 }
25256 // Account for out-of-bounds indices:
25257 if (index < 0 || index >= size) {
25258 return undefined;
25259 }
25260 // Get the first code unit
25261 var first = string.charCodeAt(index);
25262 var second;
25263 if (
25264 // check if it’s the start of a surrogate pair
25265 first >= 0xd800 &&
25266 first <= 0xdbff && // high surrogate
25267 size > index + 1 // there is a next code unit
25268 ) {
25269 second = string.charCodeAt(index + 1);
25270 if (second >= 0xdc00 && second <= 0xdfff) {
25271 // low surrogate
25272 // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
25273 return (first - 0xd800) * 0x400 + second - 0xdc00 + 0x10000;
25274 }
25275 }
25276 return first;
25277 };
25278 if (defineProperty) {
25279 defineProperty(String.prototype, 'codePointAt', {
25280 value: codePointAt,
25281 configurable: true,
25282 writable: true
25283 });
25284 } else {
25285 String.prototype.codePointAt = codePointAt;
25286 }
25287 })();
25288 }
25289
25290 var TINF_OK = 0;
25291 var TINF_DATA_ERROR = -3;
25292
25293 function Tree() {
25294 this.table = new Uint16Array(16); /* table of code length counts */
25295 this.trans = new Uint16Array(288); /* code -> symbol translation table */
25296 }
25297
25298 function Data(source, dest) {
25299 this.source = source;
25300 this.sourceIndex = 0;
25301 this.tag = 0;
25302 this.bitcount = 0;
25303
25304 this.dest = dest;
25305 this.destLen = 0;
25306
25307 this.ltree = new Tree(); /* dynamic length/symbol tree */
25308 this.dtree = new Tree(); /* dynamic distance tree */
25309 }
25310
25311 /* --------------------------------------------------- *
25312 * -- uninitialized global data (static structures) -- *
25313 * --------------------------------------------------- */
25314
25315 var sltree = new Tree();
25316 var sdtree = new Tree();
25317
25318 /* extra bits and base tables for length codes */
25319 var length_bits = new Uint8Array(30);
25320 var length_base = new Uint16Array(30);
25321
25322 /* extra bits and base tables for distance codes */
25323 var dist_bits = new Uint8Array(30);
25324 var dist_base = new Uint16Array(30);
25325
25326 /* special ordering of code length codes */
25327 var clcidx = new Uint8Array([
25328 16,
25329 17,
25330 18,
25331 0,
25332 8,
25333 7,
25334 9,
25335 6,
25336 10,
25337 5,
25338 11,
25339 4,
25340 12,
25341 3,
25342 13,
25343 2,
25344 14,
25345 1,
25346 15
25347 ]);
25348
25349 /* used by tinf_decode_trees, avoids allocations every call */
25350 var code_tree = new Tree();
25351 var lengths = new Uint8Array(288 + 32);
25352
25353 /* ----------------------- *
25354 * -- utility functions -- *
25355 * ----------------------- */
25356
25357 /* build extra bits and base tables */
25358 function tinf_build_bits_base(bits, base, delta, first) {
25359 var i, sum;
25360
25361 /* build bits table */
25362 for (i = 0; i < delta; ++i) {
25363 bits[i] = 0;
25364 }
25365 for (i = 0; i < 30 - delta; ++i) {
25366 bits[i + delta] = (i / delta) | 0;
25367 }
25368
25369 /* build base table */
25370 for (sum = first, i = 0; i < 30; ++i) {
25371 base[i] = sum;
25372 sum += 1 << bits[i];
25373 }
25374 }
25375
25376 /* build the fixed huffman trees */
25377 function tinf_build_fixed_trees(lt, dt) {
25378 var i;
25379
25380 /* build fixed length tree */
25381 for (i = 0; i < 7; ++i) {
25382 lt.table[i] = 0;
25383 }
25384
25385 lt.table[7] = 24;
25386 lt.table[8] = 152;
25387 lt.table[9] = 112;
25388
25389 for (i = 0; i < 24; ++i) {
25390 lt.trans[i] = 256 + i;
25391 }
25392 for (i = 0; i < 144; ++i) {
25393 lt.trans[24 + i] = i;
25394 }
25395 for (i = 0; i < 8; ++i) {
25396 lt.trans[24 + 144 + i] = 280 + i;
25397 }
25398 for (i = 0; i < 112; ++i) {
25399 lt.trans[24 + 144 + 8 + i] = 144 + i;
25400 }
25401
25402 /* build fixed distance tree */
25403 for (i = 0; i < 5; ++i) {
25404 dt.table[i] = 0;
25405 }
25406
25407 dt.table[5] = 32;
25408
25409 for (i = 0; i < 32; ++i) {
25410 dt.trans[i] = i;
25411 }
25412 }
25413
25414 /* given an array of code lengths, build a tree */
25415 var offs = new Uint16Array(16);
25416
25417 function tinf_build_tree(t, lengths, off, num) {
25418 var i, sum;
25419
25420 /* clear code length count table */
25421 for (i = 0; i < 16; ++i) {
25422 t.table[i] = 0;
25423 }
25424
25425 /* scan symbol lengths, and sum code length counts */
25426 for (i = 0; i < num; ++i) {
25427 t.table[lengths[off + i]]++;
25428 }
25429
25430 t.table[0] = 0;
25431
25432 /* compute offset table for distribution sort */
25433 for (sum = 0, i = 0; i < 16; ++i) {
25434 offs[i] = sum;
25435 sum += t.table[i];
25436 }
25437
25438 /* create code->symbol translation table (symbols sorted by code) */
25439 for (i = 0; i < num; ++i) {
25440 if (lengths[off + i]) {
25441 t.trans[offs[lengths[off + i]]++] = i;
25442 }
25443 }
25444 }
25445
25446 /* ---------------------- *
25447 * -- decode functions -- *
25448 * ---------------------- */
25449
25450 /* get one bit from source stream */
25451 function tinf_getbit(d) {
25452 /* check if tag is empty */
25453 if (!d.bitcount--) {
25454 /* load next tag */
25455 d.tag = d.source[d.sourceIndex++];
25456 d.bitcount = 7;
25457 }
25458
25459 /* shift bit out of tag */
25460 var bit = d.tag & 1;
25461 d.tag >>>= 1;
25462
25463 return bit;
25464 }
25465
25466 /* read a num bit value from a stream and add base */
25467 function tinf_read_bits(d, num, base) {
25468 if (!num) {
25469 return base;
25470 }
25471
25472 while (d.bitcount < 24) {
25473 d.tag |= d.source[d.sourceIndex++] << d.bitcount;
25474 d.bitcount += 8;
25475 }
25476
25477 var val = d.tag & (0xffff >>> (16 - num));
25478 d.tag >>>= num;
25479 d.bitcount -= num;
25480 return val + base;
25481 }
25482
25483 /* given a data stream and a tree, decode a symbol */
25484 function tinf_decode_symbol(d, t) {
25485 while (d.bitcount < 24) {
25486 d.tag |= d.source[d.sourceIndex++] << d.bitcount;
25487 d.bitcount += 8;
25488 }
25489
25490 var sum = 0,
25491 cur = 0,
25492 len = 0;
25493 var tag = d.tag;
25494
25495 /* get more bits while code value is above sum */
25496 do {
25497 cur = 2 * cur + (tag & 1);
25498 tag >>>= 1;
25499 ++len;
25500
25501 sum += t.table[len];
25502 cur -= t.table[len];
25503 } while (cur >= 0);
25504
25505 d.tag = tag;
25506 d.bitcount -= len;
25507
25508 return t.trans[sum + cur];
25509 }
25510
25511 /* given a data stream, decode dynamic trees from it */
25512 function tinf_decode_trees(d, lt, dt) {
25513 var hlit, hdist, hclen;
25514 var i, num, length;
25515
25516 /* get 5 bits HLIT (257-286) */
25517 hlit = tinf_read_bits(d, 5, 257);
25518
25519 /* get 5 bits HDIST (1-32) */
25520 hdist = tinf_read_bits(d, 5, 1);
25521
25522 /* get 4 bits HCLEN (4-19) */
25523 hclen = tinf_read_bits(d, 4, 4);
25524
25525 for (i = 0; i < 19; ++i) {
25526 lengths[i] = 0;
25527 }
25528
25529 /* read code lengths for code length alphabet */
25530 for (i = 0; i < hclen; ++i) {
25531 /* get 3 bits code length (0-7) */
25532 var clen = tinf_read_bits(d, 3, 0);
25533 lengths[clcidx[i]] = clen;
25534 }
25535
25536 /* build code length tree */
25537 tinf_build_tree(code_tree, lengths, 0, 19);
25538
25539 /* decode code lengths for the dynamic trees */
25540 for (num = 0; num < hlit + hdist; ) {
25541 var sym = tinf_decode_symbol(d, code_tree);
25542
25543 switch (sym) {
25544 case 16:
25545 /* copy previous code length 3-6 times (read 2 bits) */
25546 var prev = lengths[num - 1];
25547 for (length = tinf_read_bits(d, 2, 3); length; --length) {
25548 lengths[num++] = prev;
25549 }
25550 break;
25551 case 17:
25552 /* repeat code length 0 for 3-10 times (read 3 bits) */
25553 for (length = tinf_read_bits(d, 3, 3); length; --length) {
25554 lengths[num++] = 0;
25555 }
25556 break;
25557 case 18:
25558 /* repeat code length 0 for 11-138 times (read 7 bits) */
25559 for (length = tinf_read_bits(d, 7, 11); length; --length) {
25560 lengths[num++] = 0;
25561 }
25562 break;
25563 default:
25564 /* values 0-15 represent the actual code lengths */
25565 lengths[num++] = sym;
25566 break;
25567 }
25568 }
25569
25570 /* build dynamic trees */
25571 tinf_build_tree(lt, lengths, 0, hlit);
25572 tinf_build_tree(dt, lengths, hlit, hdist);
25573 }
25574
25575 /* ----------------------------- *
25576 * -- block inflate functions -- *
25577 * ----------------------------- */
25578
25579 /* given a stream and two trees, inflate a block of data */
25580 function tinf_inflate_block_data(d, lt, dt) {
25581 while (1) {
25582 var sym = tinf_decode_symbol(d, lt);
25583
25584 /* check for end of block */
25585 if (sym === 256) {
25586 return TINF_OK;
25587 }
25588
25589 if (sym < 256) {
25590 d.dest[d.destLen++] = sym;
25591 } else {
25592 var length, dist, offs;
25593 var i;
25594
25595 sym -= 257;
25596
25597 /* possibly get more bits from length code */
25598 length = tinf_read_bits(d, length_bits[sym], length_base[sym]);
25599
25600 dist = tinf_decode_symbol(d, dt);
25601
25602 /* possibly get more bits from distance code */
25603 offs = d.destLen - tinf_read_bits(d, dist_bits[dist], dist_base[dist]);
25604
25605 /* copy match */
25606 for (i = offs; i < offs + length; ++i) {
25607 d.dest[d.destLen++] = d.dest[i];
25608 }
25609 }
25610 }
25611 }
25612
25613 /* inflate an uncompressed block of data */
25614 function tinf_inflate_uncompressed_block(d) {
25615 var length, invlength;
25616 var i;
25617
25618 /* unread from bitbuffer */
25619 while (d.bitcount > 8) {
25620 d.sourceIndex--;
25621 d.bitcount -= 8;
25622 }
25623
25624 /* get length */
25625 length = d.source[d.sourceIndex + 1];
25626 length = 256 * length + d.source[d.sourceIndex];
25627
25628 /* get one's complement of length */
25629 invlength = d.source[d.sourceIndex + 3];
25630 invlength = 256 * invlength + d.source[d.sourceIndex + 2];
25631
25632 /* check length */
25633 if (length !== (~invlength & 0x0000ffff)) {
25634 return TINF_DATA_ERROR;
25635 }
25636
25637 d.sourceIndex += 4;
25638
25639 /* copy block */
25640 for (i = length; i; --i) {
25641 d.dest[d.destLen++] = d.source[d.sourceIndex++];
25642 }
25643
25644 /* make sure we start next block on a byte boundary */
25645 d.bitcount = 0;
25646
25647 return TINF_OK;
25648 }
25649
25650 /* inflate stream from source to dest */
25651 function tinf_uncompress(source, dest) {
25652 var d = new Data(source, dest);
25653 var bfinal, btype, res;
25654
25655 do {
25656 /* read final block flag */
25657 bfinal = tinf_getbit(d);
25658
25659 /* read block type (2 bits) */
25660 btype = tinf_read_bits(d, 2, 0);
25661
25662 /* decompress block */
25663 switch (btype) {
25664 case 0:
25665 /* decompress uncompressed block */
25666 res = tinf_inflate_uncompressed_block(d);
25667 break;
25668 case 1:
25669 /* decompress block with fixed huffman trees */
25670 res = tinf_inflate_block_data(d, sltree, sdtree);
25671 break;
25672 case 2:
25673 /* decompress block with dynamic huffman trees */
25674 tinf_decode_trees(d, d.ltree, d.dtree);
25675 res = tinf_inflate_block_data(d, d.ltree, d.dtree);
25676 break;
25677 default:
25678 res = TINF_DATA_ERROR;
25679 }
25680
25681 if (res !== TINF_OK) {
25682 throw new Error('Data error');
25683 }
25684 } while (!bfinal);
25685
25686 if (d.destLen < d.dest.length) {
25687 if (typeof d.dest.slice === 'function') {
25688 return d.dest.slice(0, d.destLen);
25689 } else {
25690 return d.dest.subarray(0, d.destLen);
25691 }
25692 }
25693
25694 return d.dest;
25695 }
25696
25697 /* -------------------- *
25698 * -- initialization -- *
25699 * -------------------- */
25700
25701 /* build fixed huffman trees */
25702 tinf_build_fixed_trees(sltree, sdtree);
25703
25704 /* build extra bits and base tables */
25705 tinf_build_bits_base(length_bits, length_base, 4, 3);
25706 tinf_build_bits_base(dist_bits, dist_base, 2, 1);
25707
25708 /* fix a special case */
25709 length_bits[28] = 0;
25710 length_base[28] = 258;
25711
25712 var tinyInflate = tinf_uncompress;
25713
25714 // The Bounding Box object
25715
25716 function derive(v0, v1, v2, v3, t) {
25717 return (
25718 Math.pow(1 - t, 3) * v0 +
25719 3 * Math.pow(1 - t, 2) * t * v1 +
25720 3 * (1 - t) * Math.pow(t, 2) * v2 +
25721 Math.pow(t, 3) * v3
25722 );
25723 }
25724 /**
25725 * A bounding box is an enclosing box that describes the smallest measure within which all the points lie.
25726 * It is used to calculate the bounding box of a glyph or text path.
25727 *
25728 * On initialization, x1/y1/x2/y2 will be NaN. Check if the bounding box is empty using `isEmpty()`.
25729 *
25730 * @exports opentype.BoundingBox
25731 * @class
25732 * @constructor
25733 */
25734 function BoundingBox() {
25735 this.x1 = Number.NaN;
25736 this.y1 = Number.NaN;
25737 this.x2 = Number.NaN;
25738 this.y2 = Number.NaN;
25739 }
25740
25741 /**
25742 * Returns true if the bounding box is empty, that is, no points have been added to the box yet.
25743 */
25744 BoundingBox.prototype.isEmpty = function() {
25745 return isNaN(this.x1) || isNaN(this.y1) || isNaN(this.x2) || isNaN(this.y2);
25746 };
25747
25748 /**
25749 * Add the point to the bounding box.
25750 * The x1/y1/x2/y2 coordinates of the bounding box will now encompass the given point.
25751 * @param {number} x - The X coordinate of the point.
25752 * @param {number} y - The Y coordinate of the point.
25753 */
25754 BoundingBox.prototype.addPoint = function(x, y) {
25755 if (typeof x === 'number') {
25756 if (isNaN(this.x1) || isNaN(this.x2)) {
25757 this.x1 = x;
25758 this.x2 = x;
25759 }
25760 if (x < this.x1) {
25761 this.x1 = x;
25762 }
25763 if (x > this.x2) {
25764 this.x2 = x;
25765 }
25766 }
25767 if (typeof y === 'number') {
25768 if (isNaN(this.y1) || isNaN(this.y2)) {
25769 this.y1 = y;
25770 this.y2 = y;
25771 }
25772 if (y < this.y1) {
25773 this.y1 = y;
25774 }
25775 if (y > this.y2) {
25776 this.y2 = y;
25777 }
25778 }
25779 };
25780
25781 /**
25782 * Add a X coordinate to the bounding box.
25783 * This extends the bounding box to include the X coordinate.
25784 * This function is used internally inside of addBezier.
25785 * @param {number} x - The X coordinate of the point.
25786 */
25787 BoundingBox.prototype.addX = function(x) {
25788 this.addPoint(x, null);
25789 };
25790
25791 /**
25792 * Add a Y coordinate to the bounding box.
25793 * This extends the bounding box to include the Y coordinate.
25794 * This function is used internally inside of addBezier.
25795 * @param {number} y - The Y coordinate of the point.
25796 */
25797 BoundingBox.prototype.addY = function(y) {
25798 this.addPoint(null, y);
25799 };
25800
25801 /**
25802 * Add a Bézier curve to the bounding box.
25803 * This extends the bounding box to include the entire Bézier.
25804 * @param {number} x0 - The starting X coordinate.
25805 * @param {number} y0 - The starting Y coordinate.
25806 * @param {number} x1 - The X coordinate of the first control point.
25807 * @param {number} y1 - The Y coordinate of the first control point.
25808 * @param {number} x2 - The X coordinate of the second control point.
25809 * @param {number} y2 - The Y coordinate of the second control point.
25810 * @param {number} x - The ending X coordinate.
25811 * @param {number} y - The ending Y coordinate.
25812 */
25813 BoundingBox.prototype.addBezier = function(x0, y0, x1, y1, x2, y2, x, y) {
25814 var this$1 = this;
25815
25816 // This code is based on http://nishiohirokazu.blogspot.com/2009/06/how-to-calculate-bezier-curves-bounding.html
25817 // and https://github.com/icons8/svg-path-bounding-box
25818
25819 var p0 = [x0, y0];
25820 var p1 = [x1, y1];
25821 var p2 = [x2, y2];
25822 var p3 = [x, y];
25823
25824 this.addPoint(x0, y0);
25825 this.addPoint(x, y);
25826
25827 for (var i = 0; i <= 1; i++) {
25828 var b = 6 * p0[i] - 12 * p1[i] + 6 * p2[i];
25829 var a = -3 * p0[i] + 9 * p1[i] - 9 * p2[i] + 3 * p3[i];
25830 var c = 3 * p1[i] - 3 * p0[i];
25831
25832 if (a === 0) {
25833 if (b === 0) {
25834 continue;
25835 }
25836 var t = -c / b;
25837 if (0 < t && t < 1) {
25838 if (i === 0) {
25839 this$1.addX(derive(p0[i], p1[i], p2[i], p3[i], t));
25840 }
25841 if (i === 1) {
25842 this$1.addY(derive(p0[i], p1[i], p2[i], p3[i], t));
25843 }
25844 }
25845 continue;
25846 }
25847
25848 var b2ac = Math.pow(b, 2) - 4 * c * a;
25849 if (b2ac < 0) {
25850 continue;
25851 }
25852 var t1 = (-b + Math.sqrt(b2ac)) / (2 * a);
25853 if (0 < t1 && t1 < 1) {
25854 if (i === 0) {
25855 this$1.addX(derive(p0[i], p1[i], p2[i], p3[i], t1));
25856 }
25857 if (i === 1) {
25858 this$1.addY(derive(p0[i], p1[i], p2[i], p3[i], t1));
25859 }
25860 }
25861 var t2 = (-b - Math.sqrt(b2ac)) / (2 * a);
25862 if (0 < t2 && t2 < 1) {
25863 if (i === 0) {
25864 this$1.addX(derive(p0[i], p1[i], p2[i], p3[i], t2));
25865 }
25866 if (i === 1) {
25867 this$1.addY(derive(p0[i], p1[i], p2[i], p3[i], t2));
25868 }
25869 }
25870 }
25871 };
25872
25873 /**
25874 * Add a quadratic curve to the bounding box.
25875 * This extends the bounding box to include the entire quadratic curve.
25876 * @param {number} x0 - The starting X coordinate.
25877 * @param {number} y0 - The starting Y coordinate.
25878 * @param {number} x1 - The X coordinate of the control point.
25879 * @param {number} y1 - The Y coordinate of the control point.
25880 * @param {number} x - The ending X coordinate.
25881 * @param {number} y - The ending Y coordinate.
25882 */
25883 BoundingBox.prototype.addQuad = function(x0, y0, x1, y1, x, y) {
25884 var cp1x = x0 + 2 / 3 * (x1 - x0);
25885 var cp1y = y0 + 2 / 3 * (y1 - y0);
25886 var cp2x = cp1x + 1 / 3 * (x - x0);
25887 var cp2y = cp1y + 1 / 3 * (y - y0);
25888 this.addBezier(x0, y0, cp1x, cp1y, cp2x, cp2y, x, y);
25889 };
25890
25891 // Geometric objects
25892
25893 /**
25894 * A bézier path containing a set of path commands similar to a SVG path.
25895 * Paths can be drawn on a context using `draw`.
25896 * @exports opentype.Path
25897 * @class
25898 * @constructor
25899 */
25900 function Path() {
25901 this.commands = [];
25902 this.fill = 'black';
25903 this.stroke = null;
25904 this.strokeWidth = 1;
25905 }
25906
25907 /**
25908 * @param {number} x
25909 * @param {number} y
25910 */
25911 Path.prototype.moveTo = function(x, y) {
25912 this.commands.push({
25913 type: 'M',
25914 x: x,
25915 y: y
25916 });
25917 };
25918
25919 /**
25920 * @param {number} x
25921 * @param {number} y
25922 */
25923 Path.prototype.lineTo = function(x, y) {
25924 this.commands.push({
25925 type: 'L',
25926 x: x,
25927 y: y
25928 });
25929 };
25930
25931 /**
25932 * Draws cubic curve
25933 * @function
25934 * curveTo
25935 * @memberof opentype.Path.prototype
25936 * @param {number} x1 - x of control 1
25937 * @param {number} y1 - y of control 1
25938 * @param {number} x2 - x of control 2
25939 * @param {number} y2 - y of control 2
25940 * @param {number} x - x of path point
25941 * @param {number} y - y of path point
25942 */
25943
25944 /**
25945 * Draws cubic curve
25946 * @function
25947 * bezierCurveTo
25948 * @memberof opentype.Path.prototype
25949 * @param {number} x1 - x of control 1
25950 * @param {number} y1 - y of control 1
25951 * @param {number} x2 - x of control 2
25952 * @param {number} y2 - y of control 2
25953 * @param {number} x - x of path point
25954 * @param {number} y - y of path point
25955 * @see curveTo
25956 */
25957 Path.prototype.curveTo = Path.prototype.bezierCurveTo = function(
25958 x1,
25959 y1,
25960 x2,
25961 y2,
25962 x,
25963 y
25964 ) {
25965 this.commands.push({
25966 type: 'C',
25967 x1: x1,
25968 y1: y1,
25969 x2: x2,
25970 y2: y2,
25971 x: x,
25972 y: y
25973 });
25974 };
25975
25976 /**
25977 * Draws quadratic curve
25978 * @function
25979 * quadraticCurveTo
25980 * @memberof opentype.Path.prototype
25981 * @param {number} x1 - x of control
25982 * @param {number} y1 - y of control
25983 * @param {number} x - x of path point
25984 * @param {number} y - y of path point
25985 */
25986
25987 /**
25988 * Draws quadratic curve
25989 * @function
25990 * quadTo
25991 * @memberof opentype.Path.prototype
25992 * @param {number} x1 - x of control
25993 * @param {number} y1 - y of control
25994 * @param {number} x - x of path point
25995 * @param {number} y - y of path point
25996 */
25997 Path.prototype.quadTo = Path.prototype.quadraticCurveTo = function(
25998 x1,
25999 y1,
26000 x,
26001 y
26002 ) {
26003 this.commands.push({
26004 type: 'Q',
26005 x1: x1,
26006 y1: y1,
26007 x: x,
26008 y: y
26009 });
26010 };
26011
26012 /**
26013 * Closes the path
26014 * @function closePath
26015 * @memberof opentype.Path.prototype
26016 */
26017
26018 /**
26019 * Close the path
26020 * @function close
26021 * @memberof opentype.Path.prototype
26022 */
26023 Path.prototype.close = Path.prototype.closePath = function() {
26024 this.commands.push({
26025 type: 'Z'
26026 });
26027 };
26028
26029 /**
26030 * Add the given path or list of commands to the commands of this path.
26031 * @param {Array} pathOrCommands - another opentype.Path, an opentype.BoundingBox, or an array of commands.
26032 */
26033 Path.prototype.extend = function(pathOrCommands) {
26034 if (pathOrCommands.commands) {
26035 pathOrCommands = pathOrCommands.commands;
26036 } else if (pathOrCommands instanceof BoundingBox) {
26037 var box = pathOrCommands;
26038 this.moveTo(box.x1, box.y1);
26039 this.lineTo(box.x2, box.y1);
26040 this.lineTo(box.x2, box.y2);
26041 this.lineTo(box.x1, box.y2);
26042 this.close();
26043 return;
26044 }
26045
26046 Array.prototype.push.apply(this.commands, pathOrCommands);
26047 };
26048
26049 /**
26050 * Calculate the bounding box of the path.
26051 * @returns {opentype.BoundingBox}
26052 */
26053 Path.prototype.getBoundingBox = function() {
26054 var this$1 = this;
26055
26056 var box = new BoundingBox();
26057
26058 var startX = 0;
26059 var startY = 0;
26060 var prevX = 0;
26061 var prevY = 0;
26062 for (var i = 0; i < this.commands.length; i++) {
26063 var cmd = this$1.commands[i];
26064 switch (cmd.type) {
26065 case 'M':
26066 box.addPoint(cmd.x, cmd.y);
26067 startX = prevX = cmd.x;
26068 startY = prevY = cmd.y;
26069 break;
26070 case 'L':
26071 box.addPoint(cmd.x, cmd.y);
26072 prevX = cmd.x;
26073 prevY = cmd.y;
26074 break;
26075 case 'Q':
26076 box.addQuad(prevX, prevY, cmd.x1, cmd.y1, cmd.x, cmd.y);
26077 prevX = cmd.x;
26078 prevY = cmd.y;
26079 break;
26080 case 'C':
26081 box.addBezier(
26082 prevX,
26083 prevY,
26084 cmd.x1,
26085 cmd.y1,
26086 cmd.x2,
26087 cmd.y2,
26088 cmd.x,
26089 cmd.y
26090 );
26091 prevX = cmd.x;
26092 prevY = cmd.y;
26093 break;
26094 case 'Z':
26095 prevX = startX;
26096 prevY = startY;
26097 break;
26098 default:
26099 throw new Error('Unexpected path command ' + cmd.type);
26100 }
26101 }
26102 if (box.isEmpty()) {
26103 box.addPoint(0, 0);
26104 }
26105 return box;
26106 };
26107
26108 /**
26109 * Draw the path to a 2D context.
26110 * @param {CanvasRenderingContext2D} ctx - A 2D drawing context.
26111 */
26112 Path.prototype.draw = function(ctx) {
26113 var this$1 = this;
26114
26115 ctx.beginPath();
26116 for (var i = 0; i < this.commands.length; i += 1) {
26117 var cmd = this$1.commands[i];
26118 if (cmd.type === 'M') {
26119 ctx.moveTo(cmd.x, cmd.y);
26120 } else if (cmd.type === 'L') {
26121 ctx.lineTo(cmd.x, cmd.y);
26122 } else if (cmd.type === 'C') {
26123 ctx.bezierCurveTo(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y);
26124 } else if (cmd.type === 'Q') {
26125 ctx.quadraticCurveTo(cmd.x1, cmd.y1, cmd.x, cmd.y);
26126 } else if (cmd.type === 'Z') {
26127 ctx.closePath();
26128 }
26129 }
26130
26131 if (this.fill) {
26132 ctx.fillStyle = this.fill;
26133 ctx.fill();
26134 }
26135
26136 if (this.stroke) {
26137 ctx.strokeStyle = this.stroke;
26138 ctx.lineWidth = this.strokeWidth;
26139 ctx.stroke();
26140 }
26141 };
26142
26143 /**
26144 * Convert the Path to a string of path data instructions
26145 * See http://www.w3.org/TR/SVG/paths.html#PathData
26146 * @param {number} [decimalPlaces=2] - The amount of decimal places for floating-point values
26147 * @return {string}
26148 */
26149 Path.prototype.toPathData = function(decimalPlaces) {
26150 var this$1 = this;
26151
26152 decimalPlaces = decimalPlaces !== undefined ? decimalPlaces : 2;
26153
26154 function floatToString(v) {
26155 if (Math.round(v) === v) {
26156 return '' + Math.round(v);
26157 } else {
26158 return v.toFixed(decimalPlaces);
26159 }
26160 }
26161
26162 function packValues() {
26163 var arguments$1 = arguments;
26164
26165 var s = '';
26166 for (var i = 0; i < arguments.length; i += 1) {
26167 var v = arguments$1[i];
26168 if (v >= 0 && i > 0) {
26169 s += ' ';
26170 }
26171
26172 s += floatToString(v);
26173 }
26174
26175 return s;
26176 }
26177
26178 var d = '';
26179 for (var i = 0; i < this.commands.length; i += 1) {
26180 var cmd = this$1.commands[i];
26181 if (cmd.type === 'M') {
26182 d += 'M' + packValues(cmd.x, cmd.y);
26183 } else if (cmd.type === 'L') {
26184 d += 'L' + packValues(cmd.x, cmd.y);
26185 } else if (cmd.type === 'C') {
26186 d += 'C' + packValues(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y);
26187 } else if (cmd.type === 'Q') {
26188 d += 'Q' + packValues(cmd.x1, cmd.y1, cmd.x, cmd.y);
26189 } else if (cmd.type === 'Z') {
26190 d += 'Z';
26191 }
26192 }
26193
26194 return d;
26195 };
26196
26197 /**
26198 * Convert the path to an SVG <path> element, as a string.
26199 * @param {number} [decimalPlaces=2] - The amount of decimal places for floating-point values
26200 * @return {string}
26201 */
26202 Path.prototype.toSVG = function(decimalPlaces) {
26203 var svg = '<path d="';
26204 svg += this.toPathData(decimalPlaces);
26205 svg += '"';
26206 if (this.fill && this.fill !== 'black') {
26207 if (this.fill === null) {
26208 svg += ' fill="none"';
26209 } else {
26210 svg += ' fill="' + this.fill + '"';
26211 }
26212 }
26213
26214 if (this.stroke) {
26215 svg +=
26216 ' stroke="' + this.stroke + '" stroke-width="' + this.strokeWidth + '"';
26217 }
26218
26219 svg += '/>';
26220 return svg;
26221 };
26222
26223 /**
26224 * Convert the path to a DOM element.
26225 * @param {number} [decimalPlaces=2] - The amount of decimal places for floating-point values
26226 * @return {SVGPathElement}
26227 */
26228 Path.prototype.toDOMElement = function(decimalPlaces) {
26229 var temporaryPath = this.toPathData(decimalPlaces);
26230 var newPath = document.createElementNS(
26231 'http://www.w3.org/2000/svg',
26232 'path'
26233 );
26234
26235 newPath.setAttribute('d', temporaryPath);
26236
26237 return newPath;
26238 };
26239
26240 // Run-time checking of preconditions.
26241
26242 function fail(message) {
26243 throw new Error(message);
26244 }
26245
26246 // Precondition function that checks if the given predicate is true.
26247 // If not, it will throw an error.
26248 function argument(predicate, message) {
26249 if (!predicate) {
26250 fail(message);
26251 }
26252 }
26253 var check = { fail: fail, argument: argument, assert: argument };
26254
26255 // Data types used in the OpenType font file.
26256
26257 var LIMIT16 = 32768; // The limit at which a 16-bit number switches signs == 2^15
26258 var LIMIT32 = 2147483648; // The limit at which a 32-bit number switches signs == 2 ^ 31
26259
26260 /**
26261 * @exports opentype.decode
26262 * @class
26263 */
26264 var decode = {};
26265 /**
26266 * @exports opentype.encode
26267 * @class
26268 */
26269 var encode = {};
26270 /**
26271 * @exports opentype.sizeOf
26272 * @class
26273 */
26274 var sizeOf = {};
26275
26276 // Return a function that always returns the same value.
26277 function constant(v) {
26278 return function() {
26279 return v;
26280 };
26281 }
26282
26283 // OpenType data types //////////////////////////////////////////////////////
26284
26285 /**
26286 * Convert an 8-bit unsigned integer to a list of 1 byte.
26287 * @param {number}
26288 * @returns {Array}
26289 */
26290 encode.BYTE = function(v) {
26291 check.argument(
26292 v >= 0 && v <= 255,
26293 'Byte value should be between 0 and 255.'
26294 );
26295 return [v];
26296 };
26297 /**
26298 * @constant
26299 * @type {number}
26300 */
26301 sizeOf.BYTE = constant(1);
26302
26303 /**
26304 * Convert a 8-bit signed integer to a list of 1 byte.
26305 * @param {string}
26306 * @returns {Array}
26307 */
26308 encode.CHAR = function(v) {
26309 return [v.charCodeAt(0)];
26310 };
26311
26312 /**
26313 * @constant
26314 * @type {number}
26315 */
26316 sizeOf.CHAR = constant(1);
26317
26318 /**
26319 * Convert an ASCII string to a list of bytes.
26320 * @param {string}
26321 * @returns {Array}
26322 */
26323 encode.CHARARRAY = function(v) {
26324 var b = [];
26325 for (var i = 0; i < v.length; i += 1) {
26326 b[i] = v.charCodeAt(i);
26327 }
26328
26329 return b;
26330 };
26331
26332 /**
26333 * @param {Array}
26334 * @returns {number}
26335 */
26336 sizeOf.CHARARRAY = function(v) {
26337 return v.length;
26338 };
26339
26340 /**
26341 * Convert a 16-bit unsigned integer to a list of 2 bytes.
26342 * @param {number}
26343 * @returns {Array}
26344 */
26345 encode.USHORT = function(v) {
26346 return [(v >> 8) & 0xff, v & 0xff];
26347 };
26348
26349 /**
26350 * @constant
26351 * @type {number}
26352 */
26353 sizeOf.USHORT = constant(2);
26354
26355 /**
26356 * Convert a 16-bit signed integer to a list of 2 bytes.
26357 * @param {number}
26358 * @returns {Array}
26359 */
26360 encode.SHORT = function(v) {
26361 // Two's complement
26362 if (v >= LIMIT16) {
26363 v = -(2 * LIMIT16 - v);
26364 }
26365
26366 return [(v >> 8) & 0xff, v & 0xff];
26367 };
26368
26369 /**
26370 * @constant
26371 * @type {number}
26372 */
26373 sizeOf.SHORT = constant(2);
26374
26375 /**
26376 * Convert a 24-bit unsigned integer to a list of 3 bytes.
26377 * @param {number}
26378 * @returns {Array}
26379 */
26380 encode.UINT24 = function(v) {
26381 return [(v >> 16) & 0xff, (v >> 8) & 0xff, v & 0xff];
26382 };
26383
26384 /**
26385 * @constant
26386 * @type {number}
26387 */
26388 sizeOf.UINT24 = constant(3);
26389
26390 /**
26391 * Convert a 32-bit unsigned integer to a list of 4 bytes.
26392 * @param {number}
26393 * @returns {Array}
26394 */
26395 encode.ULONG = function(v) {
26396 return [(v >> 24) & 0xff, (v >> 16) & 0xff, (v >> 8) & 0xff, v & 0xff];
26397 };
26398
26399 /**
26400 * @constant
26401 * @type {number}
26402 */
26403 sizeOf.ULONG = constant(4);
26404
26405 /**
26406 * Convert a 32-bit unsigned integer to a list of 4 bytes.
26407 * @param {number}
26408 * @returns {Array}
26409 */
26410 encode.LONG = function(v) {
26411 // Two's complement
26412 if (v >= LIMIT32) {
26413 v = -(2 * LIMIT32 - v);
26414 }
26415
26416 return [(v >> 24) & 0xff, (v >> 16) & 0xff, (v >> 8) & 0xff, v & 0xff];
26417 };
26418
26419 /**
26420 * @constant
26421 * @type {number}
26422 */
26423 sizeOf.LONG = constant(4);
26424
26425 encode.FIXED = encode.ULONG;
26426 sizeOf.FIXED = sizeOf.ULONG;
26427
26428 encode.FWORD = encode.SHORT;
26429 sizeOf.FWORD = sizeOf.SHORT;
26430
26431 encode.UFWORD = encode.USHORT;
26432 sizeOf.UFWORD = sizeOf.USHORT;
26433
26434 /**
26435 * Convert a 32-bit Apple Mac timestamp integer to a list of 8 bytes, 64-bit timestamp.
26436 * @param {number}
26437 * @returns {Array}
26438 */
26439 encode.LONGDATETIME = function(v) {
26440 return [
26441 0,
26442 0,
26443 0,
26444 0,
26445 (v >> 24) & 0xff,
26446 (v >> 16) & 0xff,
26447 (v >> 8) & 0xff,
26448 v & 0xff
26449 ];
26450 };
26451
26452 /**
26453 * @constant
26454 * @type {number}
26455 */
26456 sizeOf.LONGDATETIME = constant(8);
26457
26458 /**
26459 * Convert a 4-char tag to a list of 4 bytes.
26460 * @param {string}
26461 * @returns {Array}
26462 */
26463 encode.TAG = function(v) {
26464 check.argument(v.length === 4, 'Tag should be exactly 4 ASCII characters.');
26465 return [v.charCodeAt(0), v.charCodeAt(1), v.charCodeAt(2), v.charCodeAt(3)];
26466 };
26467
26468 /**
26469 * @constant
26470 * @type {number}
26471 */
26472 sizeOf.TAG = constant(4);
26473
26474 // CFF data types ///////////////////////////////////////////////////////////
26475
26476 encode.Card8 = encode.BYTE;
26477 sizeOf.Card8 = sizeOf.BYTE;
26478
26479 encode.Card16 = encode.USHORT;
26480 sizeOf.Card16 = sizeOf.USHORT;
26481
26482 encode.OffSize = encode.BYTE;
26483 sizeOf.OffSize = sizeOf.BYTE;
26484
26485 encode.SID = encode.USHORT;
26486 sizeOf.SID = sizeOf.USHORT;
26487
26488 // Convert a numeric operand or charstring number to a variable-size list of bytes.
26489 /**
26490 * Convert a numeric operand or charstring number to a variable-size list of bytes.
26491 * @param {number}
26492 * @returns {Array}
26493 */
26494 encode.NUMBER = function(v) {
26495 if (v >= -107 && v <= 107) {
26496 return [v + 139];
26497 } else if (v >= 108 && v <= 1131) {
26498 v = v - 108;
26499 return [(v >> 8) + 247, v & 0xff];
26500 } else if (v >= -1131 && v <= -108) {
26501 v = -v - 108;
26502 return [(v >> 8) + 251, v & 0xff];
26503 } else if (v >= -32768 && v <= 32767) {
26504 return encode.NUMBER16(v);
26505 } else {
26506 return encode.NUMBER32(v);
26507 }
26508 };
26509
26510 /**
26511 * @param {number}
26512 * @returns {number}
26513 */
26514 sizeOf.NUMBER = function(v) {
26515 return encode.NUMBER(v).length;
26516 };
26517
26518 /**
26519 * Convert a signed number between -32768 and +32767 to a three-byte value.
26520 * This ensures we always use three bytes, but is not the most compact format.
26521 * @param {number}
26522 * @returns {Array}
26523 */
26524 encode.NUMBER16 = function(v) {
26525 return [28, (v >> 8) & 0xff, v & 0xff];
26526 };
26527
26528 /**
26529 * @constant
26530 * @type {number}
26531 */
26532 sizeOf.NUMBER16 = constant(3);
26533
26534 /**
26535 * Convert a signed number between -(2^31) and +(2^31-1) to a five-byte value.
26536 * This is useful if you want to be sure you always use four bytes,
26537 * at the expense of wasting a few bytes for smaller numbers.
26538 * @param {number}
26539 * @returns {Array}
26540 */
26541 encode.NUMBER32 = function(v) {
26542 return [29, (v >> 24) & 0xff, (v >> 16) & 0xff, (v >> 8) & 0xff, v & 0xff];
26543 };
26544
26545 /**
26546 * @constant
26547 * @type {number}
26548 */
26549 sizeOf.NUMBER32 = constant(5);
26550
26551 /**
26552 * @param {number}
26553 * @returns {Array}
26554 */
26555 encode.REAL = function(v) {
26556 var value = v.toString();
26557
26558 // Some numbers use an epsilon to encode the value. (e.g. JavaScript will store 0.0000001 as 1e-7)
26559 // This code converts it back to a number without the epsilon.
26560 var m = /\.(\d*?)(?:9{5,20}|0{5,20})\d{0,2}(?:e(.+)|$)/.exec(value);
26561 if (m) {
26562 var epsilon = parseFloat('1e' + ((m[2] ? +m[2] : 0) + m[1].length));
26563 value = (Math.round(v * epsilon) / epsilon).toString();
26564 }
26565
26566 var nibbles = '';
26567 for (var i = 0, ii = value.length; i < ii; i += 1) {
26568 var c = value[i];
26569 if (c === 'e') {
26570 nibbles += value[++i] === '-' ? 'c' : 'b';
26571 } else if (c === '.') {
26572 nibbles += 'a';
26573 } else if (c === '-') {
26574 nibbles += 'e';
26575 } else {
26576 nibbles += c;
26577 }
26578 }
26579
26580 nibbles += nibbles.length & 1 ? 'f' : 'ff';
26581 var out = [30];
26582 for (var i$1 = 0, ii$1 = nibbles.length; i$1 < ii$1; i$1 += 2) {
26583 out.push(parseInt(nibbles.substr(i$1, 2), 16));
26584 }
26585
26586 return out;
26587 };
26588
26589 /**
26590 * @param {number}
26591 * @returns {number}
26592 */
26593 sizeOf.REAL = function(v) {
26594 return encode.REAL(v).length;
26595 };
26596
26597 encode.NAME = encode.CHARARRAY;
26598 sizeOf.NAME = sizeOf.CHARARRAY;
26599
26600 encode.STRING = encode.CHARARRAY;
26601 sizeOf.STRING = sizeOf.CHARARRAY;
26602
26603 /**
26604 * @param {DataView} data
26605 * @param {number} offset
26606 * @param {number} numBytes
26607 * @returns {string}
26608 */
26609 decode.UTF8 = function(data, offset, numBytes) {
26610 var codePoints = [];
26611 var numChars = numBytes;
26612 for (var j = 0; j < numChars; j++, offset += 1) {
26613 codePoints[j] = data.getUint8(offset);
26614 }
26615
26616 return String.fromCharCode.apply(null, codePoints);
26617 };
26618
26619 /**
26620 * @param {DataView} data
26621 * @param {number} offset
26622 * @param {number} numBytes
26623 * @returns {string}
26624 */
26625 decode.UTF16 = function(data, offset, numBytes) {
26626 var codePoints = [];
26627 var numChars = numBytes / 2;
26628 for (var j = 0; j < numChars; j++, offset += 2) {
26629 codePoints[j] = data.getUint16(offset);
26630 }
26631
26632 return String.fromCharCode.apply(null, codePoints);
26633 };
26634
26635 /**
26636 * Convert a JavaScript string to UTF16-BE.
26637 * @param {string}
26638 * @returns {Array}
26639 */
26640 encode.UTF16 = function(v) {
26641 var b = [];
26642 for (var i = 0; i < v.length; i += 1) {
26643 var codepoint = v.charCodeAt(i);
26644 b[b.length] = (codepoint >> 8) & 0xff;
26645 b[b.length] = codepoint & 0xff;
26646 }
26647
26648 return b;
26649 };
26650
26651 /**
26652 * @param {string}
26653 * @returns {number}
26654 */
26655 sizeOf.UTF16 = function(v) {
26656 return v.length * 2;
26657 };
26658
26659 // Data for converting old eight-bit Macintosh encodings to Unicode.
26660 // This representation is optimized for decoding; encoding is slower
26661 // and needs more memory. The assumption is that all opentype.js users
26662 // want to open fonts, but saving a font will be comparatively rare
26663 // so it can be more expensive. Keyed by IANA character set name.
26664 //
26665 // Python script for generating these strings:
26666 //
26667 // s = u''.join([chr(c).decode('mac_greek') for c in range(128, 256)])
26668 // print(s.encode('utf-8'))
26669 /**
26670 * @private
26671 */
26672 var eightBitMacEncodings = {
26673 // Python: 'mac_croatian'
26674 'x-mac-croatian':
26675 'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®Š™´¨≠ŽØ∞±≤≥∆µ∂∑∏š∫ªºΩžø' +
26676 '¿¡¬√ƒ≈Ć«Č… ÀÃÕŒœĐ—“”‘’÷◊©⁄€‹›Æ»–·‚„‰ÂćÁčÈÍÎÏÌÓÔđÒÚÛÙıˆ˜¯πË˚¸Êæˇ',
26677 // Python: 'mac_cyrillic'
26678 'x-mac-cyrillic':
26679 'АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ†°Ґ£§•¶І®©™Ђђ≠Ѓѓ∞±≤≥іµґЈЄєЇїЉљЊњ' +
26680 'јЅ¬√ƒ≈∆«»… ЋћЌќѕ–—“”‘’÷„ЎўЏџ№Ёёяабвгдежзийклмнопрстуфхцчшщъыьэю',
26681 // http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/GAELIC.TXT
26682 'x-mac-gaelic':
26683 'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØḂ±≤≥ḃĊċḊḋḞḟĠġṀæø' +
26684 'ṁṖṗɼƒſṠ«»… ÀÃÕŒœ–—“”‘’ṡẛÿŸṪ€‹›Ŷŷṫ·Ỳỳ⁊ÂÊÁËÈÍÎÏÌÓÔ♣ÒÚÛÙıÝýŴŵẄẅẀẁẂẃ',
26685 // Python: 'mac_greek'
26686 'x-mac-greek':
26687 'Ĺ²É³ÖÜ΅àâä΄¨çéèê룙î‰ôö¦€ùûü†ΓΔΘΛΞΠß®©ΣΪ§≠°·Α±≤≥¥ΒΕΖΗΙΚΜΦΫΨΩ' +
26688 'άΝ¬ΟΡ≈Τ«»… ΥΧΆΈœ–―“”‘’÷ΉΊΌΎέήίόΏύαβψδεφγηιξκλμνοπώρστθωςχυζϊϋΐΰ\u00AD',
26689 // Python: 'mac_iceland'
26690 'x-mac-icelandic':
26691 'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûüÝ°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø' +
26692 '¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄€ÐðÞþý·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ',
26693 // http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/INUIT.TXT
26694 'x-mac-inuit':
26695 'ᐃᐄᐅᐆᐊᐋᐱᐲᐳᐴᐸᐹᑉᑎᑏᑐᑑᑕᑖᑦᑭᑮᑯᑰᑲᑳᒃᒋᒌᒍᒎᒐᒑ°ᒡᒥᒦ•¶ᒧ®©™ᒨᒪᒫᒻᓂᓃᓄᓅᓇᓈᓐᓯᓰᓱᓲᓴᓵᔅᓕᓖᓗ' +
26696 'ᓘᓚᓛᓪᔨᔩᔪᔫᔭ… ᔮᔾᕕᕖᕗ–—“”‘’ᕘᕙᕚᕝᕆᕇᕈᕉᕋᕌᕐᕿᖀᖁᖂᖃᖄᖅᖏᖐᖑᖒᖓᖔᖕᙱᙲᙳᙴᙵᙶᖖᖠᖡᖢᖣᖤᖥᖦᕼŁł',
26697 // Python: 'mac_latin2'
26698 'x-mac-ce':
26699 'ÄĀāÉĄÖÜáąČäčĆć鏟ĎíďĒēĖóėôöõúĚěü†°Ę£§•¶ß®©™ę¨≠ģĮįĪ≤≥īĶ∂∑łĻļĽľĹĺŅ' +
26700 'ņѬ√ńŇ∆«»… ňŐÕőŌ–—“”‘’÷◊ōŔŕŘ‹›řŖŗŠ‚„šŚśÁŤťÍŽžŪÓÔūŮÚůŰűŲųÝýķŻŁżĢˇ',
26701 // Python: 'mac_roman'
26702 macintosh:
26703 'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø' +
26704 '¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄€‹›fifl‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ',
26705 // Python: 'mac_romanian'
26706 'x-mac-romanian':
26707 'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ĂȘ∞±≤≥¥µ∂∑∏π∫ªºΩăș' +
26708 '¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄€‹›Țț‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ',
26709 // Python: 'mac_turkish'
26710 'x-mac-turkish':
26711 'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø' +
26712 '¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸĞğİıŞş‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙˆ˜¯˘˙˚¸˝˛ˇ'
26713 };
26714
26715 /**
26716 * Decodes an old-style Macintosh string. Returns either a Unicode JavaScript
26717 * string, or 'undefined' if the encoding is unsupported. For example, we do
26718 * not support Chinese, Japanese or Korean because these would need large
26719 * mapping tables.
26720 * @param {DataView} dataView
26721 * @param {number} offset
26722 * @param {number} dataLength
26723 * @param {string} encoding
26724 * @returns {string}
26725 */
26726 decode.MACSTRING = function(dataView, offset, dataLength, encoding) {
26727 var table = eightBitMacEncodings[encoding];
26728 if (table === undefined) {
26729 return undefined;
26730 }
26731
26732 var result = '';
26733 for (var i = 0; i < dataLength; i++) {
26734 var c = dataView.getUint8(offset + i);
26735 // In all eight-bit Mac encodings, the characters 0x00..0x7F are
26736 // mapped to U+0000..U+007F; we only need to look up the others.
26737 if (c <= 0x7f) {
26738 result += String.fromCharCode(c);
26739 } else {
26740 result += table[c & 0x7f];
26741 }
26742 }
26743
26744 return result;
26745 };
26746
26747 // Helper function for encode.MACSTRING. Returns a dictionary for mapping
26748 // Unicode character codes to their 8-bit MacOS equivalent. This table
26749 // is not exactly a super cheap data structure, but we do not care because
26750 // encoding Macintosh strings is only rarely needed in typical applications.
26751 var macEncodingTableCache = typeof WeakMap === 'function' && new WeakMap();
26752 var macEncodingCacheKeys;
26753 var getMacEncodingTable = function(encoding) {
26754 // Since we use encoding as a cache key for WeakMap, it has to be
26755 // a String object and not a literal. And at least on NodeJS 2.10.1,
26756 // WeakMap requires that the same String instance is passed for cache hits.
26757 if (!macEncodingCacheKeys) {
26758 macEncodingCacheKeys = {};
26759 for (var e in eightBitMacEncodings) {
26760 /*jshint -W053 */ // Suppress "Do not use String as a constructor."
26761 macEncodingCacheKeys[e] = new String(e);
26762 }
26763 }
26764
26765 var cacheKey = macEncodingCacheKeys[encoding];
26766 if (cacheKey === undefined) {
26767 return undefined;
26768 }
26769
26770 // We can't do "if (cache.has(key)) {return cache.get(key)}" here:
26771 // since garbage collection may run at any time, it could also kick in
26772 // between the calls to cache.has() and cache.get(). In that case,
26773 // we would return 'undefined' even though we do support the encoding.
26774 if (macEncodingTableCache) {
26775 var cachedTable = macEncodingTableCache.get(cacheKey);
26776 if (cachedTable !== undefined) {
26777 return cachedTable;
26778 }
26779 }
26780
26781 var decodingTable = eightBitMacEncodings[encoding];
26782 if (decodingTable === undefined) {
26783 return undefined;
26784 }
26785
26786 var encodingTable = {};
26787 for (var i = 0; i < decodingTable.length; i++) {
26788 encodingTable[decodingTable.charCodeAt(i)] = i + 0x80;
26789 }
26790
26791 if (macEncodingTableCache) {
26792 macEncodingTableCache.set(cacheKey, encodingTable);
26793 }
26794
26795 return encodingTable;
26796 };
26797
26798 /**
26799 * Encodes an old-style Macintosh string. Returns a byte array upon success.
26800 * If the requested encoding is unsupported, or if the input string contains
26801 * a character that cannot be expressed in the encoding, the function returns
26802 * 'undefined'.
26803 * @param {string} str
26804 * @param {string} encoding
26805 * @returns {Array}
26806 */
26807 encode.MACSTRING = function(str, encoding) {
26808 var table = getMacEncodingTable(encoding);
26809 if (table === undefined) {
26810 return undefined;
26811 }
26812
26813 var result = [];
26814 for (var i = 0; i < str.length; i++) {
26815 var c = str.charCodeAt(i);
26816
26817 // In all eight-bit Mac encodings, the characters 0x00..0x7F are
26818 // mapped to U+0000..U+007F; we only need to look up the others.
26819 if (c >= 0x80) {
26820 c = table[c];
26821 if (c === undefined) {
26822 // str contains a Unicode character that cannot be encoded
26823 // in the requested encoding.
26824 return undefined;
26825 }
26826 }
26827 result[i] = c;
26828 // result.push(c);
26829 }
26830
26831 return result;
26832 };
26833
26834 /**
26835 * @param {string} str
26836 * @param {string} encoding
26837 * @returns {number}
26838 */
26839 sizeOf.MACSTRING = function(str, encoding) {
26840 var b = encode.MACSTRING(str, encoding);
26841 if (b !== undefined) {
26842 return b.length;
26843 } else {
26844 return 0;
26845 }
26846 };
26847
26848 // Helper for encode.VARDELTAS
26849 function isByteEncodable(value) {
26850 return value >= -128 && value <= 127;
26851 }
26852
26853 // Helper for encode.VARDELTAS
26854 function encodeVarDeltaRunAsZeroes(deltas, pos, result) {
26855 var runLength = 0;
26856 var numDeltas = deltas.length;
26857 while (pos < numDeltas && runLength < 64 && deltas[pos] === 0) {
26858 ++pos;
26859 ++runLength;
26860 }
26861 result.push(0x80 | (runLength - 1));
26862 return pos;
26863 }
26864
26865 // Helper for encode.VARDELTAS
26866 function encodeVarDeltaRunAsBytes(deltas, offset, result) {
26867 var runLength = 0;
26868 var numDeltas = deltas.length;
26869 var pos = offset;
26870 while (pos < numDeltas && runLength < 64) {
26871 var value = deltas[pos];
26872 if (!isByteEncodable(value)) {
26873 break;
26874 }
26875
26876 // Within a byte-encoded run of deltas, a single zero is best
26877 // stored literally as 0x00 value. However, if we have two or
26878 // more zeroes in a sequence, it is better to start a new run.
26879 // Fore example, the sequence of deltas [15, 15, 0, 15, 15]
26880 // becomes 6 bytes (04 0F 0F 00 0F 0F) when storing the zero
26881 // within the current run, but 7 bytes (01 0F 0F 80 01 0F 0F)
26882 // when starting a new run.
26883 if (value === 0 && pos + 1 < numDeltas && deltas[pos + 1] === 0) {
26884 break;
26885 }
26886
26887 ++pos;
26888 ++runLength;
26889 }
26890 result.push(runLength - 1);
26891 for (var i = offset; i < pos; ++i) {
26892 result.push((deltas[i] + 256) & 0xff);
26893 }
26894 return pos;
26895 }
26896
26897 // Helper for encode.VARDELTAS
26898 function encodeVarDeltaRunAsWords(deltas, offset, result) {
26899 var runLength = 0;
26900 var numDeltas = deltas.length;
26901 var pos = offset;
26902 while (pos < numDeltas && runLength < 64) {
26903 var value = deltas[pos];
26904
26905 // Within a word-encoded run of deltas, it is easiest to start
26906 // a new run (with a different encoding) whenever we encounter
26907 // a zero value. For example, the sequence [0x6666, 0, 0x7777]
26908 // needs 7 bytes when storing the zero inside the current run
26909 // (42 66 66 00 00 77 77), and equally 7 bytes when starting a
26910 // new run (40 66 66 80 40 77 77).
26911 if (value === 0) {
26912 break;
26913 }
26914
26915 // Within a word-encoded run of deltas, a single value in the
26916 // range (-128..127) should be encoded within the current run
26917 // because it is more compact. For example, the sequence
26918 // [0x6666, 2, 0x7777] becomes 7 bytes when storing the value
26919 // literally (42 66 66 00 02 77 77), but 8 bytes when starting
26920 // a new run (40 66 66 00 02 40 77 77).
26921 if (
26922 isByteEncodable(value) &&
26923 pos + 1 < numDeltas &&
26924 isByteEncodable(deltas[pos + 1])
26925 ) {
26926 break;
26927 }
26928
26929 ++pos;
26930 ++runLength;
26931 }
26932 result.push(0x40 | (runLength - 1));
26933 for (var i = offset; i < pos; ++i) {
26934 var val = deltas[i];
26935 result.push(((val + 0x10000) >> 8) & 0xff, (val + 0x100) & 0xff);
26936 }
26937 return pos;
26938 }
26939
26940 /**
26941 * Encode a list of variation adjustment deltas.
26942 *
26943 * Variation adjustment deltas are used in ‘gvar’ and ‘cvar’ tables.
26944 * They indicate how points (in ‘gvar’) or values (in ‘cvar’) get adjusted
26945 * when generating instances of variation fonts.
26946 *
26947 * @see https://www.microsoft.com/typography/otspec/gvar.htm
26948 * @see https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6gvar.html
26949 * @param {Array}
26950 * @return {Array}
26951 */
26952 encode.VARDELTAS = function(deltas) {
26953 var pos = 0;
26954 var result = [];
26955 while (pos < deltas.length) {
26956 var value = deltas[pos];
26957 if (value === 0) {
26958 pos = encodeVarDeltaRunAsZeroes(deltas, pos, result);
26959 } else if (value >= -128 && value <= 127) {
26960 pos = encodeVarDeltaRunAsBytes(deltas, pos, result);
26961 } else {
26962 pos = encodeVarDeltaRunAsWords(deltas, pos, result);
26963 }
26964 }
26965 return result;
26966 };
26967
26968 // Convert a list of values to a CFF INDEX structure.
26969 // The values should be objects containing name / type / value.
26970 /**
26971 * @param {Array} l
26972 * @returns {Array}
26973 */
26974 encode.INDEX = function(l) {
26975 //var offset, offsets, offsetEncoder, encodedOffsets, encodedOffset, data,
26976 // i, v;
26977 // Because we have to know which data type to use to encode the offsets,
26978 // we have to go through the values twice: once to encode the data and
26979 // calculate the offsets, then again to encode the offsets using the fitting data type.
26980 var offset = 1; // First offset is always 1.
26981 var offsets = [offset];
26982 var data = [];
26983 for (var i = 0; i < l.length; i += 1) {
26984 var v = encode.OBJECT(l[i]);
26985 Array.prototype.push.apply(data, v);
26986 offset += v.length;
26987 offsets.push(offset);
26988 }
26989
26990 if (data.length === 0) {
26991 return [0, 0];
26992 }
26993
26994 var encodedOffsets = [];
26995 var offSize = (1 + Math.floor(Math.log(offset) / Math.log(2)) / 8) | 0;
26996 var offsetEncoder = [
26997 undefined,
26998 encode.BYTE,
26999 encode.USHORT,
27000 encode.UINT24,
27001 encode.ULONG
27002 ][offSize];
27003 for (var i$1 = 0; i$1 < offsets.length; i$1 += 1) {
27004 var encodedOffset = offsetEncoder(offsets[i$1]);
27005 Array.prototype.push.apply(encodedOffsets, encodedOffset);
27006 }
27007
27008 return Array.prototype.concat(
27009 encode.Card16(l.length),
27010 encode.OffSize(offSize),
27011 encodedOffsets,
27012 data
27013 );
27014 };
27015
27016 /**
27017 * @param {Array}
27018 * @returns {number}
27019 */
27020 sizeOf.INDEX = function(v) {
27021 return encode.INDEX(v).length;
27022 };
27023
27024 /**
27025 * Convert an object to a CFF DICT structure.
27026 * The keys should be numeric.
27027 * The values should be objects containing name / type / value.
27028 * @param {Object} m
27029 * @returns {Array}
27030 */
27031 encode.DICT = function(m) {
27032 var d = [];
27033 var keys = Object.keys(m);
27034 var length = keys.length;
27035
27036 for (var i = 0; i < length; i += 1) {
27037 // Object.keys() return string keys, but our keys are always numeric.
27038 var k = parseInt(keys[i], 0);
27039 var v = m[k];
27040 // Value comes before the key.
27041 d = d.concat(encode.OPERAND(v.value, v.type));
27042 d = d.concat(encode.OPERATOR(k));
27043 }
27044
27045 return d;
27046 };
27047
27048 /**
27049 * @param {Object}
27050 * @returns {number}
27051 */
27052 sizeOf.DICT = function(m) {
27053 return encode.DICT(m).length;
27054 };
27055
27056 /**
27057 * @param {number}
27058 * @returns {Array}
27059 */
27060 encode.OPERATOR = function(v) {
27061 if (v < 1200) {
27062 return [v];
27063 } else {
27064 return [12, v - 1200];
27065 }
27066 };
27067
27068 /**
27069 * @param {Array} v
27070 * @param {string}
27071 * @returns {Array}
27072 */
27073 encode.OPERAND = function(v, type) {
27074 var d = [];
27075 if (Array.isArray(type)) {
27076 for (var i = 0; i < type.length; i += 1) {
27077 check.argument(
27078 v.length === type.length,
27079 'Not enough arguments given for type' + type
27080 );
27081 d = d.concat(encode.OPERAND(v[i], type[i]));
27082 }
27083 } else {
27084 if (type === 'SID') {
27085 d = d.concat(encode.NUMBER(v));
27086 } else if (type === 'offset') {
27087 // We make it easy for ourselves and always encode offsets as
27088 // 4 bytes. This makes offset calculation for the top dict easier.
27089 d = d.concat(encode.NUMBER32(v));
27090 } else if (type === 'number') {
27091 d = d.concat(encode.NUMBER(v));
27092 } else if (type === 'real') {
27093 d = d.concat(encode.REAL(v));
27094 } else {
27095 throw new Error('Unknown operand type ' + type);
27096 // FIXME Add support for booleans
27097 }
27098 }
27099
27100 return d;
27101 };
27102
27103 encode.OP = encode.BYTE;
27104 sizeOf.OP = sizeOf.BYTE;
27105
27106 // memoize charstring encoding using WeakMap if available
27107 var wmm = typeof WeakMap === 'function' && new WeakMap();
27108
27109 /**
27110 * Convert a list of CharString operations to bytes.
27111 * @param {Array}
27112 * @returns {Array}
27113 */
27114 encode.CHARSTRING = function(ops) {
27115 // See encode.MACSTRING for why we don't do "if (wmm && wmm.has(ops))".
27116 if (wmm) {
27117 var cachedValue = wmm.get(ops);
27118 if (cachedValue !== undefined) {
27119 return cachedValue;
27120 }
27121 }
27122
27123 var d = [];
27124 var length = ops.length;
27125
27126 for (var i = 0; i < length; i += 1) {
27127 var op = ops[i];
27128 d = d.concat(encode[op.type](op.value));
27129 }
27130
27131 if (wmm) {
27132 wmm.set(ops, d);
27133 }
27134
27135 return d;
27136 };
27137
27138 /**
27139 * @param {Array}
27140 * @returns {number}
27141 */
27142 sizeOf.CHARSTRING = function(ops) {
27143 return encode.CHARSTRING(ops).length;
27144 };
27145
27146 // Utility functions ////////////////////////////////////////////////////////
27147
27148 /**
27149 * Convert an object containing name / type / value to bytes.
27150 * @param {Object}
27151 * @returns {Array}
27152 */
27153 encode.OBJECT = function(v) {
27154 var encodingFunction = encode[v.type];
27155 check.argument(
27156 encodingFunction !== undefined,
27157 'No encoding function for type ' + v.type
27158 );
27159 return encodingFunction(v.value);
27160 };
27161
27162 /**
27163 * @param {Object}
27164 * @returns {number}
27165 */
27166 sizeOf.OBJECT = function(v) {
27167 var sizeOfFunction = sizeOf[v.type];
27168 check.argument(
27169 sizeOfFunction !== undefined,
27170 'No sizeOf function for type ' + v.type
27171 );
27172 return sizeOfFunction(v.value);
27173 };
27174
27175 /**
27176 * Convert a table object to bytes.
27177 * A table contains a list of fields containing the metadata (name, type and default value).
27178 * The table itself has the field values set as attributes.
27179 * @param {opentype.Table}
27180 * @returns {Array}
27181 */
27182 encode.TABLE = function(table) {
27183 var d = [];
27184 var length = table.fields.length;
27185 var subtables = [];
27186 var subtableOffsets = [];
27187
27188 for (var i = 0; i < length; i += 1) {
27189 var field = table.fields[i];
27190 var encodingFunction = encode[field.type];
27191 check.argument(
27192 encodingFunction !== undefined,
27193 'No encoding function for field type ' +
27194 field.type +
27195 ' (' +
27196 field.name +
27197 ')'
27198 );
27199 var value = table[field.name];
27200 if (value === undefined) {
27201 value = field.value;
27202 }
27203
27204 var bytes = encodingFunction(value);
27205
27206 if (field.type === 'TABLE') {
27207 subtableOffsets.push(d.length);
27208 d = d.concat([0, 0]);
27209 subtables.push(bytes);
27210 } else {
27211 d = d.concat(bytes);
27212 }
27213 }
27214
27215 for (var i$1 = 0; i$1 < subtables.length; i$1 += 1) {
27216 var o = subtableOffsets[i$1];
27217 var offset = d.length;
27218 check.argument(offset < 65536, 'Table ' + table.tableName + ' too big.');
27219 d[o] = offset >> 8;
27220 d[o + 1] = offset & 0xff;
27221 d = d.concat(subtables[i$1]);
27222 }
27223
27224 return d;
27225 };
27226
27227 /**
27228 * @param {opentype.Table}
27229 * @returns {number}
27230 */
27231 sizeOf.TABLE = function(table) {
27232 var numBytes = 0;
27233 var length = table.fields.length;
27234
27235 for (var i = 0; i < length; i += 1) {
27236 var field = table.fields[i];
27237 var sizeOfFunction = sizeOf[field.type];
27238 check.argument(
27239 sizeOfFunction !== undefined,
27240 'No sizeOf function for field type ' +
27241 field.type +
27242 ' (' +
27243 field.name +
27244 ')'
27245 );
27246 var value = table[field.name];
27247 if (value === undefined) {
27248 value = field.value;
27249 }
27250
27251 numBytes += sizeOfFunction(value);
27252
27253 // Subtables take 2 more bytes for offsets.
27254 if (field.type === 'TABLE') {
27255 numBytes += 2;
27256 }
27257 }
27258
27259 return numBytes;
27260 };
27261
27262 encode.RECORD = encode.TABLE;
27263 sizeOf.RECORD = sizeOf.TABLE;
27264
27265 // Merge in a list of bytes.
27266 encode.LITERAL = function(v) {
27267 return v;
27268 };
27269
27270 sizeOf.LITERAL = function(v) {
27271 return v.length;
27272 };
27273
27274 // Table metadata
27275
27276 /**
27277 * @exports opentype.Table
27278 * @class
27279 * @param {string} tableName
27280 * @param {Array} fields
27281 * @param {Object} options
27282 * @constructor
27283 */
27284 function Table(tableName, fields, options) {
27285 var this$1 = this;
27286
27287 for (var i = 0; i < fields.length; i += 1) {
27288 var field = fields[i];
27289 this$1[field.name] = field.value;
27290 }
27291
27292 this.tableName = tableName;
27293 this.fields = fields;
27294 if (options) {
27295 var optionKeys = Object.keys(options);
27296 for (var i$1 = 0; i$1 < optionKeys.length; i$1 += 1) {
27297 var k = optionKeys[i$1];
27298 var v = options[k];
27299 if (this$1[k] !== undefined) {
27300 this$1[k] = v;
27301 }
27302 }
27303 }
27304 }
27305
27306 /**
27307 * Encodes the table and returns an array of bytes
27308 * @return {Array}
27309 */
27310 Table.prototype.encode = function() {
27311 return encode.TABLE(this);
27312 };
27313
27314 /**
27315 * Get the size of the table.
27316 * @return {number}
27317 */
27318 Table.prototype.sizeOf = function() {
27319 return sizeOf.TABLE(this);
27320 };
27321
27322 /**
27323 * @private
27324 */
27325 function ushortList(itemName, list, count) {
27326 if (count === undefined) {
27327 count = list.length;
27328 }
27329 var fields = new Array(list.length + 1);
27330 fields[0] = { name: itemName + 'Count', type: 'USHORT', value: count };
27331 for (var i = 0; i < list.length; i++) {
27332 fields[i + 1] = { name: itemName + i, type: 'USHORT', value: list[i] };
27333 }
27334 return fields;
27335 }
27336
27337 /**
27338 * @private
27339 */
27340 function tableList(itemName, records, itemCallback) {
27341 var count = records.length;
27342 var fields = new Array(count + 1);
27343 fields[0] = { name: itemName + 'Count', type: 'USHORT', value: count };
27344 for (var i = 0; i < count; i++) {
27345 fields[i + 1] = {
27346 name: itemName + i,
27347 type: 'TABLE',
27348 value: itemCallback(records[i], i)
27349 };
27350 }
27351 return fields;
27352 }
27353
27354 /**
27355 * @private
27356 */
27357 function recordList(itemName, records, itemCallback) {
27358 var count = records.length;
27359 var fields = [];
27360 fields[0] = { name: itemName + 'Count', type: 'USHORT', value: count };
27361 for (var i = 0; i < count; i++) {
27362 fields = fields.concat(itemCallback(records[i], i));
27363 }
27364 return fields;
27365 }
27366
27367 // Common Layout Tables
27368
27369 /**
27370 * @exports opentype.Coverage
27371 * @class
27372 * @param {opentype.Table}
27373 * @constructor
27374 * @extends opentype.Table
27375 */
27376 function Coverage(coverageTable) {
27377 if (coverageTable.format === 1) {
27378 Table.call(
27379 this,
27380 'coverageTable',
27381 [{ name: 'coverageFormat', type: 'USHORT', value: 1 }].concat(
27382 ushortList('glyph', coverageTable.glyphs)
27383 )
27384 );
27385 } else {
27386 check.assert(false, "Can't create coverage table format 2 yet.");
27387 }
27388 }
27389 Coverage.prototype = Object.create(Table.prototype);
27390 Coverage.prototype.constructor = Coverage;
27391
27392 function ScriptList(scriptListTable) {
27393 Table.call(
27394 this,
27395 'scriptListTable',
27396 recordList('scriptRecord', scriptListTable, function(scriptRecord, i) {
27397 var script = scriptRecord.script;
27398 var defaultLangSys = script.defaultLangSys;
27399 check.assert(
27400 !!defaultLangSys,
27401 'Unable to write GSUB: script ' +
27402 scriptRecord.tag +
27403 ' has no default language system.'
27404 );
27405 return [
27406 { name: 'scriptTag' + i, type: 'TAG', value: scriptRecord.tag },
27407 {
27408 name: 'script' + i,
27409 type: 'TABLE',
27410 value: new Table(
27411 'scriptTable',
27412 [
27413 {
27414 name: 'defaultLangSys',
27415 type: 'TABLE',
27416 value: new Table(
27417 'defaultLangSys',
27418 [
27419 { name: 'lookupOrder', type: 'USHORT', value: 0 },
27420 {
27421 name: 'reqFeatureIndex',
27422 type: 'USHORT',
27423 value: defaultLangSys.reqFeatureIndex
27424 }
27425 ].concat(
27426 ushortList('featureIndex', defaultLangSys.featureIndexes)
27427 )
27428 )
27429 }
27430 ].concat(
27431 recordList('langSys', script.langSysRecords, function(
27432 langSysRecord,
27433 i
27434 ) {
27435 var langSys = langSysRecord.langSys;
27436 return [
27437 {
27438 name: 'langSysTag' + i,
27439 type: 'TAG',
27440 value: langSysRecord.tag
27441 },
27442 {
27443 name: 'langSys' + i,
27444 type: 'TABLE',
27445 value: new Table(
27446 'langSys',
27447 [
27448 { name: 'lookupOrder', type: 'USHORT', value: 0 },
27449 {
27450 name: 'reqFeatureIndex',
27451 type: 'USHORT',
27452 value: langSys.reqFeatureIndex
27453 }
27454 ].concat(
27455 ushortList('featureIndex', langSys.featureIndexes)
27456 )
27457 )
27458 }
27459 ];
27460 })
27461 )
27462 )
27463 }
27464 ];
27465 })
27466 );
27467 }
27468 ScriptList.prototype = Object.create(Table.prototype);
27469 ScriptList.prototype.constructor = ScriptList;
27470
27471 /**
27472 * @exports opentype.FeatureList
27473 * @class
27474 * @param {opentype.Table}
27475 * @constructor
27476 * @extends opentype.Table
27477 */
27478 function FeatureList(featureListTable) {
27479 Table.call(
27480 this,
27481 'featureListTable',
27482 recordList('featureRecord', featureListTable, function(featureRecord, i) {
27483 var feature = featureRecord.feature;
27484 return [
27485 { name: 'featureTag' + i, type: 'TAG', value: featureRecord.tag },
27486 {
27487 name: 'feature' + i,
27488 type: 'TABLE',
27489 value: new Table(
27490 'featureTable',
27491 [
27492 {
27493 name: 'featureParams',
27494 type: 'USHORT',
27495 value: feature.featureParams
27496 }
27497 ].concat(ushortList('lookupListIndex', feature.lookupListIndexes))
27498 )
27499 }
27500 ];
27501 })
27502 );
27503 }
27504 FeatureList.prototype = Object.create(Table.prototype);
27505 FeatureList.prototype.constructor = FeatureList;
27506
27507 /**
27508 * @exports opentype.LookupList
27509 * @class
27510 * @param {opentype.Table}
27511 * @param {Object}
27512 * @constructor
27513 * @extends opentype.Table
27514 */
27515 function LookupList(lookupListTable, subtableMakers) {
27516 Table.call(
27517 this,
27518 'lookupListTable',
27519 tableList('lookup', lookupListTable, function(lookupTable) {
27520 var subtableCallback = subtableMakers[lookupTable.lookupType];
27521 check.assert(
27522 !!subtableCallback,
27523 'Unable to write GSUB lookup type ' +
27524 lookupTable.lookupType +
27525 ' tables.'
27526 );
27527 return new Table(
27528 'lookupTable',
27529 [
27530 {
27531 name: 'lookupType',
27532 type: 'USHORT',
27533 value: lookupTable.lookupType
27534 },
27535 {
27536 name: 'lookupFlag',
27537 type: 'USHORT',
27538 value: lookupTable.lookupFlag
27539 }
27540 ].concat(
27541 tableList('subtable', lookupTable.subtables, subtableCallback)
27542 )
27543 );
27544 })
27545 );
27546 }
27547 LookupList.prototype = Object.create(Table.prototype);
27548 LookupList.prototype.constructor = LookupList;
27549
27550 // Record = same as Table, but inlined (a Table has an offset and its data is further in the stream)
27551 // Don't use offsets inside Records (probable bug), only in Tables.
27552 var table = {
27553 Table: Table,
27554 Record: Table,
27555 Coverage: Coverage,
27556 ScriptList: ScriptList,
27557 FeatureList: FeatureList,
27558 LookupList: LookupList,
27559 ushortList: ushortList,
27560 tableList: tableList,
27561 recordList: recordList
27562 };
27563
27564 // Parsing utility functions
27565
27566 // Retrieve an unsigned byte from the DataView.
27567 function getByte(dataView, offset) {
27568 return dataView.getUint8(offset);
27569 }
27570
27571 // Retrieve an unsigned 16-bit short from the DataView.
27572 // The value is stored in big endian.
27573 function getUShort(dataView, offset) {
27574 return dataView.getUint16(offset, false);
27575 }
27576
27577 // Retrieve a signed 16-bit short from the DataView.
27578 // The value is stored in big endian.
27579 function getShort(dataView, offset) {
27580 return dataView.getInt16(offset, false);
27581 }
27582
27583 // Retrieve an unsigned 32-bit long from the DataView.
27584 // The value is stored in big endian.
27585 function getULong(dataView, offset) {
27586 return dataView.getUint32(offset, false);
27587 }
27588
27589 // Retrieve a 32-bit signed fixed-point number (16.16) from the DataView.
27590 // The value is stored in big endian.
27591 function getFixed(dataView, offset) {
27592 var decimal = dataView.getInt16(offset, false);
27593 var fraction = dataView.getUint16(offset + 2, false);
27594 return decimal + fraction / 65535;
27595 }
27596
27597 // Retrieve a 4-character tag from the DataView.
27598 // Tags are used to identify tables.
27599 function getTag(dataView, offset) {
27600 var tag = '';
27601 for (var i = offset; i < offset + 4; i += 1) {
27602 tag += String.fromCharCode(dataView.getInt8(i));
27603 }
27604
27605 return tag;
27606 }
27607
27608 // Retrieve an offset from the DataView.
27609 // Offsets are 1 to 4 bytes in length, depending on the offSize argument.
27610 function getOffset(dataView, offset, offSize) {
27611 var v = 0;
27612 for (var i = 0; i < offSize; i += 1) {
27613 v <<= 8;
27614 v += dataView.getUint8(offset + i);
27615 }
27616
27617 return v;
27618 }
27619
27620 // Retrieve a number of bytes from start offset to the end offset from the DataView.
27621 function getBytes(dataView, startOffset, endOffset) {
27622 var bytes = [];
27623 for (var i = startOffset; i < endOffset; i += 1) {
27624 bytes.push(dataView.getUint8(i));
27625 }
27626
27627 return bytes;
27628 }
27629
27630 // Convert the list of bytes to a string.
27631 function bytesToString(bytes) {
27632 var s = '';
27633 for (var i = 0; i < bytes.length; i += 1) {
27634 s += String.fromCharCode(bytes[i]);
27635 }
27636
27637 return s;
27638 }
27639
27640 var typeOffsets = {
27641 byte: 1,
27642 uShort: 2,
27643 short: 2,
27644 uLong: 4,
27645 fixed: 4,
27646 longDateTime: 8,
27647 tag: 4
27648 };
27649
27650 // A stateful parser that changes the offset whenever a value is retrieved.
27651 // The data is a DataView.
27652 function Parser(data, offset) {
27653 this.data = data;
27654 this.offset = offset;
27655 this.relativeOffset = 0;
27656 }
27657
27658 Parser.prototype.parseByte = function() {
27659 var v = this.data.getUint8(this.offset + this.relativeOffset);
27660 this.relativeOffset += 1;
27661 return v;
27662 };
27663
27664 Parser.prototype.parseChar = function() {
27665 var v = this.data.getInt8(this.offset + this.relativeOffset);
27666 this.relativeOffset += 1;
27667 return v;
27668 };
27669
27670 Parser.prototype.parseCard8 = Parser.prototype.parseByte;
27671
27672 Parser.prototype.parseUShort = function() {
27673 var v = this.data.getUint16(this.offset + this.relativeOffset);
27674 this.relativeOffset += 2;
27675 return v;
27676 };
27677
27678 Parser.prototype.parseCard16 = Parser.prototype.parseUShort;
27679 Parser.prototype.parseSID = Parser.prototype.parseUShort;
27680 Parser.prototype.parseOffset16 = Parser.prototype.parseUShort;
27681
27682 Parser.prototype.parseShort = function() {
27683 var v = this.data.getInt16(this.offset + this.relativeOffset);
27684 this.relativeOffset += 2;
27685 return v;
27686 };
27687
27688 Parser.prototype.parseF2Dot14 = function() {
27689 var v = this.data.getInt16(this.offset + this.relativeOffset) / 16384;
27690 this.relativeOffset += 2;
27691 return v;
27692 };
27693
27694 Parser.prototype.parseULong = function() {
27695 var v = getULong(this.data, this.offset + this.relativeOffset);
27696 this.relativeOffset += 4;
27697 return v;
27698 };
27699
27700 Parser.prototype.parseOffset32 = Parser.prototype.parseULong;
27701
27702 Parser.prototype.parseFixed = function() {
27703 var v = getFixed(this.data, this.offset + this.relativeOffset);
27704 this.relativeOffset += 4;
27705 return v;
27706 };
27707
27708 Parser.prototype.parseString = function(length) {
27709 var dataView = this.data;
27710 var offset = this.offset + this.relativeOffset;
27711 var string = '';
27712 this.relativeOffset += length;
27713 for (var i = 0; i < length; i++) {
27714 string += String.fromCharCode(dataView.getUint8(offset + i));
27715 }
27716
27717 return string;
27718 };
27719
27720 Parser.prototype.parseTag = function() {
27721 return this.parseString(4);
27722 };
27723
27724 // LONGDATETIME is a 64-bit integer.
27725 // JavaScript and unix timestamps traditionally use 32 bits, so we
27726 // only take the last 32 bits.
27727 // + Since until 2038 those bits will be filled by zeros we can ignore them.
27728 Parser.prototype.parseLongDateTime = function() {
27729 var v = getULong(this.data, this.offset + this.relativeOffset + 4);
27730 // Subtract seconds between 01/01/1904 and 01/01/1970
27731 // to convert Apple Mac timestamp to Standard Unix timestamp
27732 v -= 2082844800;
27733 this.relativeOffset += 8;
27734 return v;
27735 };
27736
27737 Parser.prototype.parseVersion = function(minorBase) {
27738 var major = getUShort(this.data, this.offset + this.relativeOffset);
27739
27740 // How to interpret the minor version is very vague in the spec. 0x5000 is 5, 0x1000 is 1
27741 // Default returns the correct number if minor = 0xN000 where N is 0-9
27742 // Set minorBase to 1 for tables that use minor = N where N is 0-9
27743 var minor = getUShort(this.data, this.offset + this.relativeOffset + 2);
27744 this.relativeOffset += 4;
27745 if (minorBase === undefined) {
27746 minorBase = 0x1000;
27747 }
27748 return major + minor / minorBase / 10;
27749 };
27750
27751 Parser.prototype.skip = function(type, amount) {
27752 if (amount === undefined) {
27753 amount = 1;
27754 }
27755
27756 this.relativeOffset += typeOffsets[type] * amount;
27757 };
27758
27759 ///// Parsing lists and records ///////////////////////////////
27760
27761 // Parse a list of 32 bit unsigned integers.
27762 Parser.prototype.parseULongList = function(count) {
27763 if (count === undefined) {
27764 count = this.parseULong();
27765 }
27766 var offsets = new Array(count);
27767 var dataView = this.data;
27768 var offset = this.offset + this.relativeOffset;
27769 for (var i = 0; i < count; i++) {
27770 offsets[i] = dataView.getUint32(offset);
27771 offset += 4;
27772 }
27773
27774 this.relativeOffset += count * 4;
27775 return offsets;
27776 };
27777
27778 // Parse a list of 16 bit unsigned integers. The length of the list can be read on the stream
27779 // or provided as an argument.
27780 Parser.prototype.parseOffset16List = Parser.prototype.parseUShortList = function(
27781 count
27782 ) {
27783 if (count === undefined) {
27784 count = this.parseUShort();
27785 }
27786 var offsets = new Array(count);
27787 var dataView = this.data;
27788 var offset = this.offset + this.relativeOffset;
27789 for (var i = 0; i < count; i++) {
27790 offsets[i] = dataView.getUint16(offset);
27791 offset += 2;
27792 }
27793
27794 this.relativeOffset += count * 2;
27795 return offsets;
27796 };
27797
27798 // Parses a list of 16 bit signed integers.
27799 Parser.prototype.parseShortList = function(count) {
27800 var list = new Array(count);
27801 var dataView = this.data;
27802 var offset = this.offset + this.relativeOffset;
27803 for (var i = 0; i < count; i++) {
27804 list[i] = dataView.getInt16(offset);
27805 offset += 2;
27806 }
27807
27808 this.relativeOffset += count * 2;
27809 return list;
27810 };
27811
27812 // Parses a list of bytes.
27813 Parser.prototype.parseByteList = function(count) {
27814 var list = new Array(count);
27815 var dataView = this.data;
27816 var offset = this.offset + this.relativeOffset;
27817 for (var i = 0; i < count; i++) {
27818 list[i] = dataView.getUint8(offset++);
27819 }
27820
27821 this.relativeOffset += count;
27822 return list;
27823 };
27824
27825 /**
27826 * Parse a list of items.
27827 * Record count is optional, if omitted it is read from the stream.
27828 * itemCallback is one of the Parser methods.
27829 */
27830 Parser.prototype.parseList = function(count, itemCallback) {
27831 var this$1 = this;
27832
27833 if (!itemCallback) {
27834 itemCallback = count;
27835 count = this.parseUShort();
27836 }
27837 var list = new Array(count);
27838 for (var i = 0; i < count; i++) {
27839 list[i] = itemCallback.call(this$1);
27840 }
27841 return list;
27842 };
27843
27844 Parser.prototype.parseList32 = function(count, itemCallback) {
27845 var this$1 = this;
27846
27847 if (!itemCallback) {
27848 itemCallback = count;
27849 count = this.parseULong();
27850 }
27851 var list = new Array(count);
27852 for (var i = 0; i < count; i++) {
27853 list[i] = itemCallback.call(this$1);
27854 }
27855 return list;
27856 };
27857
27858 /**
27859 * Parse a list of records.
27860 * Record count is optional, if omitted it is read from the stream.
27861 * Example of recordDescription: { sequenceIndex: Parser.uShort, lookupListIndex: Parser.uShort }
27862 */
27863 Parser.prototype.parseRecordList = function(count, recordDescription) {
27864 var this$1 = this;
27865
27866 // If the count argument is absent, read it in the stream.
27867 if (!recordDescription) {
27868 recordDescription = count;
27869 count = this.parseUShort();
27870 }
27871 var records = new Array(count);
27872 var fields = Object.keys(recordDescription);
27873 for (var i = 0; i < count; i++) {
27874 var rec = {};
27875 for (var j = 0; j < fields.length; j++) {
27876 var fieldName = fields[j];
27877 var fieldType = recordDescription[fieldName];
27878 rec[fieldName] = fieldType.call(this$1);
27879 }
27880 records[i] = rec;
27881 }
27882 return records;
27883 };
27884
27885 Parser.prototype.parseRecordList32 = function(count, recordDescription) {
27886 var this$1 = this;
27887
27888 // If the count argument is absent, read it in the stream.
27889 if (!recordDescription) {
27890 recordDescription = count;
27891 count = this.parseULong();
27892 }
27893 var records = new Array(count);
27894 var fields = Object.keys(recordDescription);
27895 for (var i = 0; i < count; i++) {
27896 var rec = {};
27897 for (var j = 0; j < fields.length; j++) {
27898 var fieldName = fields[j];
27899 var fieldType = recordDescription[fieldName];
27900 rec[fieldName] = fieldType.call(this$1);
27901 }
27902 records[i] = rec;
27903 }
27904 return records;
27905 };
27906
27907 // Parse a data structure into an object
27908 // Example of description: { sequenceIndex: Parser.uShort, lookupListIndex: Parser.uShort }
27909 Parser.prototype.parseStruct = function(description) {
27910 var this$1 = this;
27911
27912 if (typeof description === 'function') {
27913 return description.call(this);
27914 } else {
27915 var fields = Object.keys(description);
27916 var struct = {};
27917 for (var j = 0; j < fields.length; j++) {
27918 var fieldName = fields[j];
27919 var fieldType = description[fieldName];
27920 struct[fieldName] = fieldType.call(this$1);
27921 }
27922 return struct;
27923 }
27924 };
27925
27926 /**
27927 * Parse a GPOS valueRecord
27928 * https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#value-record
27929 * valueFormat is optional, if omitted it is read from the stream.
27930 */
27931 Parser.prototype.parseValueRecord = function(valueFormat) {
27932 if (valueFormat === undefined) {
27933 valueFormat = this.parseUShort();
27934 }
27935 if (valueFormat === 0) {
27936 // valueFormat2 in kerning pairs is most often 0
27937 // in this case return undefined instead of an empty object, to save space
27938 return;
27939 }
27940 var valueRecord = {};
27941
27942 if (valueFormat & 0x0001) {
27943 valueRecord.xPlacement = this.parseShort();
27944 }
27945 if (valueFormat & 0x0002) {
27946 valueRecord.yPlacement = this.parseShort();
27947 }
27948 if (valueFormat & 0x0004) {
27949 valueRecord.xAdvance = this.parseShort();
27950 }
27951 if (valueFormat & 0x0008) {
27952 valueRecord.yAdvance = this.parseShort();
27953 }
27954
27955 // Device table (non-variable font) / VariationIndex table (variable font) not supported
27956 // https://docs.microsoft.com/fr-fr/typography/opentype/spec/chapter2#devVarIdxTbls
27957 if (valueFormat & 0x0010) {
27958 valueRecord.xPlaDevice = undefined;
27959 this.parseShort();
27960 }
27961 if (valueFormat & 0x0020) {
27962 valueRecord.yPlaDevice = undefined;
27963 this.parseShort();
27964 }
27965 if (valueFormat & 0x0040) {
27966 valueRecord.xAdvDevice = undefined;
27967 this.parseShort();
27968 }
27969 if (valueFormat & 0x0080) {
27970 valueRecord.yAdvDevice = undefined;
27971 this.parseShort();
27972 }
27973
27974 return valueRecord;
27975 };
27976
27977 /**
27978 * Parse a list of GPOS valueRecords
27979 * https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#value-record
27980 * valueFormat and valueCount are read from the stream.
27981 */
27982 Parser.prototype.parseValueRecordList = function() {
27983 var this$1 = this;
27984
27985 var valueFormat = this.parseUShort();
27986 var valueCount = this.parseUShort();
27987 var values = new Array(valueCount);
27988 for (var i = 0; i < valueCount; i++) {
27989 values[i] = this$1.parseValueRecord(valueFormat);
27990 }
27991 return values;
27992 };
27993
27994 Parser.prototype.parsePointer = function(description) {
27995 var structOffset = this.parseOffset16();
27996 if (structOffset > 0) {
27997 // NULL offset => return undefined
27998 return new Parser(this.data, this.offset + structOffset).parseStruct(
27999 description
28000 );
28001 }
28002 return undefined;
28003 };
28004
28005 Parser.prototype.parsePointer32 = function(description) {
28006 var structOffset = this.parseOffset32();
28007 if (structOffset > 0) {
28008 // NULL offset => return undefined
28009 return new Parser(this.data, this.offset + structOffset).parseStruct(
28010 description
28011 );
28012 }
28013 return undefined;
28014 };
28015
28016 /**
28017 * Parse a list of offsets to lists of 16-bit integers,
28018 * or a list of offsets to lists of offsets to any kind of items.
28019 * If itemCallback is not provided, a list of list of UShort is assumed.
28020 * If provided, itemCallback is called on each item and must parse the item.
28021 * See examples in tables/gsub.js
28022 */
28023 Parser.prototype.parseListOfLists = function(itemCallback) {
28024 var this$1 = this;
28025
28026 var offsets = this.parseOffset16List();
28027 var count = offsets.length;
28028 var relativeOffset = this.relativeOffset;
28029 var list = new Array(count);
28030 for (var i = 0; i < count; i++) {
28031 var start = offsets[i];
28032 if (start === 0) {
28033 // NULL offset
28034 // Add i as owned property to list. Convenient with assert.
28035 list[i] = undefined;
28036 continue;
28037 }
28038 this$1.relativeOffset = start;
28039 if (itemCallback) {
28040 var subOffsets = this$1.parseOffset16List();
28041 var subList = new Array(subOffsets.length);
28042 for (var j = 0; j < subOffsets.length; j++) {
28043 this$1.relativeOffset = start + subOffsets[j];
28044 subList[j] = itemCallback.call(this$1);
28045 }
28046 list[i] = subList;
28047 } else {
28048 list[i] = this$1.parseUShortList();
28049 }
28050 }
28051 this.relativeOffset = relativeOffset;
28052 return list;
28053 };
28054
28055 ///// Complex tables parsing //////////////////////////////////
28056
28057 // Parse a coverage table in a GSUB, GPOS or GDEF table.
28058 // https://www.microsoft.com/typography/OTSPEC/chapter2.htm
28059 // parser.offset must point to the start of the table containing the coverage.
28060 Parser.prototype.parseCoverage = function() {
28061 var this$1 = this;
28062
28063 var startOffset = this.offset + this.relativeOffset;
28064 var format = this.parseUShort();
28065 var count = this.parseUShort();
28066 if (format === 1) {
28067 return {
28068 format: 1,
28069 glyphs: this.parseUShortList(count)
28070 };
28071 } else if (format === 2) {
28072 var ranges = new Array(count);
28073 for (var i = 0; i < count; i++) {
28074 ranges[i] = {
28075 start: this$1.parseUShort(),
28076 end: this$1.parseUShort(),
28077 index: this$1.parseUShort()
28078 };
28079 }
28080 return {
28081 format: 2,
28082 ranges: ranges
28083 };
28084 }
28085 throw new Error(
28086 '0x' + startOffset.toString(16) + ': Coverage format must be 1 or 2.'
28087 );
28088 };
28089
28090 // Parse a Class Definition Table in a GSUB, GPOS or GDEF table.
28091 // https://www.microsoft.com/typography/OTSPEC/chapter2.htm
28092 Parser.prototype.parseClassDef = function() {
28093 var startOffset = this.offset + this.relativeOffset;
28094 var format = this.parseUShort();
28095 if (format === 1) {
28096 return {
28097 format: 1,
28098 startGlyph: this.parseUShort(),
28099 classes: this.parseUShortList()
28100 };
28101 } else if (format === 2) {
28102 return {
28103 format: 2,
28104 ranges: this.parseRecordList({
28105 start: Parser.uShort,
28106 end: Parser.uShort,
28107 classId: Parser.uShort
28108 })
28109 };
28110 }
28111 throw new Error(
28112 '0x' + startOffset.toString(16) + ': ClassDef format must be 1 or 2.'
28113 );
28114 };
28115
28116 ///// Static methods ///////////////////////////////////
28117 // These convenience methods can be used as callbacks and should be called with "this" context set to a Parser instance.
28118
28119 Parser.list = function(count, itemCallback) {
28120 return function() {
28121 return this.parseList(count, itemCallback);
28122 };
28123 };
28124
28125 Parser.list32 = function(count, itemCallback) {
28126 return function() {
28127 return this.parseList32(count, itemCallback);
28128 };
28129 };
28130
28131 Parser.recordList = function(count, recordDescription) {
28132 return function() {
28133 return this.parseRecordList(count, recordDescription);
28134 };
28135 };
28136
28137 Parser.recordList32 = function(count, recordDescription) {
28138 return function() {
28139 return this.parseRecordList32(count, recordDescription);
28140 };
28141 };
28142
28143 Parser.pointer = function(description) {
28144 return function() {
28145 return this.parsePointer(description);
28146 };
28147 };
28148
28149 Parser.pointer32 = function(description) {
28150 return function() {
28151 return this.parsePointer32(description);
28152 };
28153 };
28154
28155 Parser.tag = Parser.prototype.parseTag;
28156 Parser.byte = Parser.prototype.parseByte;
28157 Parser.uShort = Parser.offset16 = Parser.prototype.parseUShort;
28158 Parser.uShortList = Parser.prototype.parseUShortList;
28159 Parser.uLong = Parser.offset32 = Parser.prototype.parseULong;
28160 Parser.uLongList = Parser.prototype.parseULongList;
28161 Parser.struct = Parser.prototype.parseStruct;
28162 Parser.coverage = Parser.prototype.parseCoverage;
28163 Parser.classDef = Parser.prototype.parseClassDef;
28164
28165 ///// Script, Feature, Lookup lists ///////////////////////////////////////////////
28166 // https://www.microsoft.com/typography/OTSPEC/chapter2.htm
28167
28168 var langSysTable = {
28169 reserved: Parser.uShort,
28170 reqFeatureIndex: Parser.uShort,
28171 featureIndexes: Parser.uShortList
28172 };
28173
28174 Parser.prototype.parseScriptList = function() {
28175 return (
28176 this.parsePointer(
28177 Parser.recordList({
28178 tag: Parser.tag,
28179 script: Parser.pointer({
28180 defaultLangSys: Parser.pointer(langSysTable),
28181 langSysRecords: Parser.recordList({
28182 tag: Parser.tag,
28183 langSys: Parser.pointer(langSysTable)
28184 })
28185 })
28186 })
28187 ) || []
28188 );
28189 };
28190
28191 Parser.prototype.parseFeatureList = function() {
28192 return (
28193 this.parsePointer(
28194 Parser.recordList({
28195 tag: Parser.tag,
28196 feature: Parser.pointer({
28197 featureParams: Parser.offset16,
28198 lookupListIndexes: Parser.uShortList
28199 })
28200 })
28201 ) || []
28202 );
28203 };
28204
28205 Parser.prototype.parseLookupList = function(lookupTableParsers) {
28206 return (
28207 this.parsePointer(
28208 Parser.list(
28209 Parser.pointer(function() {
28210 var lookupType = this.parseUShort();
28211 check.argument(
28212 1 <= lookupType && lookupType <= 9,
28213 'GPOS/GSUB lookup type ' + lookupType + ' unknown.'
28214 );
28215 var lookupFlag = this.parseUShort();
28216 var useMarkFilteringSet = lookupFlag & 0x10;
28217 return {
28218 lookupType: lookupType,
28219 lookupFlag: lookupFlag,
28220 subtables: this.parseList(
28221 Parser.pointer(lookupTableParsers[lookupType])
28222 ),
28223 markFilteringSet: useMarkFilteringSet
28224 ? this.parseUShort()
28225 : undefined
28226 };
28227 })
28228 )
28229 ) || []
28230 );
28231 };
28232
28233 Parser.prototype.parseFeatureVariationsList = function() {
28234 return (
28235 this.parsePointer32(function() {
28236 var majorVersion = this.parseUShort();
28237 var minorVersion = this.parseUShort();
28238 check.argument(
28239 majorVersion === 1 && minorVersion < 1,
28240 'GPOS/GSUB feature variations table unknown.'
28241 );
28242 var featureVariations = this.parseRecordList32({
28243 conditionSetOffset: Parser.offset32,
28244 featureTableSubstitutionOffset: Parser.offset32
28245 });
28246 return featureVariations;
28247 }) || []
28248 );
28249 };
28250
28251 var parse = {
28252 getByte: getByte,
28253 getCard8: getByte,
28254 getUShort: getUShort,
28255 getCard16: getUShort,
28256 getShort: getShort,
28257 getULong: getULong,
28258 getFixed: getFixed,
28259 getTag: getTag,
28260 getOffset: getOffset,
28261 getBytes: getBytes,
28262 bytesToString: bytesToString,
28263 Parser: Parser
28264 };
28265
28266 // The `cmap` table stores the mappings from characters to glyphs.
28267
28268 function parseCmapTableFormat12(cmap, p) {
28269 //Skip reserved.
28270 p.parseUShort();
28271
28272 // Length in bytes of the sub-tables.
28273 cmap.length = p.parseULong();
28274 cmap.language = p.parseULong();
28275
28276 var groupCount;
28277 cmap.groupCount = groupCount = p.parseULong();
28278 cmap.glyphIndexMap = {};
28279
28280 for (var i = 0; i < groupCount; i += 1) {
28281 var startCharCode = p.parseULong();
28282 var endCharCode = p.parseULong();
28283 var startGlyphId = p.parseULong();
28284
28285 for (var c = startCharCode; c <= endCharCode; c += 1) {
28286 cmap.glyphIndexMap[c] = startGlyphId;
28287 startGlyphId++;
28288 }
28289 }
28290 }
28291
28292 function parseCmapTableFormat4(cmap, p, data, start, offset) {
28293 // Length in bytes of the sub-tables.
28294 cmap.length = p.parseUShort();
28295 cmap.language = p.parseUShort();
28296
28297 // segCount is stored x 2.
28298 var segCount;
28299 cmap.segCount = segCount = p.parseUShort() >> 1;
28300
28301 // Skip searchRange, entrySelector, rangeShift.
28302 p.skip('uShort', 3);
28303
28304 // The "unrolled" mapping from character codes to glyph indices.
28305 cmap.glyphIndexMap = {};
28306 var endCountParser = new parse.Parser(data, start + offset + 14);
28307 var startCountParser = new parse.Parser(
28308 data,
28309 start + offset + 16 + segCount * 2
28310 );
28311 var idDeltaParser = new parse.Parser(
28312 data,
28313 start + offset + 16 + segCount * 4
28314 );
28315 var idRangeOffsetParser = new parse.Parser(
28316 data,
28317 start + offset + 16 + segCount * 6
28318 );
28319 var glyphIndexOffset = start + offset + 16 + segCount * 8;
28320 for (var i = 0; i < segCount - 1; i += 1) {
28321 var glyphIndex = void 0;
28322 var endCount = endCountParser.parseUShort();
28323 var startCount = startCountParser.parseUShort();
28324 var idDelta = idDeltaParser.parseShort();
28325 var idRangeOffset = idRangeOffsetParser.parseUShort();
28326 for (var c = startCount; c <= endCount; c += 1) {
28327 if (idRangeOffset !== 0) {
28328 // The idRangeOffset is relative to the current position in the idRangeOffset array.
28329 // Take the current offset in the idRangeOffset array.
28330 glyphIndexOffset =
28331 idRangeOffsetParser.offset + idRangeOffsetParser.relativeOffset - 2;
28332
28333 // Add the value of the idRangeOffset, which will move us into the glyphIndex array.
28334 glyphIndexOffset += idRangeOffset;
28335
28336 // Then add the character index of the current segment, multiplied by 2 for USHORTs.
28337 glyphIndexOffset += (c - startCount) * 2;
28338 glyphIndex = parse.getUShort(data, glyphIndexOffset);
28339 if (glyphIndex !== 0) {
28340 glyphIndex = (glyphIndex + idDelta) & 0xffff;
28341 }
28342 } else {
28343 glyphIndex = (c + idDelta) & 0xffff;
28344 }
28345
28346 cmap.glyphIndexMap[c] = glyphIndex;
28347 }
28348 }
28349 }
28350
28351 // Parse the `cmap` table. This table stores the mappings from characters to glyphs.
28352 // There are many available formats, but we only support the Windows format 4 and 12.
28353 // This function returns a `CmapEncoding` object or null if no supported format could be found.
28354 function parseCmapTable(data, start) {
28355 var cmap = {};
28356 cmap.version = parse.getUShort(data, start);
28357 check.argument(cmap.version === 0, 'cmap table version should be 0.');
28358
28359 // The cmap table can contain many sub-tables, each with their own format.
28360 // We're only interested in a "platform 0" (Unicode format) and "platform 3" (Windows format) table.
28361 cmap.numTables = parse.getUShort(data, start + 2);
28362 var offset = -1;
28363 for (var i = cmap.numTables - 1; i >= 0; i -= 1) {
28364 var platformId = parse.getUShort(data, start + 4 + i * 8);
28365 var encodingId = parse.getUShort(data, start + 4 + i * 8 + 2);
28366 if (
28367 (platformId === 3 &&
28368 (encodingId === 0 || encodingId === 1 || encodingId === 10)) ||
28369 (platformId === 0 &&
28370 (encodingId === 0 ||
28371 encodingId === 1 ||
28372 encodingId === 2 ||
28373 encodingId === 3 ||
28374 encodingId === 4))
28375 ) {
28376 offset = parse.getULong(data, start + 4 + i * 8 + 4);
28377 break;
28378 }
28379 }
28380
28381 if (offset === -1) {
28382 // There is no cmap table in the font that we support.
28383 throw new Error('No valid cmap sub-tables found.');
28384 }
28385
28386 var p = new parse.Parser(data, start + offset);
28387 cmap.format = p.parseUShort();
28388
28389 if (cmap.format === 12) {
28390 parseCmapTableFormat12(cmap, p);
28391 } else if (cmap.format === 4) {
28392 parseCmapTableFormat4(cmap, p, data, start, offset);
28393 } else {
28394 throw new Error(
28395 'Only format 4 and 12 cmap tables are supported (found format ' +
28396 cmap.format +
28397 ').'
28398 );
28399 }
28400
28401 return cmap;
28402 }
28403
28404 function addSegment(t, code, glyphIndex) {
28405 t.segments.push({
28406 end: code,
28407 start: code,
28408 delta: -(code - glyphIndex),
28409 offset: 0,
28410 glyphIndex: glyphIndex
28411 });
28412 }
28413
28414 function addTerminatorSegment(t) {
28415 t.segments.push({
28416 end: 0xffff,
28417 start: 0xffff,
28418 delta: 1,
28419 offset: 0
28420 });
28421 }
28422
28423 // Make cmap table, format 4 by default, 12 if needed only
28424 function makeCmapTable(glyphs) {
28425 // Plan 0 is the base Unicode Plan but emojis, for example are on another plan, and needs cmap 12 format (with 32bit)
28426 var isPlan0Only = true;
28427 var i;
28428
28429 // Check if we need to add cmap format 12 or if format 4 only is fine
28430 for (i = glyphs.length - 1; i > 0; i -= 1) {
28431 var g = glyphs.get(i);
28432 if (g.unicode > 65535) {
28433 console.log('Adding CMAP format 12 (needed!)');
28434 isPlan0Only = false;
28435 break;
28436 }
28437 }
28438
28439 var cmapTable = [
28440 { name: 'version', type: 'USHORT', value: 0 },
28441 { name: 'numTables', type: 'USHORT', value: isPlan0Only ? 1 : 2 },
28442
28443 // CMAP 4 header
28444 { name: 'platformID', type: 'USHORT', value: 3 },
28445 { name: 'encodingID', type: 'USHORT', value: 1 },
28446 { name: 'offset', type: 'ULONG', value: isPlan0Only ? 12 : 12 + 8 }
28447 ];
28448
28449 if (!isPlan0Only) {
28450 cmapTable = cmapTable.concat([
28451 // CMAP 12 header
28452 { name: 'cmap12PlatformID', type: 'USHORT', value: 3 }, // We encode only for PlatformID = 3 (Windows) because it is supported everywhere
28453 { name: 'cmap12EncodingID', type: 'USHORT', value: 10 },
28454 { name: 'cmap12Offset', type: 'ULONG', value: 0 }
28455 ]);
28456 }
28457
28458 cmapTable = cmapTable.concat([
28459 // CMAP 4 Subtable
28460 { name: 'format', type: 'USHORT', value: 4 },
28461 { name: 'cmap4Length', type: 'USHORT', value: 0 },
28462 { name: 'language', type: 'USHORT', value: 0 },
28463 { name: 'segCountX2', type: 'USHORT', value: 0 },
28464 { name: 'searchRange', type: 'USHORT', value: 0 },
28465 { name: 'entrySelector', type: 'USHORT', value: 0 },
28466 { name: 'rangeShift', type: 'USHORT', value: 0 }
28467 ]);
28468
28469 var t = new table.Table('cmap', cmapTable);
28470
28471 t.segments = [];
28472 for (i = 0; i < glyphs.length; i += 1) {
28473 var glyph = glyphs.get(i);
28474 for (var j = 0; j < glyph.unicodes.length; j += 1) {
28475 addSegment(t, glyph.unicodes[j], i);
28476 }
28477
28478 t.segments = t.segments.sort(function(a, b) {
28479 return a.start - b.start;
28480 });
28481 }
28482
28483 addTerminatorSegment(t);
28484
28485 var segCount = t.segments.length;
28486 var segCountToRemove = 0;
28487
28488 // CMAP 4
28489 // Set up parallel segment arrays.
28490 var endCounts = [];
28491 var startCounts = [];
28492 var idDeltas = [];
28493 var idRangeOffsets = [];
28494 var glyphIds = [];
28495
28496 // CMAP 12
28497 var cmap12Groups = [];
28498
28499 // Reminder this loop is not following the specification at 100%
28500 // The specification -> find suites of characters and make a group
28501 // Here we're doing one group for each letter
28502 // Doing as the spec can save 8 times (or more) space
28503 for (i = 0; i < segCount; i += 1) {
28504 var segment = t.segments[i];
28505
28506 // CMAP 4
28507 if (segment.end <= 65535 && segment.start <= 65535) {
28508 endCounts = endCounts.concat({
28509 name: 'end_' + i,
28510 type: 'USHORT',
28511 value: segment.end
28512 });
28513 startCounts = startCounts.concat({
28514 name: 'start_' + i,
28515 type: 'USHORT',
28516 value: segment.start
28517 });
28518 idDeltas = idDeltas.concat({
28519 name: 'idDelta_' + i,
28520 type: 'SHORT',
28521 value: segment.delta
28522 });
28523 idRangeOffsets = idRangeOffsets.concat({
28524 name: 'idRangeOffset_' + i,
28525 type: 'USHORT',
28526 value: segment.offset
28527 });
28528 if (segment.glyphId !== undefined) {
28529 glyphIds = glyphIds.concat({
28530 name: 'glyph_' + i,
28531 type: 'USHORT',
28532 value: segment.glyphId
28533 });
28534 }
28535 } else {
28536 // Skip Unicode > 65535 (16bit unsigned max) for CMAP 4, will be added in CMAP 12
28537 segCountToRemove += 1;
28538 }
28539
28540 // CMAP 12
28541 // Skip Terminator Segment
28542 if (!isPlan0Only && segment.glyphIndex !== undefined) {
28543 cmap12Groups = cmap12Groups.concat({
28544 name: 'cmap12Start_' + i,
28545 type: 'ULONG',
28546 value: segment.start
28547 });
28548 cmap12Groups = cmap12Groups.concat({
28549 name: 'cmap12End_' + i,
28550 type: 'ULONG',
28551 value: segment.end
28552 });
28553 cmap12Groups = cmap12Groups.concat({
28554 name: 'cmap12Glyph_' + i,
28555 type: 'ULONG',
28556 value: segment.glyphIndex
28557 });
28558 }
28559 }
28560
28561 // CMAP 4 Subtable
28562 t.segCountX2 = (segCount - segCountToRemove) * 2;
28563 t.searchRange =
28564 Math.pow(
28565 2,
28566 Math.floor(Math.log(segCount - segCountToRemove) / Math.log(2))
28567 ) * 2;
28568 t.entrySelector = Math.log(t.searchRange / 2) / Math.log(2);
28569 t.rangeShift = t.segCountX2 - t.searchRange;
28570
28571 t.fields = t.fields.concat(endCounts);
28572 t.fields.push({ name: 'reservedPad', type: 'USHORT', value: 0 });
28573 t.fields = t.fields.concat(startCounts);
28574 t.fields = t.fields.concat(idDeltas);
28575 t.fields = t.fields.concat(idRangeOffsets);
28576 t.fields = t.fields.concat(glyphIds);
28577
28578 t.cmap4Length =
28579 14 + // Subtable header
28580 endCounts.length * 2 +
28581 2 + // reservedPad
28582 startCounts.length * 2 +
28583 idDeltas.length * 2 +
28584 idRangeOffsets.length * 2 +
28585 glyphIds.length * 2;
28586
28587 if (!isPlan0Only) {
28588 // CMAP 12 Subtable
28589 var cmap12Length =
28590 16 + // Subtable header
28591 cmap12Groups.length * 4;
28592
28593 t.cmap12Offset = 12 + 2 * 2 + 4 + t.cmap4Length;
28594 t.fields = t.fields.concat([
28595 { name: 'cmap12Format', type: 'USHORT', value: 12 },
28596 { name: 'cmap12Reserved', type: 'USHORT', value: 0 },
28597 { name: 'cmap12Length', type: 'ULONG', value: cmap12Length },
28598 { name: 'cmap12Language', type: 'ULONG', value: 0 },
28599 { name: 'cmap12nGroups', type: 'ULONG', value: cmap12Groups.length / 3 }
28600 ]);
28601
28602 t.fields = t.fields.concat(cmap12Groups);
28603 }
28604
28605 return t;
28606 }
28607
28608 var cmap = { parse: parseCmapTable, make: makeCmapTable };
28609
28610 // Glyph encoding
28611
28612 var cffStandardStrings = [
28613 '.notdef',
28614 'space',
28615 'exclam',
28616 'quotedbl',
28617 'numbersign',
28618 'dollar',
28619 'percent',
28620 'ampersand',
28621 'quoteright',
28622 'parenleft',
28623 'parenright',
28624 'asterisk',
28625 'plus',
28626 'comma',
28627 'hyphen',
28628 'period',
28629 'slash',
28630 'zero',
28631 'one',
28632 'two',
28633 'three',
28634 'four',
28635 'five',
28636 'six',
28637 'seven',
28638 'eight',
28639 'nine',
28640 'colon',
28641 'semicolon',
28642 'less',
28643 'equal',
28644 'greater',
28645 'question',
28646 'at',
28647 'A',
28648 'B',
28649 'C',
28650 'D',
28651 'E',
28652 'F',
28653 'G',
28654 'H',
28655 'I',
28656 'J',
28657 'K',
28658 'L',
28659 'M',
28660 'N',
28661 'O',
28662 'P',
28663 'Q',
28664 'R',
28665 'S',
28666 'T',
28667 'U',
28668 'V',
28669 'W',
28670 'X',
28671 'Y',
28672 'Z',
28673 'bracketleft',
28674 'backslash',
28675 'bracketright',
28676 'asciicircum',
28677 'underscore',
28678 'quoteleft',
28679 'a',
28680 'b',
28681 'c',
28682 'd',
28683 'e',
28684 'f',
28685 'g',
28686 'h',
28687 'i',
28688 'j',
28689 'k',
28690 'l',
28691 'm',
28692 'n',
28693 'o',
28694 'p',
28695 'q',
28696 'r',
28697 's',
28698 't',
28699 'u',
28700 'v',
28701 'w',
28702 'x',
28703 'y',
28704 'z',
28705 'braceleft',
28706 'bar',
28707 'braceright',
28708 'asciitilde',
28709 'exclamdown',
28710 'cent',
28711 'sterling',
28712 'fraction',
28713 'yen',
28714 'florin',
28715 'section',
28716 'currency',
28717 'quotesingle',
28718 'quotedblleft',
28719 'guillemotleft',
28720 'guilsinglleft',
28721 'guilsinglright',
28722 'fi',
28723 'fl',
28724 'endash',
28725 'dagger',
28726 'daggerdbl',
28727 'periodcentered',
28728 'paragraph',
28729 'bullet',
28730 'quotesinglbase',
28731 'quotedblbase',
28732 'quotedblright',
28733 'guillemotright',
28734 'ellipsis',
28735 'perthousand',
28736 'questiondown',
28737 'grave',
28738 'acute',
28739 'circumflex',
28740 'tilde',
28741 'macron',
28742 'breve',
28743 'dotaccent',
28744 'dieresis',
28745 'ring',
28746 'cedilla',
28747 'hungarumlaut',
28748 'ogonek',
28749 'caron',
28750 'emdash',
28751 'AE',
28752 'ordfeminine',
28753 'Lslash',
28754 'Oslash',
28755 'OE',
28756 'ordmasculine',
28757 'ae',
28758 'dotlessi',
28759 'lslash',
28760 'oslash',
28761 'oe',
28762 'germandbls',
28763 'onesuperior',
28764 'logicalnot',
28765 'mu',
28766 'trademark',
28767 'Eth',
28768 'onehalf',
28769 'plusminus',
28770 'Thorn',
28771 'onequarter',
28772 'divide',
28773 'brokenbar',
28774 'degree',
28775 'thorn',
28776 'threequarters',
28777 'twosuperior',
28778 'registered',
28779 'minus',
28780 'eth',
28781 'multiply',
28782 'threesuperior',
28783 'copyright',
28784 'Aacute',
28785 'Acircumflex',
28786 'Adieresis',
28787 'Agrave',
28788 'Aring',
28789 'Atilde',
28790 'Ccedilla',
28791 'Eacute',
28792 'Ecircumflex',
28793 'Edieresis',
28794 'Egrave',
28795 'Iacute',
28796 'Icircumflex',
28797 'Idieresis',
28798 'Igrave',
28799 'Ntilde',
28800 'Oacute',
28801 'Ocircumflex',
28802 'Odieresis',
28803 'Ograve',
28804 'Otilde',
28805 'Scaron',
28806 'Uacute',
28807 'Ucircumflex',
28808 'Udieresis',
28809 'Ugrave',
28810 'Yacute',
28811 'Ydieresis',
28812 'Zcaron',
28813 'aacute',
28814 'acircumflex',
28815 'adieresis',
28816 'agrave',
28817 'aring',
28818 'atilde',
28819 'ccedilla',
28820 'eacute',
28821 'ecircumflex',
28822 'edieresis',
28823 'egrave',
28824 'iacute',
28825 'icircumflex',
28826 'idieresis',
28827 'igrave',
28828 'ntilde',
28829 'oacute',
28830 'ocircumflex',
28831 'odieresis',
28832 'ograve',
28833 'otilde',
28834 'scaron',
28835 'uacute',
28836 'ucircumflex',
28837 'udieresis',
28838 'ugrave',
28839 'yacute',
28840 'ydieresis',
28841 'zcaron',
28842 'exclamsmall',
28843 'Hungarumlautsmall',
28844 'dollaroldstyle',
28845 'dollarsuperior',
28846 'ampersandsmall',
28847 'Acutesmall',
28848 'parenleftsuperior',
28849 'parenrightsuperior',
28850 '266 ff',
28851 'onedotenleader',
28852 'zerooldstyle',
28853 'oneoldstyle',
28854 'twooldstyle',
28855 'threeoldstyle',
28856 'fouroldstyle',
28857 'fiveoldstyle',
28858 'sixoldstyle',
28859 'sevenoldstyle',
28860 'eightoldstyle',
28861 'nineoldstyle',
28862 'commasuperior',
28863 'threequartersemdash',
28864 'periodsuperior',
28865 'questionsmall',
28866 'asuperior',
28867 'bsuperior',
28868 'centsuperior',
28869 'dsuperior',
28870 'esuperior',
28871 'isuperior',
28872 'lsuperior',
28873 'msuperior',
28874 'nsuperior',
28875 'osuperior',
28876 'rsuperior',
28877 'ssuperior',
28878 'tsuperior',
28879 'ff',
28880 'ffi',
28881 'ffl',
28882 'parenleftinferior',
28883 'parenrightinferior',
28884 'Circumflexsmall',
28885 'hyphensuperior',
28886 'Gravesmall',
28887 'Asmall',
28888 'Bsmall',
28889 'Csmall',
28890 'Dsmall',
28891 'Esmall',
28892 'Fsmall',
28893 'Gsmall',
28894 'Hsmall',
28895 'Ismall',
28896 'Jsmall',
28897 'Ksmall',
28898 'Lsmall',
28899 'Msmall',
28900 'Nsmall',
28901 'Osmall',
28902 'Psmall',
28903 'Qsmall',
28904 'Rsmall',
28905 'Ssmall',
28906 'Tsmall',
28907 'Usmall',
28908 'Vsmall',
28909 'Wsmall',
28910 'Xsmall',
28911 'Ysmall',
28912 'Zsmall',
28913 'colonmonetary',
28914 'onefitted',
28915 'rupiah',
28916 'Tildesmall',
28917 'exclamdownsmall',
28918 'centoldstyle',
28919 'Lslashsmall',
28920 'Scaronsmall',
28921 'Zcaronsmall',
28922 'Dieresissmall',
28923 'Brevesmall',
28924 'Caronsmall',
28925 'Dotaccentsmall',
28926 'Macronsmall',
28927 'figuredash',
28928 'hypheninferior',
28929 'Ogoneksmall',
28930 'Ringsmall',
28931 'Cedillasmall',
28932 'questiondownsmall',
28933 'oneeighth',
28934 'threeeighths',
28935 'fiveeighths',
28936 'seveneighths',
28937 'onethird',
28938 'twothirds',
28939 'zerosuperior',
28940 'foursuperior',
28941 'fivesuperior',
28942 'sixsuperior',
28943 'sevensuperior',
28944 'eightsuperior',
28945 'ninesuperior',
28946 'zeroinferior',
28947 'oneinferior',
28948 'twoinferior',
28949 'threeinferior',
28950 'fourinferior',
28951 'fiveinferior',
28952 'sixinferior',
28953 'seveninferior',
28954 'eightinferior',
28955 'nineinferior',
28956 'centinferior',
28957 'dollarinferior',
28958 'periodinferior',
28959 'commainferior',
28960 'Agravesmall',
28961 'Aacutesmall',
28962 'Acircumflexsmall',
28963 'Atildesmall',
28964 'Adieresissmall',
28965 'Aringsmall',
28966 'AEsmall',
28967 'Ccedillasmall',
28968 'Egravesmall',
28969 'Eacutesmall',
28970 'Ecircumflexsmall',
28971 'Edieresissmall',
28972 'Igravesmall',
28973 'Iacutesmall',
28974 'Icircumflexsmall',
28975 'Idieresissmall',
28976 'Ethsmall',
28977 'Ntildesmall',
28978 'Ogravesmall',
28979 'Oacutesmall',
28980 'Ocircumflexsmall',
28981 'Otildesmall',
28982 'Odieresissmall',
28983 'OEsmall',
28984 'Oslashsmall',
28985 'Ugravesmall',
28986 'Uacutesmall',
28987 'Ucircumflexsmall',
28988 'Udieresissmall',
28989 'Yacutesmall',
28990 'Thornsmall',
28991 'Ydieresissmall',
28992 '001.000',
28993 '001.001',
28994 '001.002',
28995 '001.003',
28996 'Black',
28997 'Bold',
28998 'Book',
28999 'Light',
29000 'Medium',
29001 'Regular',
29002 'Roman',
29003 'Semibold'
29004 ];
29005
29006 var cffStandardEncoding = [
29007 '',
29008 '',
29009 '',
29010 '',
29011 '',
29012 '',
29013 '',
29014 '',
29015 '',
29016 '',
29017 '',
29018 '',
29019 '',
29020 '',
29021 '',
29022 '',
29023 '',
29024 '',
29025 '',
29026 '',
29027 '',
29028 '',
29029 '',
29030 '',
29031 '',
29032 '',
29033 '',
29034 '',
29035 '',
29036 '',
29037 '',
29038 '',
29039 'space',
29040 'exclam',
29041 'quotedbl',
29042 'numbersign',
29043 'dollar',
29044 'percent',
29045 'ampersand',
29046 'quoteright',
29047 'parenleft',
29048 'parenright',
29049 'asterisk',
29050 'plus',
29051 'comma',
29052 'hyphen',
29053 'period',
29054 'slash',
29055 'zero',
29056 'one',
29057 'two',
29058 'three',
29059 'four',
29060 'five',
29061 'six',
29062 'seven',
29063 'eight',
29064 'nine',
29065 'colon',
29066 'semicolon',
29067 'less',
29068 'equal',
29069 'greater',
29070 'question',
29071 'at',
29072 'A',
29073 'B',
29074 'C',
29075 'D',
29076 'E',
29077 'F',
29078 'G',
29079 'H',
29080 'I',
29081 'J',
29082 'K',
29083 'L',
29084 'M',
29085 'N',
29086 'O',
29087 'P',
29088 'Q',
29089 'R',
29090 'S',
29091 'T',
29092 'U',
29093 'V',
29094 'W',
29095 'X',
29096 'Y',
29097 'Z',
29098 'bracketleft',
29099 'backslash',
29100 'bracketright',
29101 'asciicircum',
29102 'underscore',
29103 'quoteleft',
29104 'a',
29105 'b',
29106 'c',
29107 'd',
29108 'e',
29109 'f',
29110 'g',
29111 'h',
29112 'i',
29113 'j',
29114 'k',
29115 'l',
29116 'm',
29117 'n',
29118 'o',
29119 'p',
29120 'q',
29121 'r',
29122 's',
29123 't',
29124 'u',
29125 'v',
29126 'w',
29127 'x',
29128 'y',
29129 'z',
29130 'braceleft',
29131 'bar',
29132 'braceright',
29133 'asciitilde',
29134 '',
29135 '',
29136 '',
29137 '',
29138 '',
29139 '',
29140 '',
29141 '',
29142 '',
29143 '',
29144 '',
29145 '',
29146 '',
29147 '',
29148 '',
29149 '',
29150 '',
29151 '',
29152 '',
29153 '',
29154 '',
29155 '',
29156 '',
29157 '',
29158 '',
29159 '',
29160 '',
29161 '',
29162 '',
29163 '',
29164 '',
29165 '',
29166 '',
29167 '',
29168 'exclamdown',
29169 'cent',
29170 'sterling',
29171 'fraction',
29172 'yen',
29173 'florin',
29174 'section',
29175 'currency',
29176 'quotesingle',
29177 'quotedblleft',
29178 'guillemotleft',
29179 'guilsinglleft',
29180 'guilsinglright',
29181 'fi',
29182 'fl',
29183 '',
29184 'endash',
29185 'dagger',
29186 'daggerdbl',
29187 'periodcentered',
29188 '',
29189 'paragraph',
29190 'bullet',
29191 'quotesinglbase',
29192 'quotedblbase',
29193 'quotedblright',
29194 'guillemotright',
29195 'ellipsis',
29196 'perthousand',
29197 '',
29198 'questiondown',
29199 '',
29200 'grave',
29201 'acute',
29202 'circumflex',
29203 'tilde',
29204 'macron',
29205 'breve',
29206 'dotaccent',
29207 'dieresis',
29208 '',
29209 'ring',
29210 'cedilla',
29211 '',
29212 'hungarumlaut',
29213 'ogonek',
29214 'caron',
29215 'emdash',
29216 '',
29217 '',
29218 '',
29219 '',
29220 '',
29221 '',
29222 '',
29223 '',
29224 '',
29225 '',
29226 '',
29227 '',
29228 '',
29229 '',
29230 '',
29231 '',
29232 'AE',
29233 '',
29234 'ordfeminine',
29235 '',
29236 '',
29237 '',
29238 '',
29239 'Lslash',
29240 'Oslash',
29241 'OE',
29242 'ordmasculine',
29243 '',
29244 '',
29245 '',
29246 '',
29247 '',
29248 'ae',
29249 '',
29250 '',
29251 '',
29252 'dotlessi',
29253 '',
29254 '',
29255 'lslash',
29256 'oslash',
29257 'oe',
29258 'germandbls'
29259 ];
29260
29261 var cffExpertEncoding = [
29262 '',
29263 '',
29264 '',
29265 '',
29266 '',
29267 '',
29268 '',
29269 '',
29270 '',
29271 '',
29272 '',
29273 '',
29274 '',
29275 '',
29276 '',
29277 '',
29278 '',
29279 '',
29280 '',
29281 '',
29282 '',
29283 '',
29284 '',
29285 '',
29286 '',
29287 '',
29288 '',
29289 '',
29290 '',
29291 '',
29292 '',
29293 '',
29294 'space',
29295 'exclamsmall',
29296 'Hungarumlautsmall',
29297 '',
29298 'dollaroldstyle',
29299 'dollarsuperior',
29300 'ampersandsmall',
29301 'Acutesmall',
29302 'parenleftsuperior',
29303 'parenrightsuperior',
29304 'twodotenleader',
29305 'onedotenleader',
29306 'comma',
29307 'hyphen',
29308 'period',
29309 'fraction',
29310 'zerooldstyle',
29311 'oneoldstyle',
29312 'twooldstyle',
29313 'threeoldstyle',
29314 'fouroldstyle',
29315 'fiveoldstyle',
29316 'sixoldstyle',
29317 'sevenoldstyle',
29318 'eightoldstyle',
29319 'nineoldstyle',
29320 'colon',
29321 'semicolon',
29322 'commasuperior',
29323 'threequartersemdash',
29324 'periodsuperior',
29325 'questionsmall',
29326 '',
29327 'asuperior',
29328 'bsuperior',
29329 'centsuperior',
29330 'dsuperior',
29331 'esuperior',
29332 '',
29333 '',
29334 'isuperior',
29335 '',
29336 '',
29337 'lsuperior',
29338 'msuperior',
29339 'nsuperior',
29340 'osuperior',
29341 '',
29342 '',
29343 'rsuperior',
29344 'ssuperior',
29345 'tsuperior',
29346 '',
29347 'ff',
29348 'fi',
29349 'fl',
29350 'ffi',
29351 'ffl',
29352 'parenleftinferior',
29353 '',
29354 'parenrightinferior',
29355 'Circumflexsmall',
29356 'hyphensuperior',
29357 'Gravesmall',
29358 'Asmall',
29359 'Bsmall',
29360 'Csmall',
29361 'Dsmall',
29362 'Esmall',
29363 'Fsmall',
29364 'Gsmall',
29365 'Hsmall',
29366 'Ismall',
29367 'Jsmall',
29368 'Ksmall',
29369 'Lsmall',
29370 'Msmall',
29371 'Nsmall',
29372 'Osmall',
29373 'Psmall',
29374 'Qsmall',
29375 'Rsmall',
29376 'Ssmall',
29377 'Tsmall',
29378 'Usmall',
29379 'Vsmall',
29380 'Wsmall',
29381 'Xsmall',
29382 'Ysmall',
29383 'Zsmall',
29384 'colonmonetary',
29385 'onefitted',
29386 'rupiah',
29387 'Tildesmall',
29388 '',
29389 '',
29390 '',
29391 '',
29392 '',
29393 '',
29394 '',
29395 '',
29396 '',
29397 '',
29398 '',
29399 '',
29400 '',
29401 '',
29402 '',
29403 '',
29404 '',
29405 '',
29406 '',
29407 '',
29408 '',
29409 '',
29410 '',
29411 '',
29412 '',
29413 '',
29414 '',
29415 '',
29416 '',
29417 '',
29418 '',
29419 '',
29420 '',
29421 '',
29422 'exclamdownsmall',
29423 'centoldstyle',
29424 'Lslashsmall',
29425 '',
29426 '',
29427 'Scaronsmall',
29428 'Zcaronsmall',
29429 'Dieresissmall',
29430 'Brevesmall',
29431 'Caronsmall',
29432 '',
29433 'Dotaccentsmall',
29434 '',
29435 '',
29436 'Macronsmall',
29437 '',
29438 '',
29439 'figuredash',
29440 'hypheninferior',
29441 '',
29442 '',
29443 'Ogoneksmall',
29444 'Ringsmall',
29445 'Cedillasmall',
29446 '',
29447 '',
29448 '',
29449 'onequarter',
29450 'onehalf',
29451 'threequarters',
29452 'questiondownsmall',
29453 'oneeighth',
29454 'threeeighths',
29455 'fiveeighths',
29456 'seveneighths',
29457 'onethird',
29458 'twothirds',
29459 '',
29460 '',
29461 'zerosuperior',
29462 'onesuperior',
29463 'twosuperior',
29464 'threesuperior',
29465 'foursuperior',
29466 'fivesuperior',
29467 'sixsuperior',
29468 'sevensuperior',
29469 'eightsuperior',
29470 'ninesuperior',
29471 'zeroinferior',
29472 'oneinferior',
29473 'twoinferior',
29474 'threeinferior',
29475 'fourinferior',
29476 'fiveinferior',
29477 'sixinferior',
29478 'seveninferior',
29479 'eightinferior',
29480 'nineinferior',
29481 'centinferior',
29482 'dollarinferior',
29483 'periodinferior',
29484 'commainferior',
29485 'Agravesmall',
29486 'Aacutesmall',
29487 'Acircumflexsmall',
29488 'Atildesmall',
29489 'Adieresissmall',
29490 'Aringsmall',
29491 'AEsmall',
29492 'Ccedillasmall',
29493 'Egravesmall',
29494 'Eacutesmall',
29495 'Ecircumflexsmall',
29496 'Edieresissmall',
29497 'Igravesmall',
29498 'Iacutesmall',
29499 'Icircumflexsmall',
29500 'Idieresissmall',
29501 'Ethsmall',
29502 'Ntildesmall',
29503 'Ogravesmall',
29504 'Oacutesmall',
29505 'Ocircumflexsmall',
29506 'Otildesmall',
29507 'Odieresissmall',
29508 'OEsmall',
29509 'Oslashsmall',
29510 'Ugravesmall',
29511 'Uacutesmall',
29512 'Ucircumflexsmall',
29513 'Udieresissmall',
29514 'Yacutesmall',
29515 'Thornsmall',
29516 'Ydieresissmall'
29517 ];
29518
29519 var standardNames = [
29520 '.notdef',
29521 '.null',
29522 'nonmarkingreturn',
29523 'space',
29524 'exclam',
29525 'quotedbl',
29526 'numbersign',
29527 'dollar',
29528 'percent',
29529 'ampersand',
29530 'quotesingle',
29531 'parenleft',
29532 'parenright',
29533 'asterisk',
29534 'plus',
29535 'comma',
29536 'hyphen',
29537 'period',
29538 'slash',
29539 'zero',
29540 'one',
29541 'two',
29542 'three',
29543 'four',
29544 'five',
29545 'six',
29546 'seven',
29547 'eight',
29548 'nine',
29549 'colon',
29550 'semicolon',
29551 'less',
29552 'equal',
29553 'greater',
29554 'question',
29555 'at',
29556 'A',
29557 'B',
29558 'C',
29559 'D',
29560 'E',
29561 'F',
29562 'G',
29563 'H',
29564 'I',
29565 'J',
29566 'K',
29567 'L',
29568 'M',
29569 'N',
29570 'O',
29571 'P',
29572 'Q',
29573 'R',
29574 'S',
29575 'T',
29576 'U',
29577 'V',
29578 'W',
29579 'X',
29580 'Y',
29581 'Z',
29582 'bracketleft',
29583 'backslash',
29584 'bracketright',
29585 'asciicircum',
29586 'underscore',
29587 'grave',
29588 'a',
29589 'b',
29590 'c',
29591 'd',
29592 'e',
29593 'f',
29594 'g',
29595 'h',
29596 'i',
29597 'j',
29598 'k',
29599 'l',
29600 'm',
29601 'n',
29602 'o',
29603 'p',
29604 'q',
29605 'r',
29606 's',
29607 't',
29608 'u',
29609 'v',
29610 'w',
29611 'x',
29612 'y',
29613 'z',
29614 'braceleft',
29615 'bar',
29616 'braceright',
29617 'asciitilde',
29618 'Adieresis',
29619 'Aring',
29620 'Ccedilla',
29621 'Eacute',
29622 'Ntilde',
29623 'Odieresis',
29624 'Udieresis',
29625 'aacute',
29626 'agrave',
29627 'acircumflex',
29628 'adieresis',
29629 'atilde',
29630 'aring',
29631 'ccedilla',
29632 'eacute',
29633 'egrave',
29634 'ecircumflex',
29635 'edieresis',
29636 'iacute',
29637 'igrave',
29638 'icircumflex',
29639 'idieresis',
29640 'ntilde',
29641 'oacute',
29642 'ograve',
29643 'ocircumflex',
29644 'odieresis',
29645 'otilde',
29646 'uacute',
29647 'ugrave',
29648 'ucircumflex',
29649 'udieresis',
29650 'dagger',
29651 'degree',
29652 'cent',
29653 'sterling',
29654 'section',
29655 'bullet',
29656 'paragraph',
29657 'germandbls',
29658 'registered',
29659 'copyright',
29660 'trademark',
29661 'acute',
29662 'dieresis',
29663 'notequal',
29664 'AE',
29665 'Oslash',
29666 'infinity',
29667 'plusminus',
29668 'lessequal',
29669 'greaterequal',
29670 'yen',
29671 'mu',
29672 'partialdiff',
29673 'summation',
29674 'product',
29675 'pi',
29676 'integral',
29677 'ordfeminine',
29678 'ordmasculine',
29679 'Omega',
29680 'ae',
29681 'oslash',
29682 'questiondown',
29683 'exclamdown',
29684 'logicalnot',
29685 'radical',
29686 'florin',
29687 'approxequal',
29688 'Delta',
29689 'guillemotleft',
29690 'guillemotright',
29691 'ellipsis',
29692 'nonbreakingspace',
29693 'Agrave',
29694 'Atilde',
29695 'Otilde',
29696 'OE',
29697 'oe',
29698 'endash',
29699 'emdash',
29700 'quotedblleft',
29701 'quotedblright',
29702 'quoteleft',
29703 'quoteright',
29704 'divide',
29705 'lozenge',
29706 'ydieresis',
29707 'Ydieresis',
29708 'fraction',
29709 'currency',
29710 'guilsinglleft',
29711 'guilsinglright',
29712 'fi',
29713 'fl',
29714 'daggerdbl',
29715 'periodcentered',
29716 'quotesinglbase',
29717 'quotedblbase',
29718 'perthousand',
29719 'Acircumflex',
29720 'Ecircumflex',
29721 'Aacute',
29722 'Edieresis',
29723 'Egrave',
29724 'Iacute',
29725 'Icircumflex',
29726 'Idieresis',
29727 'Igrave',
29728 'Oacute',
29729 'Ocircumflex',
29730 'apple',
29731 'Ograve',
29732 'Uacute',
29733 'Ucircumflex',
29734 'Ugrave',
29735 'dotlessi',
29736 'circumflex',
29737 'tilde',
29738 'macron',
29739 'breve',
29740 'dotaccent',
29741 'ring',
29742 'cedilla',
29743 'hungarumlaut',
29744 'ogonek',
29745 'caron',
29746 'Lslash',
29747 'lslash',
29748 'Scaron',
29749 'scaron',
29750 'Zcaron',
29751 'zcaron',
29752 'brokenbar',
29753 'Eth',
29754 'eth',
29755 'Yacute',
29756 'yacute',
29757 'Thorn',
29758 'thorn',
29759 'minus',
29760 'multiply',
29761 'onesuperior',
29762 'twosuperior',
29763 'threesuperior',
29764 'onehalf',
29765 'onequarter',
29766 'threequarters',
29767 'franc',
29768 'Gbreve',
29769 'gbreve',
29770 'Idotaccent',
29771 'Scedilla',
29772 'scedilla',
29773 'Cacute',
29774 'cacute',
29775 'Ccaron',
29776 'ccaron',
29777 'dcroat'
29778 ];
29779
29780 /**
29781 * This is the encoding used for fonts created from scratch.
29782 * It loops through all glyphs and finds the appropriate unicode value.
29783 * Since it's linear time, other encodings will be faster.
29784 * @exports opentype.DefaultEncoding
29785 * @class
29786 * @constructor
29787 * @param {opentype.Font}
29788 */
29789 function DefaultEncoding(font) {
29790 this.font = font;
29791 }
29792
29793 DefaultEncoding.prototype.charToGlyphIndex = function(c) {
29794 var code = c.codePointAt(0);
29795 var glyphs = this.font.glyphs;
29796 if (glyphs) {
29797 for (var i = 0; i < glyphs.length; i += 1) {
29798 var glyph = glyphs.get(i);
29799 for (var j = 0; j < glyph.unicodes.length; j += 1) {
29800 if (glyph.unicodes[j] === code) {
29801 return i;
29802 }
29803 }
29804 }
29805 }
29806 return null;
29807 };
29808
29809 /**
29810 * @exports opentype.CmapEncoding
29811 * @class
29812 * @constructor
29813 * @param {Object} cmap - a object with the cmap encoded data
29814 */
29815 function CmapEncoding(cmap) {
29816 this.cmap = cmap;
29817 }
29818
29819 /**
29820 * @param {string} c - the character
29821 * @return {number} The glyph index.
29822 */
29823 CmapEncoding.prototype.charToGlyphIndex = function(c) {
29824 return this.cmap.glyphIndexMap[c.codePointAt(0)] || 0;
29825 };
29826
29827 /**
29828 * @exports opentype.CffEncoding
29829 * @class
29830 * @constructor
29831 * @param {string} encoding - The encoding
29832 * @param {Array} charset - The character set.
29833 */
29834 function CffEncoding(encoding, charset) {
29835 this.encoding = encoding;
29836 this.charset = charset;
29837 }
29838
29839 /**
29840 * @param {string} s - The character
29841 * @return {number} The index.
29842 */
29843 CffEncoding.prototype.charToGlyphIndex = function(s) {
29844 var code = s.codePointAt(0);
29845 var charName = this.encoding[code];
29846 return this.charset.indexOf(charName);
29847 };
29848
29849 /**
29850 * @exports opentype.GlyphNames
29851 * @class
29852 * @constructor
29853 * @param {Object} post
29854 */
29855 function GlyphNames(post) {
29856 var this$1 = this;
29857
29858 switch (post.version) {
29859 case 1:
29860 this.names = standardNames.slice();
29861 break;
29862 case 2:
29863 this.names = new Array(post.numberOfGlyphs);
29864 for (var i = 0; i < post.numberOfGlyphs; i++) {
29865 if (post.glyphNameIndex[i] < standardNames.length) {
29866 this$1.names[i] = standardNames[post.glyphNameIndex[i]];
29867 } else {
29868 this$1.names[i] =
29869 post.names[post.glyphNameIndex[i] - standardNames.length];
29870 }
29871 }
29872
29873 break;
29874 case 2.5:
29875 this.names = new Array(post.numberOfGlyphs);
29876 for (var i$1 = 0; i$1 < post.numberOfGlyphs; i$1++) {
29877 this$1.names[i$1] = standardNames[i$1 + post.glyphNameIndex[i$1]];
29878 }
29879
29880 break;
29881 case 3:
29882 this.names = [];
29883 break;
29884 default:
29885 this.names = [];
29886 break;
29887 }
29888 }
29889
29890 /**
29891 * Gets the index of a glyph by name.
29892 * @param {string} name - The glyph name
29893 * @return {number} The index
29894 */
29895 GlyphNames.prototype.nameToGlyphIndex = function(name) {
29896 return this.names.indexOf(name);
29897 };
29898
29899 /**
29900 * @param {number} gid
29901 * @return {string}
29902 */
29903 GlyphNames.prototype.glyphIndexToName = function(gid) {
29904 return this.names[gid];
29905 };
29906
29907 /**
29908 * @alias opentype.addGlyphNames
29909 * @param {opentype.Font}
29910 */
29911 function addGlyphNames(font) {
29912 var glyph;
29913 var glyphIndexMap = font.tables.cmap.glyphIndexMap;
29914 var charCodes = Object.keys(glyphIndexMap);
29915
29916 for (var i = 0; i < charCodes.length; i += 1) {
29917 var c = charCodes[i];
29918 var glyphIndex = glyphIndexMap[c];
29919 glyph = font.glyphs.get(glyphIndex);
29920 glyph.addUnicode(parseInt(c));
29921 }
29922
29923 for (var i$1 = 0; i$1 < font.glyphs.length; i$1 += 1) {
29924 glyph = font.glyphs.get(i$1);
29925 if (font.cffEncoding) {
29926 if (font.isCIDFont) {
29927 glyph.name = 'gid' + i$1;
29928 } else {
29929 glyph.name = font.cffEncoding.charset[i$1];
29930 }
29931 } else if (font.glyphNames.names) {
29932 glyph.name = font.glyphNames.glyphIndexToName(i$1);
29933 }
29934 }
29935 }
29936
29937 // Drawing utility functions.
29938
29939 // Draw a line on the given context from point `x1,y1` to point `x2,y2`.
29940 function line(ctx, x1, y1, x2, y2) {
29941 ctx.beginPath();
29942 ctx.moveTo(x1, y1);
29943 ctx.lineTo(x2, y2);
29944 ctx.stroke();
29945 }
29946
29947 var draw = { line: line };
29948
29949 // The Glyph object
29950 // import glyf from './tables/glyf' Can't be imported here, because it's a circular dependency
29951
29952 function getPathDefinition(glyph, path) {
29953 var _path = path || new Path();
29954 return {
29955 configurable: true,
29956
29957 get: function() {
29958 if (typeof _path === 'function') {
29959 _path = _path();
29960 }
29961
29962 return _path;
29963 },
29964
29965 set: function(p) {
29966 _path = p;
29967 }
29968 };
29969 }
29970 /**
29971 * @typedef GlyphOptions
29972 * @type Object
29973 * @property {string} [name] - The glyph name
29974 * @property {number} [unicode]
29975 * @property {Array} [unicodes]
29976 * @property {number} [xMin]
29977 * @property {number} [yMin]
29978 * @property {number} [xMax]
29979 * @property {number} [yMax]
29980 * @property {number} [advanceWidth]
29981 */
29982
29983 // A Glyph is an individual mark that often corresponds to a character.
29984 // Some glyphs, such as ligatures, are a combination of many characters.
29985 // Glyphs are the basic building blocks of a font.
29986 //
29987 // The `Glyph` class contains utility methods for drawing the path and its points.
29988 /**
29989 * @exports opentype.Glyph
29990 * @class
29991 * @param {GlyphOptions}
29992 * @constructor
29993 */
29994 function Glyph(options) {
29995 // By putting all the code on a prototype function (which is only declared once)
29996 // we reduce the memory requirements for larger fonts by some 2%
29997 this.bindConstructorValues(options);
29998 }
29999
30000 /**
30001 * @param {GlyphOptions}
30002 */
30003 Glyph.prototype.bindConstructorValues = function(options) {
30004 this.index = options.index || 0;
30005
30006 // These three values cannot be deferred for memory optimization:
30007 this.name = options.name || null;
30008 this.unicode = options.unicode || undefined;
30009 this.unicodes =
30010 options.unicodes || options.unicode !== undefined
30011 ? [options.unicode]
30012 : [];
30013
30014 // But by binding these values only when necessary, we reduce can
30015 // the memory requirements by almost 3% for larger fonts.
30016 if (options.xMin) {
30017 this.xMin = options.xMin;
30018 }
30019
30020 if (options.yMin) {
30021 this.yMin = options.yMin;
30022 }
30023
30024 if (options.xMax) {
30025 this.xMax = options.xMax;
30026 }
30027
30028 if (options.yMax) {
30029 this.yMax = options.yMax;
30030 }
30031
30032 if (options.advanceWidth) {
30033 this.advanceWidth = options.advanceWidth;
30034 }
30035
30036 // The path for a glyph is the most memory intensive, and is bound as a value
30037 // with a getter/setter to ensure we actually do path parsing only once the
30038 // path is actually needed by anything.
30039 Object.defineProperty(this, 'path', getPathDefinition(this, options.path));
30040 };
30041
30042 /**
30043 * @param {number}
30044 */
30045 Glyph.prototype.addUnicode = function(unicode) {
30046 if (this.unicodes.length === 0) {
30047 this.unicode = unicode;
30048 }
30049
30050 this.unicodes.push(unicode);
30051 };
30052
30053 /**
30054 * Calculate the minimum bounding box for this glyph.
30055 * @return {opentype.BoundingBox}
30056 */
30057 Glyph.prototype.getBoundingBox = function() {
30058 return this.path.getBoundingBox();
30059 };
30060
30061 /**
30062 * Convert the glyph to a Path we can draw on a drawing context.
30063 * @param {number} [x=0] - Horizontal position of the beginning of the text.
30064 * @param {number} [y=0] - Vertical position of the *baseline* of the text.
30065 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`.
30066 * @param {Object=} options - xScale, yScale to stretch the glyph.
30067 * @param {opentype.Font} if hinting is to be used, the font
30068 * @return {opentype.Path}
30069 */
30070 Glyph.prototype.getPath = function(x, y, fontSize, options, font) {
30071 x = x !== undefined ? x : 0;
30072 y = y !== undefined ? y : 0;
30073 fontSize = fontSize !== undefined ? fontSize : 72;
30074 var commands;
30075 var hPoints;
30076 if (!options) {
30077 options = {};
30078 }
30079 var xScale = options.xScale;
30080 var yScale = options.yScale;
30081
30082 if (options.hinting && font && font.hinting) {
30083 // in case of hinting, the hinting engine takes care
30084 // of scaling the points (not the path) before hinting.
30085 hPoints = this.path && font.hinting.exec(this, fontSize);
30086 // in case the hinting engine failed hPoints is undefined
30087 // and thus reverts to plain rending
30088 }
30089
30090 if (hPoints) {
30091 // Call font.hinting.getCommands instead of `glyf.getPath(hPoints).commands` to avoid a circular dependency
30092 commands = font.hinting.getCommands(hPoints);
30093 x = Math.round(x);
30094 y = Math.round(y);
30095 // TODO in case of hinting xyScaling is not yet supported
30096 xScale = yScale = 1;
30097 } else {
30098 commands = this.path.commands;
30099 var scale = 1 / this.path.unitsPerEm * fontSize;
30100 if (xScale === undefined) {
30101 xScale = scale;
30102 }
30103 if (yScale === undefined) {
30104 yScale = scale;
30105 }
30106 }
30107
30108 var p = new Path();
30109 for (var i = 0; i < commands.length; i += 1) {
30110 var cmd = commands[i];
30111 if (cmd.type === 'M') {
30112 p.moveTo(x + cmd.x * xScale, y + -cmd.y * yScale);
30113 } else if (cmd.type === 'L') {
30114 p.lineTo(x + cmd.x * xScale, y + -cmd.y * yScale);
30115 } else if (cmd.type === 'Q') {
30116 p.quadraticCurveTo(
30117 x + cmd.x1 * xScale,
30118 y + -cmd.y1 * yScale,
30119 x + cmd.x * xScale,
30120 y + -cmd.y * yScale
30121 );
30122 } else if (cmd.type === 'C') {
30123 p.curveTo(
30124 x + cmd.x1 * xScale,
30125 y + -cmd.y1 * yScale,
30126 x + cmd.x2 * xScale,
30127 y + -cmd.y2 * yScale,
30128 x + cmd.x * xScale,
30129 y + -cmd.y * yScale
30130 );
30131 } else if (cmd.type === 'Z') {
30132 p.closePath();
30133 }
30134 }
30135
30136 return p;
30137 };
30138
30139 /**
30140 * Split the glyph into contours.
30141 * This function is here for backwards compatibility, and to
30142 * provide raw access to the TrueType glyph outlines.
30143 * @return {Array}
30144 */
30145 Glyph.prototype.getContours = function() {
30146 var this$1 = this;
30147
30148 if (this.points === undefined) {
30149 return [];
30150 }
30151
30152 var contours = [];
30153 var currentContour = [];
30154 for (var i = 0; i < this.points.length; i += 1) {
30155 var pt = this$1.points[i];
30156 currentContour.push(pt);
30157 if (pt.lastPointOfContour) {
30158 contours.push(currentContour);
30159 currentContour = [];
30160 }
30161 }
30162
30163 check.argument(
30164 currentContour.length === 0,
30165 'There are still points left in the current contour.'
30166 );
30167 return contours;
30168 };
30169
30170 /**
30171 * Calculate the xMin/yMin/xMax/yMax/lsb/rsb for a Glyph.
30172 * @return {Object}
30173 */
30174 Glyph.prototype.getMetrics = function() {
30175 var commands = this.path.commands;
30176 var xCoords = [];
30177 var yCoords = [];
30178 for (var i = 0; i < commands.length; i += 1) {
30179 var cmd = commands[i];
30180 if (cmd.type !== 'Z') {
30181 xCoords.push(cmd.x);
30182 yCoords.push(cmd.y);
30183 }
30184
30185 if (cmd.type === 'Q' || cmd.type === 'C') {
30186 xCoords.push(cmd.x1);
30187 yCoords.push(cmd.y1);
30188 }
30189
30190 if (cmd.type === 'C') {
30191 xCoords.push(cmd.x2);
30192 yCoords.push(cmd.y2);
30193 }
30194 }
30195
30196 var metrics = {
30197 xMin: Math.min.apply(null, xCoords),
30198 yMin: Math.min.apply(null, yCoords),
30199 xMax: Math.max.apply(null, xCoords),
30200 yMax: Math.max.apply(null, yCoords),
30201 leftSideBearing: this.leftSideBearing
30202 };
30203
30204 if (!isFinite(metrics.xMin)) {
30205 metrics.xMin = 0;
30206 }
30207
30208 if (!isFinite(metrics.xMax)) {
30209 metrics.xMax = this.advanceWidth;
30210 }
30211
30212 if (!isFinite(metrics.yMin)) {
30213 metrics.yMin = 0;
30214 }
30215
30216 if (!isFinite(metrics.yMax)) {
30217 metrics.yMax = 0;
30218 }
30219
30220 metrics.rightSideBearing =
30221 this.advanceWidth -
30222 metrics.leftSideBearing -
30223 (metrics.xMax - metrics.xMin);
30224 return metrics;
30225 };
30226
30227 /**
30228 * Draw the glyph on the given context.
30229 * @param {CanvasRenderingContext2D} ctx - A 2D drawing context, like Canvas.
30230 * @param {number} [x=0] - Horizontal position of the beginning of the text.
30231 * @param {number} [y=0] - Vertical position of the *baseline* of the text.
30232 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`.
30233 * @param {Object=} options - xScale, yScale to stretch the glyph.
30234 */
30235 Glyph.prototype.draw = function(ctx, x, y, fontSize, options) {
30236 this.getPath(x, y, fontSize, options).draw(ctx);
30237 };
30238
30239 /**
30240 * Draw the points of the glyph.
30241 * On-curve points will be drawn in blue, off-curve points will be drawn in red.
30242 * @param {CanvasRenderingContext2D} ctx - A 2D drawing context, like Canvas.
30243 * @param {number} [x=0] - Horizontal position of the beginning of the text.
30244 * @param {number} [y=0] - Vertical position of the *baseline* of the text.
30245 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`.
30246 */
30247 Glyph.prototype.drawPoints = function(ctx, x, y, fontSize) {
30248 function drawCircles(l, x, y, scale) {
30249 var PI_SQ = Math.PI * 2;
30250 ctx.beginPath();
30251 for (var j = 0; j < l.length; j += 1) {
30252 ctx.moveTo(x + l[j].x * scale, y + l[j].y * scale);
30253 ctx.arc(x + l[j].x * scale, y + l[j].y * scale, 2, 0, PI_SQ, false);
30254 }
30255
30256 ctx.closePath();
30257 ctx.fill();
30258 }
30259
30260 x = x !== undefined ? x : 0;
30261 y = y !== undefined ? y : 0;
30262 fontSize = fontSize !== undefined ? fontSize : 24;
30263 var scale = 1 / this.path.unitsPerEm * fontSize;
30264
30265 var blueCircles = [];
30266 var redCircles = [];
30267 var path = this.path;
30268 for (var i = 0; i < path.commands.length; i += 1) {
30269 var cmd = path.commands[i];
30270 if (cmd.x !== undefined) {
30271 blueCircles.push({ x: cmd.x, y: -cmd.y });
30272 }
30273
30274 if (cmd.x1 !== undefined) {
30275 redCircles.push({ x: cmd.x1, y: -cmd.y1 });
30276 }
30277
30278 if (cmd.x2 !== undefined) {
30279 redCircles.push({ x: cmd.x2, y: -cmd.y2 });
30280 }
30281 }
30282
30283 ctx.fillStyle = 'blue';
30284 drawCircles(blueCircles, x, y, scale);
30285 ctx.fillStyle = 'red';
30286 drawCircles(redCircles, x, y, scale);
30287 };
30288
30289 /**
30290 * Draw lines indicating important font measurements.
30291 * Black lines indicate the origin of the coordinate system (point 0,0).
30292 * Blue lines indicate the glyph bounding box.
30293 * Green line indicates the advance width of the glyph.
30294 * @param {CanvasRenderingContext2D} ctx - A 2D drawing context, like Canvas.
30295 * @param {number} [x=0] - Horizontal position of the beginning of the text.
30296 * @param {number} [y=0] - Vertical position of the *baseline* of the text.
30297 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`.
30298 */
30299 Glyph.prototype.drawMetrics = function(ctx, x, y, fontSize) {
30300 var scale;
30301 x = x !== undefined ? x : 0;
30302 y = y !== undefined ? y : 0;
30303 fontSize = fontSize !== undefined ? fontSize : 24;
30304 scale = 1 / this.path.unitsPerEm * fontSize;
30305 ctx.lineWidth = 1;
30306
30307 // Draw the origin
30308 ctx.strokeStyle = 'black';
30309 draw.line(ctx, x, -10000, x, 10000);
30310 draw.line(ctx, -10000, y, 10000, y);
30311
30312 // This code is here due to memory optimization: by not using
30313 // defaults in the constructor, we save a notable amount of memory.
30314 var xMin = this.xMin || 0;
30315 var yMin = this.yMin || 0;
30316 var xMax = this.xMax || 0;
30317 var yMax = this.yMax || 0;
30318 var advanceWidth = this.advanceWidth || 0;
30319
30320 // Draw the glyph box
30321 ctx.strokeStyle = 'blue';
30322 draw.line(ctx, x + xMin * scale, -10000, x + xMin * scale, 10000);
30323 draw.line(ctx, x + xMax * scale, -10000, x + xMax * scale, 10000);
30324 draw.line(ctx, -10000, y + -yMin * scale, 10000, y + -yMin * scale);
30325 draw.line(ctx, -10000, y + -yMax * scale, 10000, y + -yMax * scale);
30326
30327 // Draw the advance width
30328 ctx.strokeStyle = 'green';
30329 draw.line(
30330 ctx,
30331 x + advanceWidth * scale,
30332 -10000,
30333 x + advanceWidth * scale,
30334 10000
30335 );
30336 };
30337
30338 // The GlyphSet object
30339
30340 // Define a property on the glyph that depends on the path being loaded.
30341 function defineDependentProperty(glyph, externalName, internalName) {
30342 Object.defineProperty(glyph, externalName, {
30343 get: function() {
30344 // Request the path property to make sure the path is loaded.
30345 glyph.path; // jshint ignore:line
30346 return glyph[internalName];
30347 },
30348 set: function(newValue) {
30349 glyph[internalName] = newValue;
30350 },
30351 enumerable: true,
30352 configurable: true
30353 });
30354 }
30355
30356 /**
30357 * A GlyphSet represents all glyphs available in the font, but modelled using
30358 * a deferred glyph loader, for retrieving glyphs only once they are absolutely
30359 * necessary, to keep the memory footprint down.
30360 * @exports opentype.GlyphSet
30361 * @class
30362 * @param {opentype.Font}
30363 * @param {Array}
30364 */
30365 function GlyphSet(font, glyphs) {
30366 var this$1 = this;
30367
30368 this.font = font;
30369 this.glyphs = {};
30370 if (Array.isArray(glyphs)) {
30371 for (var i = 0; i < glyphs.length; i++) {
30372 this$1.glyphs[i] = glyphs[i];
30373 }
30374 }
30375
30376 this.length = (glyphs && glyphs.length) || 0;
30377 }
30378
30379 /**
30380 * @param {number} index
30381 * @return {opentype.Glyph}
30382 */
30383 GlyphSet.prototype.get = function(index) {
30384 if (typeof this.glyphs[index] === 'function') {
30385 this.glyphs[index] = this.glyphs[index]();
30386 }
30387
30388 return this.glyphs[index];
30389 };
30390
30391 /**
30392 * @param {number} index
30393 * @param {Object}
30394 */
30395 GlyphSet.prototype.push = function(index, loader) {
30396 this.glyphs[index] = loader;
30397 this.length++;
30398 };
30399
30400 /**
30401 * @alias opentype.glyphLoader
30402 * @param {opentype.Font} font
30403 * @param {number} index
30404 * @return {opentype.Glyph}
30405 */
30406 function glyphLoader(font, index) {
30407 return new Glyph({ index: index, font: font });
30408 }
30409
30410 /**
30411 * Generate a stub glyph that can be filled with all metadata *except*
30412 * the "points" and "path" properties, which must be loaded only once
30413 * the glyph's path is actually requested for text shaping.
30414 * @alias opentype.ttfGlyphLoader
30415 * @param {opentype.Font} font
30416 * @param {number} index
30417 * @param {Function} parseGlyph
30418 * @param {Object} data
30419 * @param {number} position
30420 * @param {Function} buildPath
30421 * @return {opentype.Glyph}
30422 */
30423 function ttfGlyphLoader(font, index, parseGlyph, data, position, buildPath) {
30424 return function() {
30425 var glyph = new Glyph({ index: index, font: font });
30426
30427 glyph.path = function() {
30428 parseGlyph(glyph, data, position);
30429 var path = buildPath(font.glyphs, glyph);
30430 path.unitsPerEm = font.unitsPerEm;
30431 return path;
30432 };
30433
30434 defineDependentProperty(glyph, 'xMin', '_xMin');
30435 defineDependentProperty(glyph, 'xMax', '_xMax');
30436 defineDependentProperty(glyph, 'yMin', '_yMin');
30437 defineDependentProperty(glyph, 'yMax', '_yMax');
30438
30439 return glyph;
30440 };
30441 }
30442 /**
30443 * @alias opentype.cffGlyphLoader
30444 * @param {opentype.Font} font
30445 * @param {number} index
30446 * @param {Function} parseCFFCharstring
30447 * @param {string} charstring
30448 * @return {opentype.Glyph}
30449 */
30450 function cffGlyphLoader(font, index, parseCFFCharstring, charstring) {
30451 return function() {
30452 var glyph = new Glyph({ index: index, font: font });
30453
30454 glyph.path = function() {
30455 var path = parseCFFCharstring(font, glyph, charstring);
30456 path.unitsPerEm = font.unitsPerEm;
30457 return path;
30458 };
30459
30460 return glyph;
30461 };
30462 }
30463
30464 var glyphset = {
30465 GlyphSet: GlyphSet,
30466 glyphLoader: glyphLoader,
30467 ttfGlyphLoader: ttfGlyphLoader,
30468 cffGlyphLoader: cffGlyphLoader
30469 };
30470
30471 // The `CFF` table contains the glyph outlines in PostScript format.
30472
30473 // Custom equals function that can also check lists.
30474 function equals(a, b) {
30475 if (a === b) {
30476 return true;
30477 } else if (Array.isArray(a) && Array.isArray(b)) {
30478 if (a.length !== b.length) {
30479 return false;
30480 }
30481
30482 for (var i = 0; i < a.length; i += 1) {
30483 if (!equals(a[i], b[i])) {
30484 return false;
30485 }
30486 }
30487
30488 return true;
30489 } else {
30490 return false;
30491 }
30492 }
30493
30494 // Subroutines are encoded using the negative half of the number space.
30495 // See type 2 chapter 4.7 "Subroutine operators".
30496 function calcCFFSubroutineBias(subrs) {
30497 var bias;
30498 if (subrs.length < 1240) {
30499 bias = 107;
30500 } else if (subrs.length < 33900) {
30501 bias = 1131;
30502 } else {
30503 bias = 32768;
30504 }
30505
30506 return bias;
30507 }
30508
30509 // Parse a `CFF` INDEX array.
30510 // An index array consists of a list of offsets, then a list of objects at those offsets.
30511 function parseCFFIndex(data, start, conversionFn) {
30512 var offsets = [];
30513 var objects = [];
30514 var count = parse.getCard16(data, start);
30515 var objectOffset;
30516 var endOffset;
30517 if (count !== 0) {
30518 var offsetSize = parse.getByte(data, start + 2);
30519 objectOffset = start + (count + 1) * offsetSize + 2;
30520 var pos = start + 3;
30521 for (var i = 0; i < count + 1; i += 1) {
30522 offsets.push(parse.getOffset(data, pos, offsetSize));
30523 pos += offsetSize;
30524 }
30525
30526 // The total size of the index array is 4 header bytes + the value of the last offset.
30527 endOffset = objectOffset + offsets[count];
30528 } else {
30529 endOffset = start + 2;
30530 }
30531
30532 for (var i$1 = 0; i$1 < offsets.length - 1; i$1 += 1) {
30533 var value = parse.getBytes(
30534 data,
30535 objectOffset + offsets[i$1],
30536 objectOffset + offsets[i$1 + 1]
30537 );
30538 if (conversionFn) {
30539 value = conversionFn(value);
30540 }
30541
30542 objects.push(value);
30543 }
30544
30545 return { objects: objects, startOffset: start, endOffset: endOffset };
30546 }
30547
30548 // Parse a `CFF` DICT real value.
30549 function parseFloatOperand(parser) {
30550 var s = '';
30551 var eof = 15;
30552 var lookup = [
30553 '0',
30554 '1',
30555 '2',
30556 '3',
30557 '4',
30558 '5',
30559 '6',
30560 '7',
30561 '8',
30562 '9',
30563 '.',
30564 'E',
30565 'E-',
30566 null,
30567 '-'
30568 ];
30569 while (true) {
30570 var b = parser.parseByte();
30571 var n1 = b >> 4;
30572 var n2 = b & 15;
30573
30574 if (n1 === eof) {
30575 break;
30576 }
30577
30578 s += lookup[n1];
30579
30580 if (n2 === eof) {
30581 break;
30582 }
30583
30584 s += lookup[n2];
30585 }
30586
30587 return parseFloat(s);
30588 }
30589
30590 // Parse a `CFF` DICT operand.
30591 function parseOperand(parser, b0) {
30592 var b1;
30593 var b2;
30594 var b3;
30595 var b4;
30596 if (b0 === 28) {
30597 b1 = parser.parseByte();
30598 b2 = parser.parseByte();
30599 return (b1 << 8) | b2;
30600 }
30601
30602 if (b0 === 29) {
30603 b1 = parser.parseByte();
30604 b2 = parser.parseByte();
30605 b3 = parser.parseByte();
30606 b4 = parser.parseByte();
30607 return (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
30608 }
30609
30610 if (b0 === 30) {
30611 return parseFloatOperand(parser);
30612 }
30613
30614 if (b0 >= 32 && b0 <= 246) {
30615 return b0 - 139;
30616 }
30617
30618 if (b0 >= 247 && b0 <= 250) {
30619 b1 = parser.parseByte();
30620 return (b0 - 247) * 256 + b1 + 108;
30621 }
30622
30623 if (b0 >= 251 && b0 <= 254) {
30624 b1 = parser.parseByte();
30625 return -(b0 - 251) * 256 - b1 - 108;
30626 }
30627
30628 throw new Error('Invalid b0 ' + b0);
30629 }
30630
30631 // Convert the entries returned by `parseDict` to a proper dictionary.
30632 // If a value is a list of one, it is unpacked.
30633 function entriesToObject(entries) {
30634 var o = {};
30635 for (var i = 0; i < entries.length; i += 1) {
30636 var key = entries[i][0];
30637 var values = entries[i][1];
30638 var value = void 0;
30639 if (values.length === 1) {
30640 value = values[0];
30641 } else {
30642 value = values;
30643 }
30644
30645 if (o.hasOwnProperty(key) && !isNaN(o[key])) {
30646 throw new Error('Object ' + o + ' already has key ' + key);
30647 }
30648
30649 o[key] = value;
30650 }
30651
30652 return o;
30653 }
30654
30655 // Parse a `CFF` DICT object.
30656 // A dictionary contains key-value pairs in a compact tokenized format.
30657 function parseCFFDict(data, start, size) {
30658 start = start !== undefined ? start : 0;
30659 var parser = new parse.Parser(data, start);
30660 var entries = [];
30661 var operands = [];
30662 size = size !== undefined ? size : data.length;
30663
30664 while (parser.relativeOffset < size) {
30665 var op = parser.parseByte();
30666
30667 // The first byte for each dict item distinguishes between operator (key) and operand (value).
30668 // Values <= 21 are operators.
30669 if (op <= 21) {
30670 // Two-byte operators have an initial escape byte of 12.
30671 if (op === 12) {
30672 op = 1200 + parser.parseByte();
30673 }
30674
30675 entries.push([op, operands]);
30676 operands = [];
30677 } else {
30678 // Since the operands (values) come before the operators (keys), we store all operands in a list
30679 // until we encounter an operator.
30680 operands.push(parseOperand(parser, op));
30681 }
30682 }
30683
30684 return entriesToObject(entries);
30685 }
30686
30687 // Given a String Index (SID), return the value of the string.
30688 // Strings below index 392 are standard CFF strings and are not encoded in the font.
30689 function getCFFString(strings, index) {
30690 if (index <= 390) {
30691 index = cffStandardStrings[index];
30692 } else {
30693 index = strings[index - 391];
30694 }
30695
30696 return index;
30697 }
30698
30699 // Interpret a dictionary and return a new dictionary with readable keys and values for missing entries.
30700 // This function takes `meta` which is a list of objects containing `operand`, `name` and `default`.
30701 function interpretDict(dict, meta, strings) {
30702 var newDict = {};
30703 var value;
30704
30705 // Because we also want to include missing values, we start out from the meta list
30706 // and lookup values in the dict.
30707 for (var i = 0; i < meta.length; i += 1) {
30708 var m = meta[i];
30709
30710 if (Array.isArray(m.type)) {
30711 var values = [];
30712 values.length = m.type.length;
30713 for (var j = 0; j < m.type.length; j++) {
30714 value = dict[m.op] !== undefined ? dict[m.op][j] : undefined;
30715 if (value === undefined) {
30716 value =
30717 m.value !== undefined && m.value[j] !== undefined
30718 ? m.value[j]
30719 : null;
30720 }
30721 if (m.type[j] === 'SID') {
30722 value = getCFFString(strings, value);
30723 }
30724 values[j] = value;
30725 }
30726 newDict[m.name] = values;
30727 } else {
30728 value = dict[m.op];
30729 if (value === undefined) {
30730 value = m.value !== undefined ? m.value : null;
30731 }
30732
30733 if (m.type === 'SID') {
30734 value = getCFFString(strings, value);
30735 }
30736 newDict[m.name] = value;
30737 }
30738 }
30739
30740 return newDict;
30741 }
30742
30743 // Parse the CFF header.
30744 function parseCFFHeader(data, start) {
30745 var header = {};
30746 header.formatMajor = parse.getCard8(data, start);
30747 header.formatMinor = parse.getCard8(data, start + 1);
30748 header.size = parse.getCard8(data, start + 2);
30749 header.offsetSize = parse.getCard8(data, start + 3);
30750 header.startOffset = start;
30751 header.endOffset = start + 4;
30752 return header;
30753 }
30754
30755 var TOP_DICT_META = [
30756 { name: 'version', op: 0, type: 'SID' },
30757 { name: 'notice', op: 1, type: 'SID' },
30758 { name: 'copyright', op: 1200, type: 'SID' },
30759 { name: 'fullName', op: 2, type: 'SID' },
30760 { name: 'familyName', op: 3, type: 'SID' },
30761 { name: 'weight', op: 4, type: 'SID' },
30762 { name: 'isFixedPitch', op: 1201, type: 'number', value: 0 },
30763 { name: 'italicAngle', op: 1202, type: 'number', value: 0 },
30764 { name: 'underlinePosition', op: 1203, type: 'number', value: -100 },
30765 { name: 'underlineThickness', op: 1204, type: 'number', value: 50 },
30766 { name: 'paintType', op: 1205, type: 'number', value: 0 },
30767 { name: 'charstringType', op: 1206, type: 'number', value: 2 },
30768 {
30769 name: 'fontMatrix',
30770 op: 1207,
30771 type: ['real', 'real', 'real', 'real', 'real', 'real'],
30772 value: [0.001, 0, 0, 0.001, 0, 0]
30773 },
30774 { name: 'uniqueId', op: 13, type: 'number' },
30775 {
30776 name: 'fontBBox',
30777 op: 5,
30778 type: ['number', 'number', 'number', 'number'],
30779 value: [0, 0, 0, 0]
30780 },
30781 { name: 'strokeWidth', op: 1208, type: 'number', value: 0 },
30782 { name: 'xuid', op: 14, type: [], value: null },
30783 { name: 'charset', op: 15, type: 'offset', value: 0 },
30784 { name: 'encoding', op: 16, type: 'offset', value: 0 },
30785 { name: 'charStrings', op: 17, type: 'offset', value: 0 },
30786 { name: 'private', op: 18, type: ['number', 'offset'], value: [0, 0] },
30787 { name: 'ros', op: 1230, type: ['SID', 'SID', 'number'] },
30788 { name: 'cidFontVersion', op: 1231, type: 'number', value: 0 },
30789 { name: 'cidFontRevision', op: 1232, type: 'number', value: 0 },
30790 { name: 'cidFontType', op: 1233, type: 'number', value: 0 },
30791 { name: 'cidCount', op: 1234, type: 'number', value: 8720 },
30792 { name: 'uidBase', op: 1235, type: 'number' },
30793 { name: 'fdArray', op: 1236, type: 'offset' },
30794 { name: 'fdSelect', op: 1237, type: 'offset' },
30795 { name: 'fontName', op: 1238, type: 'SID' }
30796 ];
30797
30798 var PRIVATE_DICT_META = [
30799 { name: 'subrs', op: 19, type: 'offset', value: 0 },
30800 { name: 'defaultWidthX', op: 20, type: 'number', value: 0 },
30801 { name: 'nominalWidthX', op: 21, type: 'number', value: 0 }
30802 ];
30803
30804 // Parse the CFF top dictionary. A CFF table can contain multiple fonts, each with their own top dictionary.
30805 // The top dictionary contains the essential metadata for the font, together with the private dictionary.
30806 function parseCFFTopDict(data, strings) {
30807 var dict = parseCFFDict(data, 0, data.byteLength);
30808 return interpretDict(dict, TOP_DICT_META, strings);
30809 }
30810
30811 // Parse the CFF private dictionary. We don't fully parse out all the values, only the ones we need.
30812 function parseCFFPrivateDict(data, start, size, strings) {
30813 var dict = parseCFFDict(data, start, size);
30814 return interpretDict(dict, PRIVATE_DICT_META, strings);
30815 }
30816
30817 // Returns a list of "Top DICT"s found using an INDEX list.
30818 // Used to read both the usual high-level Top DICTs and also the FDArray
30819 // discovered inside CID-keyed fonts. When a Top DICT has a reference to
30820 // a Private DICT that is read and saved into the Top DICT.
30821 //
30822 // In addition to the expected/optional values as outlined in TOP_DICT_META
30823 // the following values might be saved into the Top DICT.
30824 //
30825 // _subrs [] array of local CFF subroutines from Private DICT
30826 // _subrsBias bias value computed from number of subroutines
30827 // (see calcCFFSubroutineBias() and parseCFFCharstring())
30828 // _defaultWidthX default widths for CFF characters
30829 // _nominalWidthX bias added to width embedded within glyph description
30830 //
30831 // _privateDict saved copy of parsed Private DICT from Top DICT
30832 function gatherCFFTopDicts(data, start, cffIndex, strings) {
30833 var topDictArray = [];
30834 for (var iTopDict = 0; iTopDict < cffIndex.length; iTopDict += 1) {
30835 var topDictData = new DataView(new Uint8Array(cffIndex[iTopDict]).buffer);
30836 var topDict = parseCFFTopDict(topDictData, strings);
30837 topDict._subrs = [];
30838 topDict._subrsBias = 0;
30839 var privateSize = topDict.private[0];
30840 var privateOffset = topDict.private[1];
30841 if (privateSize !== 0 && privateOffset !== 0) {
30842 var privateDict = parseCFFPrivateDict(
30843 data,
30844 privateOffset + start,
30845 privateSize,
30846 strings
30847 );
30848 topDict._defaultWidthX = privateDict.defaultWidthX;
30849 topDict._nominalWidthX = privateDict.nominalWidthX;
30850 if (privateDict.subrs !== 0) {
30851 var subrOffset = privateOffset + privateDict.subrs;
30852 var subrIndex = parseCFFIndex(data, subrOffset + start);
30853 topDict._subrs = subrIndex.objects;
30854 topDict._subrsBias = calcCFFSubroutineBias(topDict._subrs);
30855 }
30856 topDict._privateDict = privateDict;
30857 }
30858 topDictArray.push(topDict);
30859 }
30860 return topDictArray;
30861 }
30862
30863 // Parse the CFF charset table, which contains internal names for all the glyphs.
30864 // This function will return a list of glyph names.
30865 // See Adobe TN #5176 chapter 13, "Charsets".
30866 function parseCFFCharset(data, start, nGlyphs, strings) {
30867 var sid;
30868 var count;
30869 var parser = new parse.Parser(data, start);
30870
30871 // The .notdef glyph is not included, so subtract 1.
30872 nGlyphs -= 1;
30873 var charset = ['.notdef'];
30874
30875 var format = parser.parseCard8();
30876 if (format === 0) {
30877 for (var i = 0; i < nGlyphs; i += 1) {
30878 sid = parser.parseSID();
30879 charset.push(getCFFString(strings, sid));
30880 }
30881 } else if (format === 1) {
30882 while (charset.length <= nGlyphs) {
30883 sid = parser.parseSID();
30884 count = parser.parseCard8();
30885 for (var i$1 = 0; i$1 <= count; i$1 += 1) {
30886 charset.push(getCFFString(strings, sid));
30887 sid += 1;
30888 }
30889 }
30890 } else if (format === 2) {
30891 while (charset.length <= nGlyphs) {
30892 sid = parser.parseSID();
30893 count = parser.parseCard16();
30894 for (var i$2 = 0; i$2 <= count; i$2 += 1) {
30895 charset.push(getCFFString(strings, sid));
30896 sid += 1;
30897 }
30898 }
30899 } else {
30900 throw new Error('Unknown charset format ' + format);
30901 }
30902
30903 return charset;
30904 }
30905
30906 // Parse the CFF encoding data. Only one encoding can be specified per font.
30907 // See Adobe TN #5176 chapter 12, "Encodings".
30908 function parseCFFEncoding(data, start, charset) {
30909 var code;
30910 var enc = {};
30911 var parser = new parse.Parser(data, start);
30912 var format = parser.parseCard8();
30913 if (format === 0) {
30914 var nCodes = parser.parseCard8();
30915 for (var i = 0; i < nCodes; i += 1) {
30916 code = parser.parseCard8();
30917 enc[code] = i;
30918 }
30919 } else if (format === 1) {
30920 var nRanges = parser.parseCard8();
30921 code = 1;
30922 for (var i$1 = 0; i$1 < nRanges; i$1 += 1) {
30923 var first = parser.parseCard8();
30924 var nLeft = parser.parseCard8();
30925 for (var j = first; j <= first + nLeft; j += 1) {
30926 enc[j] = code;
30927 code += 1;
30928 }
30929 }
30930 } else {
30931 throw new Error('Unknown encoding format ' + format);
30932 }
30933
30934 return new CffEncoding(enc, charset);
30935 }
30936
30937 // Take in charstring code and return a Glyph object.
30938 // The encoding is described in the Type 2 Charstring Format
30939 // https://www.microsoft.com/typography/OTSPEC/charstr2.htm
30940 function parseCFFCharstring(font, glyph, code) {
30941 var c1x;
30942 var c1y;
30943 var c2x;
30944 var c2y;
30945 var p = new Path();
30946 var stack = [];
30947 var nStems = 0;
30948 var haveWidth = false;
30949 var open = false;
30950 var x = 0;
30951 var y = 0;
30952 var subrs;
30953 var subrsBias;
30954 var defaultWidthX;
30955 var nominalWidthX;
30956 if (font.isCIDFont) {
30957 var fdIndex = font.tables.cff.topDict._fdSelect[glyph.index];
30958 var fdDict = font.tables.cff.topDict._fdArray[fdIndex];
30959 subrs = fdDict._subrs;
30960 subrsBias = fdDict._subrsBias;
30961 defaultWidthX = fdDict._defaultWidthX;
30962 nominalWidthX = fdDict._nominalWidthX;
30963 } else {
30964 subrs = font.tables.cff.topDict._subrs;
30965 subrsBias = font.tables.cff.topDict._subrsBias;
30966 defaultWidthX = font.tables.cff.topDict._defaultWidthX;
30967 nominalWidthX = font.tables.cff.topDict._nominalWidthX;
30968 }
30969 var width = defaultWidthX;
30970
30971 function newContour(x, y) {
30972 if (open) {
30973 p.closePath();
30974 }
30975
30976 p.moveTo(x, y);
30977 open = true;
30978 }
30979
30980 function parseStems() {
30981 var hasWidthArg;
30982
30983 // The number of stem operators on the stack is always even.
30984 // If the value is uneven, that means a width is specified.
30985 hasWidthArg = stack.length % 2 !== 0;
30986 if (hasWidthArg && !haveWidth) {
30987 width = stack.shift() + nominalWidthX;
30988 }
30989
30990 nStems += stack.length >> 1;
30991 stack.length = 0;
30992 haveWidth = true;
30993 }
30994
30995 function parse$$1(code) {
30996 var b1;
30997 var b2;
30998 var b3;
30999 var b4;
31000 var codeIndex;
31001 var subrCode;
31002 var jpx;
31003 var jpy;
31004 var c3x;
31005 var c3y;
31006 var c4x;
31007 var c4y;
31008
31009 var i = 0;
31010 while (i < code.length) {
31011 var v = code[i];
31012 i += 1;
31013 switch (v) {
31014 case 1: // hstem
31015 parseStems();
31016 break;
31017 case 3: // vstem
31018 parseStems();
31019 break;
31020 case 4: // vmoveto
31021 if (stack.length > 1 && !haveWidth) {
31022 width = stack.shift() + nominalWidthX;
31023 haveWidth = true;
31024 }
31025
31026 y += stack.pop();
31027 newContour(x, y);
31028 break;
31029 case 5: // rlineto
31030 while (stack.length > 0) {
31031 x += stack.shift();
31032 y += stack.shift();
31033 p.lineTo(x, y);
31034 }
31035
31036 break;
31037 case 6: // hlineto
31038 while (stack.length > 0) {
31039 x += stack.shift();
31040 p.lineTo(x, y);
31041 if (stack.length === 0) {
31042 break;
31043 }
31044
31045 y += stack.shift();
31046 p.lineTo(x, y);
31047 }
31048
31049 break;
31050 case 7: // vlineto
31051 while (stack.length > 0) {
31052 y += stack.shift();
31053 p.lineTo(x, y);
31054 if (stack.length === 0) {
31055 break;
31056 }
31057
31058 x += stack.shift();
31059 p.lineTo(x, y);
31060 }
31061
31062 break;
31063 case 8: // rrcurveto
31064 while (stack.length > 0) {
31065 c1x = x + stack.shift();
31066 c1y = y + stack.shift();
31067 c2x = c1x + stack.shift();
31068 c2y = c1y + stack.shift();
31069 x = c2x + stack.shift();
31070 y = c2y + stack.shift();
31071 p.curveTo(c1x, c1y, c2x, c2y, x, y);
31072 }
31073
31074 break;
31075 case 10: // callsubr
31076 codeIndex = stack.pop() + subrsBias;
31077 subrCode = subrs[codeIndex];
31078 if (subrCode) {
31079 parse$$1(subrCode);
31080 }
31081
31082 break;
31083 case 11: // return
31084 return;
31085 case 12: // flex operators
31086 v = code[i];
31087 i += 1;
31088 switch (v) {
31089 case 35: // flex
31090 // |- dx1 dy1 dx2 dy2 dx3 dy3 dx4 dy4 dx5 dy5 dx6 dy6 fd flex (12 35) |-
31091 c1x = x + stack.shift(); // dx1
31092 c1y = y + stack.shift(); // dy1
31093 c2x = c1x + stack.shift(); // dx2
31094 c2y = c1y + stack.shift(); // dy2
31095 jpx = c2x + stack.shift(); // dx3
31096 jpy = c2y + stack.shift(); // dy3
31097 c3x = jpx + stack.shift(); // dx4
31098 c3y = jpy + stack.shift(); // dy4
31099 c4x = c3x + stack.shift(); // dx5
31100 c4y = c3y + stack.shift(); // dy5
31101 x = c4x + stack.shift(); // dx6
31102 y = c4y + stack.shift(); // dy6
31103 stack.shift(); // flex depth
31104 p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);
31105 p.curveTo(c3x, c3y, c4x, c4y, x, y);
31106 break;
31107 case 34: // hflex
31108 // |- dx1 dx2 dy2 dx3 dx4 dx5 dx6 hflex (12 34) |-
31109 c1x = x + stack.shift(); // dx1
31110 c1y = y; // dy1
31111 c2x = c1x + stack.shift(); // dx2
31112 c2y = c1y + stack.shift(); // dy2
31113 jpx = c2x + stack.shift(); // dx3
31114 jpy = c2y; // dy3
31115 c3x = jpx + stack.shift(); // dx4
31116 c3y = c2y; // dy4
31117 c4x = c3x + stack.shift(); // dx5
31118 c4y = y; // dy5
31119 x = c4x + stack.shift(); // dx6
31120 p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);
31121 p.curveTo(c3x, c3y, c4x, c4y, x, y);
31122 break;
31123 case 36: // hflex1
31124 // |- dx1 dy1 dx2 dy2 dx3 dx4 dx5 dy5 dx6 hflex1 (12 36) |-
31125 c1x = x + stack.shift(); // dx1
31126 c1y = y + stack.shift(); // dy1
31127 c2x = c1x + stack.shift(); // dx2
31128 c2y = c1y + stack.shift(); // dy2
31129 jpx = c2x + stack.shift(); // dx3
31130 jpy = c2y; // dy3
31131 c3x = jpx + stack.shift(); // dx4
31132 c3y = c2y; // dy4
31133 c4x = c3x + stack.shift(); // dx5
31134 c4y = c3y + stack.shift(); // dy5
31135 x = c4x + stack.shift(); // dx6
31136 p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);
31137 p.curveTo(c3x, c3y, c4x, c4y, x, y);
31138 break;
31139 case 37: // flex1
31140 // |- dx1 dy1 dx2 dy2 dx3 dy3 dx4 dy4 dx5 dy5 d6 flex1 (12 37) |-
31141 c1x = x + stack.shift(); // dx1
31142 c1y = y + stack.shift(); // dy1
31143 c2x = c1x + stack.shift(); // dx2
31144 c2y = c1y + stack.shift(); // dy2
31145 jpx = c2x + stack.shift(); // dx3
31146 jpy = c2y + stack.shift(); // dy3
31147 c3x = jpx + stack.shift(); // dx4
31148 c3y = jpy + stack.shift(); // dy4
31149 c4x = c3x + stack.shift(); // dx5
31150 c4y = c3y + stack.shift(); // dy5
31151 if (Math.abs(c4x - x) > Math.abs(c4y - y)) {
31152 x = c4x + stack.shift();
31153 } else {
31154 y = c4y + stack.shift();
31155 }
31156
31157 p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);
31158 p.curveTo(c3x, c3y, c4x, c4y, x, y);
31159 break;
31160 default:
31161 console.log(
31162 'Glyph ' + glyph.index + ': unknown operator ' + 1200 + v
31163 );
31164 stack.length = 0;
31165 }
31166 break;
31167 case 14: // endchar
31168 if (stack.length > 0 && !haveWidth) {
31169 width = stack.shift() + nominalWidthX;
31170 haveWidth = true;
31171 }
31172
31173 if (open) {
31174 p.closePath();
31175 open = false;
31176 }
31177
31178 break;
31179 case 18: // hstemhm
31180 parseStems();
31181 break;
31182 case 19: // hintmask
31183 case 20: // cntrmask
31184 parseStems();
31185 i += (nStems + 7) >> 3;
31186 break;
31187 case 21: // rmoveto
31188 if (stack.length > 2 && !haveWidth) {
31189 width = stack.shift() + nominalWidthX;
31190 haveWidth = true;
31191 }
31192
31193 y += stack.pop();
31194 x += stack.pop();
31195 newContour(x, y);
31196 break;
31197 case 22: // hmoveto
31198 if (stack.length > 1 && !haveWidth) {
31199 width = stack.shift() + nominalWidthX;
31200 haveWidth = true;
31201 }
31202
31203 x += stack.pop();
31204 newContour(x, y);
31205 break;
31206 case 23: // vstemhm
31207 parseStems();
31208 break;
31209 case 24: // rcurveline
31210 while (stack.length > 2) {
31211 c1x = x + stack.shift();
31212 c1y = y + stack.shift();
31213 c2x = c1x + stack.shift();
31214 c2y = c1y + stack.shift();
31215 x = c2x + stack.shift();
31216 y = c2y + stack.shift();
31217 p.curveTo(c1x, c1y, c2x, c2y, x, y);
31218 }
31219
31220 x += stack.shift();
31221 y += stack.shift();
31222 p.lineTo(x, y);
31223 break;
31224 case 25: // rlinecurve
31225 while (stack.length > 6) {
31226 x += stack.shift();
31227 y += stack.shift();
31228 p.lineTo(x, y);
31229 }
31230
31231 c1x = x + stack.shift();
31232 c1y = y + stack.shift();
31233 c2x = c1x + stack.shift();
31234 c2y = c1y + stack.shift();
31235 x = c2x + stack.shift();
31236 y = c2y + stack.shift();
31237 p.curveTo(c1x, c1y, c2x, c2y, x, y);
31238 break;
31239 case 26: // vvcurveto
31240 if (stack.length % 2) {
31241 x += stack.shift();
31242 }
31243
31244 while (stack.length > 0) {
31245 c1x = x;
31246 c1y = y + stack.shift();
31247 c2x = c1x + stack.shift();
31248 c2y = c1y + stack.shift();
31249 x = c2x;
31250 y = c2y + stack.shift();
31251 p.curveTo(c1x, c1y, c2x, c2y, x, y);
31252 }
31253
31254 break;
31255 case 27: // hhcurveto
31256 if (stack.length % 2) {
31257 y += stack.shift();
31258 }
31259
31260 while (stack.length > 0) {
31261 c1x = x + stack.shift();
31262 c1y = y;
31263 c2x = c1x + stack.shift();
31264 c2y = c1y + stack.shift();
31265 x = c2x + stack.shift();
31266 y = c2y;
31267 p.curveTo(c1x, c1y, c2x, c2y, x, y);
31268 }
31269
31270 break;
31271 case 28: // shortint
31272 b1 = code[i];
31273 b2 = code[i + 1];
31274 stack.push(((b1 << 24) | (b2 << 16)) >> 16);
31275 i += 2;
31276 break;
31277 case 29: // callgsubr
31278 codeIndex = stack.pop() + font.gsubrsBias;
31279 subrCode = font.gsubrs[codeIndex];
31280 if (subrCode) {
31281 parse$$1(subrCode);
31282 }
31283
31284 break;
31285 case 30: // vhcurveto
31286 while (stack.length > 0) {
31287 c1x = x;
31288 c1y = y + stack.shift();
31289 c2x = c1x + stack.shift();
31290 c2y = c1y + stack.shift();
31291 x = c2x + stack.shift();
31292 y = c2y + (stack.length === 1 ? stack.shift() : 0);
31293 p.curveTo(c1x, c1y, c2x, c2y, x, y);
31294 if (stack.length === 0) {
31295 break;
31296 }
31297
31298 c1x = x + stack.shift();
31299 c1y = y;
31300 c2x = c1x + stack.shift();
31301 c2y = c1y + stack.shift();
31302 y = c2y + stack.shift();
31303 x = c2x + (stack.length === 1 ? stack.shift() : 0);
31304 p.curveTo(c1x, c1y, c2x, c2y, x, y);
31305 }
31306
31307 break;
31308 case 31: // hvcurveto
31309 while (stack.length > 0) {
31310 c1x = x + stack.shift();
31311 c1y = y;
31312 c2x = c1x + stack.shift();
31313 c2y = c1y + stack.shift();
31314 y = c2y + stack.shift();
31315 x = c2x + (stack.length === 1 ? stack.shift() : 0);
31316 p.curveTo(c1x, c1y, c2x, c2y, x, y);
31317 if (stack.length === 0) {
31318 break;
31319 }
31320
31321 c1x = x;
31322 c1y = y + stack.shift();
31323 c2x = c1x + stack.shift();
31324 c2y = c1y + stack.shift();
31325 x = c2x + stack.shift();
31326 y = c2y + (stack.length === 1 ? stack.shift() : 0);
31327 p.curveTo(c1x, c1y, c2x, c2y, x, y);
31328 }
31329
31330 break;
31331 default:
31332 if (v < 32) {
31333 console.log('Glyph ' + glyph.index + ': unknown operator ' + v);
31334 } else if (v < 247) {
31335 stack.push(v - 139);
31336 } else if (v < 251) {
31337 b1 = code[i];
31338 i += 1;
31339 stack.push((v - 247) * 256 + b1 + 108);
31340 } else if (v < 255) {
31341 b1 = code[i];
31342 i += 1;
31343 stack.push(-(v - 251) * 256 - b1 - 108);
31344 } else {
31345 b1 = code[i];
31346 b2 = code[i + 1];
31347 b3 = code[i + 2];
31348 b4 = code[i + 3];
31349 i += 4;
31350 stack.push(((b1 << 24) | (b2 << 16) | (b3 << 8) | b4) / 65536);
31351 }
31352 }
31353 }
31354 }
31355
31356 parse$$1(code);
31357
31358 glyph.advanceWidth = width;
31359 return p;
31360 }
31361
31362 function parseCFFFDSelect(data, start, nGlyphs, fdArrayCount) {
31363 var fdSelect = [];
31364 var fdIndex;
31365 var parser = new parse.Parser(data, start);
31366 var format = parser.parseCard8();
31367 if (format === 0) {
31368 // Simple list of nGlyphs elements
31369 for (var iGid = 0; iGid < nGlyphs; iGid++) {
31370 fdIndex = parser.parseCard8();
31371 if (fdIndex >= fdArrayCount) {
31372 throw new Error(
31373 'CFF table CID Font FDSelect has bad FD index value ' +
31374 fdIndex +
31375 ' (FD count ' +
31376 fdArrayCount +
31377 ')'
31378 );
31379 }
31380 fdSelect.push(fdIndex);
31381 }
31382 } else if (format === 3) {
31383 // Ranges
31384 var nRanges = parser.parseCard16();
31385 var first = parser.parseCard16();
31386 if (first !== 0) {
31387 throw new Error(
31388 'CFF Table CID Font FDSelect format 3 range has bad initial GID ' +
31389 first
31390 );
31391 }
31392 var next;
31393 for (var iRange = 0; iRange < nRanges; iRange++) {
31394 fdIndex = parser.parseCard8();
31395 next = parser.parseCard16();
31396 if (fdIndex >= fdArrayCount) {
31397 throw new Error(
31398 'CFF table CID Font FDSelect has bad FD index value ' +
31399 fdIndex +
31400 ' (FD count ' +
31401 fdArrayCount +
31402 ')'
31403 );
31404 }
31405 if (next > nGlyphs) {
31406 throw new Error(
31407 'CFF Table CID Font FDSelect format 3 range has bad GID ' + next
31408 );
31409 }
31410 for (; first < next; first++) {
31411 fdSelect.push(fdIndex);
31412 }
31413 first = next;
31414 }
31415 if (next !== nGlyphs) {
31416 throw new Error(
31417 'CFF Table CID Font FDSelect format 3 range has bad final GID ' + next
31418 );
31419 }
31420 } else {
31421 throw new Error(
31422 'CFF Table CID Font FDSelect table has unsupported format ' + format
31423 );
31424 }
31425 return fdSelect;
31426 }
31427
31428 // Parse the `CFF` table, which contains the glyph outlines in PostScript format.
31429 function parseCFFTable(data, start, font) {
31430 font.tables.cff = {};
31431 var header = parseCFFHeader(data, start);
31432 var nameIndex = parseCFFIndex(data, header.endOffset, parse.bytesToString);
31433 var topDictIndex = parseCFFIndex(data, nameIndex.endOffset);
31434 var stringIndex = parseCFFIndex(
31435 data,
31436 topDictIndex.endOffset,
31437 parse.bytesToString
31438 );
31439 var globalSubrIndex = parseCFFIndex(data, stringIndex.endOffset);
31440 font.gsubrs = globalSubrIndex.objects;
31441 font.gsubrsBias = calcCFFSubroutineBias(font.gsubrs);
31442
31443 var topDictArray = gatherCFFTopDicts(
31444 data,
31445 start,
31446 topDictIndex.objects,
31447 stringIndex.objects
31448 );
31449 if (topDictArray.length !== 1) {
31450 throw new Error(
31451 "CFF table has too many fonts in 'FontSet' - count of fonts NameIndex.length = " +
31452 topDictArray.length
31453 );
31454 }
31455
31456 var topDict = topDictArray[0];
31457 font.tables.cff.topDict = topDict;
31458
31459 if (topDict._privateDict) {
31460 font.defaultWidthX = topDict._privateDict.defaultWidthX;
31461 font.nominalWidthX = topDict._privateDict.nominalWidthX;
31462 }
31463
31464 if (topDict.ros[0] !== undefined && topDict.ros[1] !== undefined) {
31465 font.isCIDFont = true;
31466 }
31467
31468 if (font.isCIDFont) {
31469 var fdArrayOffset = topDict.fdArray;
31470 var fdSelectOffset = topDict.fdSelect;
31471 if (fdArrayOffset === 0 || fdSelectOffset === 0) {
31472 throw new Error(
31473 'Font is marked as a CID font, but FDArray and/or FDSelect information is missing'
31474 );
31475 }
31476 fdArrayOffset += start;
31477 var fdArrayIndex = parseCFFIndex(data, fdArrayOffset);
31478 var fdArray = gatherCFFTopDicts(
31479 data,
31480 start,
31481 fdArrayIndex.objects,
31482 stringIndex.objects
31483 );
31484 topDict._fdArray = fdArray;
31485 fdSelectOffset += start;
31486 topDict._fdSelect = parseCFFFDSelect(
31487 data,
31488 fdSelectOffset,
31489 font.numGlyphs,
31490 fdArray.length
31491 );
31492 }
31493
31494 var privateDictOffset = start + topDict.private[1];
31495 var privateDict = parseCFFPrivateDict(
31496 data,
31497 privateDictOffset,
31498 topDict.private[0],
31499 stringIndex.objects
31500 );
31501 font.defaultWidthX = privateDict.defaultWidthX;
31502 font.nominalWidthX = privateDict.nominalWidthX;
31503
31504 if (privateDict.subrs !== 0) {
31505 var subrOffset = privateDictOffset + privateDict.subrs;
31506 var subrIndex = parseCFFIndex(data, subrOffset);
31507 font.subrs = subrIndex.objects;
31508 font.subrsBias = calcCFFSubroutineBias(font.subrs);
31509 } else {
31510 font.subrs = [];
31511 font.subrsBias = 0;
31512 }
31513
31514 // Offsets in the top dict are relative to the beginning of the CFF data, so add the CFF start offset.
31515 var charStringsIndex = parseCFFIndex(data, start + topDict.charStrings);
31516 font.nGlyphs = charStringsIndex.objects.length;
31517
31518 var charset = parseCFFCharset(
31519 data,
31520 start + topDict.charset,
31521 font.nGlyphs,
31522 stringIndex.objects
31523 );
31524 if (topDict.encoding === 0) {
31525 // Standard encoding
31526 font.cffEncoding = new CffEncoding(cffStandardEncoding, charset);
31527 } else if (topDict.encoding === 1) {
31528 // Expert encoding
31529 font.cffEncoding = new CffEncoding(cffExpertEncoding, charset);
31530 } else {
31531 font.cffEncoding = parseCFFEncoding(
31532 data,
31533 start + topDict.encoding,
31534 charset
31535 );
31536 }
31537
31538 // Prefer the CMAP encoding to the CFF encoding.
31539 font.encoding = font.encoding || font.cffEncoding;
31540
31541 font.glyphs = new glyphset.GlyphSet(font);
31542 for (var i = 0; i < font.nGlyphs; i += 1) {
31543 var charString = charStringsIndex.objects[i];
31544 font.glyphs.push(
31545 i,
31546 glyphset.cffGlyphLoader(font, i, parseCFFCharstring, charString)
31547 );
31548 }
31549 }
31550
31551 // Convert a string to a String ID (SID).
31552 // The list of strings is modified in place.
31553 function encodeString(s, strings) {
31554 var sid;
31555
31556 // Is the string in the CFF standard strings?
31557 var i = cffStandardStrings.indexOf(s);
31558 if (i >= 0) {
31559 sid = i;
31560 }
31561
31562 // Is the string already in the string index?
31563 i = strings.indexOf(s);
31564 if (i >= 0) {
31565 sid = i + cffStandardStrings.length;
31566 } else {
31567 sid = cffStandardStrings.length + strings.length;
31568 strings.push(s);
31569 }
31570
31571 return sid;
31572 }
31573
31574 function makeHeader() {
31575 return new table.Record('Header', [
31576 { name: 'major', type: 'Card8', value: 1 },
31577 { name: 'minor', type: 'Card8', value: 0 },
31578 { name: 'hdrSize', type: 'Card8', value: 4 },
31579 { name: 'major', type: 'Card8', value: 1 }
31580 ]);
31581 }
31582
31583 function makeNameIndex(fontNames) {
31584 var t = new table.Record('Name INDEX', [
31585 { name: 'names', type: 'INDEX', value: [] }
31586 ]);
31587 t.names = [];
31588 for (var i = 0; i < fontNames.length; i += 1) {
31589 t.names.push({ name: 'name_' + i, type: 'NAME', value: fontNames[i] });
31590 }
31591
31592 return t;
31593 }
31594
31595 // Given a dictionary's metadata, create a DICT structure.
31596 function makeDict(meta, attrs, strings) {
31597 var m = {};
31598 for (var i = 0; i < meta.length; i += 1) {
31599 var entry = meta[i];
31600 var value = attrs[entry.name];
31601 if (value !== undefined && !equals(value, entry.value)) {
31602 if (entry.type === 'SID') {
31603 value = encodeString(value, strings);
31604 }
31605
31606 m[entry.op] = { name: entry.name, type: entry.type, value: value };
31607 }
31608 }
31609
31610 return m;
31611 }
31612
31613 // The Top DICT houses the global font attributes.
31614 function makeTopDict(attrs, strings) {
31615 var t = new table.Record('Top DICT', [
31616 { name: 'dict', type: 'DICT', value: {} }
31617 ]);
31618 t.dict = makeDict(TOP_DICT_META, attrs, strings);
31619 return t;
31620 }
31621
31622 function makeTopDictIndex(topDict) {
31623 var t = new table.Record('Top DICT INDEX', [
31624 { name: 'topDicts', type: 'INDEX', value: [] }
31625 ]);
31626 t.topDicts = [{ name: 'topDict_0', type: 'TABLE', value: topDict }];
31627 return t;
31628 }
31629
31630 function makeStringIndex(strings) {
31631 var t = new table.Record('String INDEX', [
31632 { name: 'strings', type: 'INDEX', value: [] }
31633 ]);
31634 t.strings = [];
31635 for (var i = 0; i < strings.length; i += 1) {
31636 t.strings.push({
31637 name: 'string_' + i,
31638 type: 'STRING',
31639 value: strings[i]
31640 });
31641 }
31642
31643 return t;
31644 }
31645
31646 function makeGlobalSubrIndex() {
31647 // Currently we don't use subroutines.
31648 return new table.Record('Global Subr INDEX', [
31649 { name: 'subrs', type: 'INDEX', value: [] }
31650 ]);
31651 }
31652
31653 function makeCharsets(glyphNames, strings) {
31654 var t = new table.Record('Charsets', [
31655 { name: 'format', type: 'Card8', value: 0 }
31656 ]);
31657 for (var i = 0; i < glyphNames.length; i += 1) {
31658 var glyphName = glyphNames[i];
31659 var glyphSID = encodeString(glyphName, strings);
31660 t.fields.push({ name: 'glyph_' + i, type: 'SID', value: glyphSID });
31661 }
31662
31663 return t;
31664 }
31665
31666 function glyphToOps(glyph) {
31667 var ops = [];
31668 var path = glyph.path;
31669 ops.push({ name: 'width', type: 'NUMBER', value: glyph.advanceWidth });
31670 var x = 0;
31671 var y = 0;
31672 for (var i = 0; i < path.commands.length; i += 1) {
31673 var dx = void 0;
31674 var dy = void 0;
31675 var cmd = path.commands[i];
31676 if (cmd.type === 'Q') {
31677 // CFF only supports bézier curves, so convert the quad to a bézier.
31678 var _13 = 1 / 3;
31679 var _23 = 2 / 3;
31680
31681 // We're going to create a new command so we don't change the original path.
31682 cmd = {
31683 type: 'C',
31684 x: cmd.x,
31685 y: cmd.y,
31686 x1: _13 * x + _23 * cmd.x1,
31687 y1: _13 * y + _23 * cmd.y1,
31688 x2: _13 * cmd.x + _23 * cmd.x1,
31689 y2: _13 * cmd.y + _23 * cmd.y1
31690 };
31691 }
31692
31693 if (cmd.type === 'M') {
31694 dx = Math.round(cmd.x - x);
31695 dy = Math.round(cmd.y - y);
31696 ops.push({ name: 'dx', type: 'NUMBER', value: dx });
31697 ops.push({ name: 'dy', type: 'NUMBER', value: dy });
31698 ops.push({ name: 'rmoveto', type: 'OP', value: 21 });
31699 x = Math.round(cmd.x);
31700 y = Math.round(cmd.y);
31701 } else if (cmd.type === 'L') {
31702 dx = Math.round(cmd.x - x);
31703 dy = Math.round(cmd.y - y);
31704 ops.push({ name: 'dx', type: 'NUMBER', value: dx });
31705 ops.push({ name: 'dy', type: 'NUMBER', value: dy });
31706 ops.push({ name: 'rlineto', type: 'OP', value: 5 });
31707 x = Math.round(cmd.x);
31708 y = Math.round(cmd.y);
31709 } else if (cmd.type === 'C') {
31710 var dx1 = Math.round(cmd.x1 - x);
31711 var dy1 = Math.round(cmd.y1 - y);
31712 var dx2 = Math.round(cmd.x2 - cmd.x1);
31713 var dy2 = Math.round(cmd.y2 - cmd.y1);
31714 dx = Math.round(cmd.x - cmd.x2);
31715 dy = Math.round(cmd.y - cmd.y2);
31716 ops.push({ name: 'dx1', type: 'NUMBER', value: dx1 });
31717 ops.push({ name: 'dy1', type: 'NUMBER', value: dy1 });
31718 ops.push({ name: 'dx2', type: 'NUMBER', value: dx2 });
31719 ops.push({ name: 'dy2', type: 'NUMBER', value: dy2 });
31720 ops.push({ name: 'dx', type: 'NUMBER', value: dx });
31721 ops.push({ name: 'dy', type: 'NUMBER', value: dy });
31722 ops.push({ name: 'rrcurveto', type: 'OP', value: 8 });
31723 x = Math.round(cmd.x);
31724 y = Math.round(cmd.y);
31725 }
31726
31727 // Contours are closed automatically.
31728 }
31729
31730 ops.push({ name: 'endchar', type: 'OP', value: 14 });
31731 return ops;
31732 }
31733
31734 function makeCharStringsIndex(glyphs) {
31735 var t = new table.Record('CharStrings INDEX', [
31736 { name: 'charStrings', type: 'INDEX', value: [] }
31737 ]);
31738
31739 for (var i = 0; i < glyphs.length; i += 1) {
31740 var glyph = glyphs.get(i);
31741 var ops = glyphToOps(glyph);
31742 t.charStrings.push({ name: glyph.name, type: 'CHARSTRING', value: ops });
31743 }
31744
31745 return t;
31746 }
31747
31748 function makePrivateDict(attrs, strings) {
31749 var t = new table.Record('Private DICT', [
31750 { name: 'dict', type: 'DICT', value: {} }
31751 ]);
31752 t.dict = makeDict(PRIVATE_DICT_META, attrs, strings);
31753 return t;
31754 }
31755
31756 function makeCFFTable(glyphs, options) {
31757 var t = new table.Table('CFF ', [
31758 { name: 'header', type: 'RECORD' },
31759 { name: 'nameIndex', type: 'RECORD' },
31760 { name: 'topDictIndex', type: 'RECORD' },
31761 { name: 'stringIndex', type: 'RECORD' },
31762 { name: 'globalSubrIndex', type: 'RECORD' },
31763 { name: 'charsets', type: 'RECORD' },
31764 { name: 'charStringsIndex', type: 'RECORD' },
31765 { name: 'privateDict', type: 'RECORD' }
31766 ]);
31767
31768 var fontScale = 1 / options.unitsPerEm;
31769 // We use non-zero values for the offsets so that the DICT encodes them.
31770 // This is important because the size of the Top DICT plays a role in offset calculation,
31771 // and the size shouldn't change after we've written correct offsets.
31772 var attrs = {
31773 version: options.version,
31774 fullName: options.fullName,
31775 familyName: options.familyName,
31776 weight: options.weightName,
31777 fontBBox: options.fontBBox || [0, 0, 0, 0],
31778 fontMatrix: [fontScale, 0, 0, fontScale, 0, 0],
31779 charset: 999,
31780 encoding: 0,
31781 charStrings: 999,
31782 private: [0, 999]
31783 };
31784
31785 var privateAttrs = {};
31786
31787 var glyphNames = [];
31788 var glyph;
31789
31790 // Skip first glyph (.notdef)
31791 for (var i = 1; i < glyphs.length; i += 1) {
31792 glyph = glyphs.get(i);
31793 glyphNames.push(glyph.name);
31794 }
31795
31796 var strings = [];
31797
31798 t.header = makeHeader();
31799 t.nameIndex = makeNameIndex([options.postScriptName]);
31800 var topDict = makeTopDict(attrs, strings);
31801 t.topDictIndex = makeTopDictIndex(topDict);
31802 t.globalSubrIndex = makeGlobalSubrIndex();
31803 t.charsets = makeCharsets(glyphNames, strings);
31804 t.charStringsIndex = makeCharStringsIndex(glyphs);
31805 t.privateDict = makePrivateDict(privateAttrs, strings);
31806
31807 // Needs to come at the end, to encode all custom strings used in the font.
31808 t.stringIndex = makeStringIndex(strings);
31809
31810 var startOffset =
31811 t.header.sizeOf() +
31812 t.nameIndex.sizeOf() +
31813 t.topDictIndex.sizeOf() +
31814 t.stringIndex.sizeOf() +
31815 t.globalSubrIndex.sizeOf();
31816 attrs.charset = startOffset;
31817
31818 // We use the CFF standard encoding; proper encoding will be handled in cmap.
31819 attrs.encoding = 0;
31820 attrs.charStrings = attrs.charset + t.charsets.sizeOf();
31821 attrs.private[1] = attrs.charStrings + t.charStringsIndex.sizeOf();
31822
31823 // Recreate the Top DICT INDEX with the correct offsets.
31824 topDict = makeTopDict(attrs, strings);
31825 t.topDictIndex = makeTopDictIndex(topDict);
31826
31827 return t;
31828 }
31829
31830 var cff = { parse: parseCFFTable, make: makeCFFTable };
31831
31832 // The `head` table contains global information about the font.
31833
31834 // Parse the header `head` table
31835 function parseHeadTable(data, start) {
31836 var head = {};
31837 var p = new parse.Parser(data, start);
31838 head.version = p.parseVersion();
31839 head.fontRevision = Math.round(p.parseFixed() * 1000) / 1000;
31840 head.checkSumAdjustment = p.parseULong();
31841 head.magicNumber = p.parseULong();
31842 check.argument(
31843 head.magicNumber === 0x5f0f3cf5,
31844 'Font header has wrong magic number.'
31845 );
31846 head.flags = p.parseUShort();
31847 head.unitsPerEm = p.parseUShort();
31848 head.created = p.parseLongDateTime();
31849 head.modified = p.parseLongDateTime();
31850 head.xMin = p.parseShort();
31851 head.yMin = p.parseShort();
31852 head.xMax = p.parseShort();
31853 head.yMax = p.parseShort();
31854 head.macStyle = p.parseUShort();
31855 head.lowestRecPPEM = p.parseUShort();
31856 head.fontDirectionHint = p.parseShort();
31857 head.indexToLocFormat = p.parseShort();
31858 head.glyphDataFormat = p.parseShort();
31859 return head;
31860 }
31861
31862 function makeHeadTable(options) {
31863 // Apple Mac timestamp epoch is 01/01/1904 not 01/01/1970
31864 var timestamp = Math.round(new Date().getTime() / 1000) + 2082844800;
31865 var createdTimestamp = timestamp;
31866
31867 if (options.createdTimestamp) {
31868 createdTimestamp = options.createdTimestamp + 2082844800;
31869 }
31870
31871 return new table.Table(
31872 'head',
31873 [
31874 { name: 'version', type: 'FIXED', value: 0x00010000 },
31875 { name: 'fontRevision', type: 'FIXED', value: 0x00010000 },
31876 { name: 'checkSumAdjustment', type: 'ULONG', value: 0 },
31877 { name: 'magicNumber', type: 'ULONG', value: 0x5f0f3cf5 },
31878 { name: 'flags', type: 'USHORT', value: 0 },
31879 { name: 'unitsPerEm', type: 'USHORT', value: 1000 },
31880 { name: 'created', type: 'LONGDATETIME', value: createdTimestamp },
31881 { name: 'modified', type: 'LONGDATETIME', value: timestamp },
31882 { name: 'xMin', type: 'SHORT', value: 0 },
31883 { name: 'yMin', type: 'SHORT', value: 0 },
31884 { name: 'xMax', type: 'SHORT', value: 0 },
31885 { name: 'yMax', type: 'SHORT', value: 0 },
31886 { name: 'macStyle', type: 'USHORT', value: 0 },
31887 { name: 'lowestRecPPEM', type: 'USHORT', value: 0 },
31888 { name: 'fontDirectionHint', type: 'SHORT', value: 2 },
31889 { name: 'indexToLocFormat', type: 'SHORT', value: 0 },
31890 { name: 'glyphDataFormat', type: 'SHORT', value: 0 }
31891 ],
31892 options
31893 );
31894 }
31895
31896 var head = { parse: parseHeadTable, make: makeHeadTable };
31897
31898 // The `hhea` table contains information for horizontal layout.
31899
31900 // Parse the horizontal header `hhea` table
31901 function parseHheaTable(data, start) {
31902 var hhea = {};
31903 var p = new parse.Parser(data, start);
31904 hhea.version = p.parseVersion();
31905 hhea.ascender = p.parseShort();
31906 hhea.descender = p.parseShort();
31907 hhea.lineGap = p.parseShort();
31908 hhea.advanceWidthMax = p.parseUShort();
31909 hhea.minLeftSideBearing = p.parseShort();
31910 hhea.minRightSideBearing = p.parseShort();
31911 hhea.xMaxExtent = p.parseShort();
31912 hhea.caretSlopeRise = p.parseShort();
31913 hhea.caretSlopeRun = p.parseShort();
31914 hhea.caretOffset = p.parseShort();
31915 p.relativeOffset += 8;
31916 hhea.metricDataFormat = p.parseShort();
31917 hhea.numberOfHMetrics = p.parseUShort();
31918 return hhea;
31919 }
31920
31921 function makeHheaTable(options) {
31922 return new table.Table(
31923 'hhea',
31924 [
31925 { name: 'version', type: 'FIXED', value: 0x00010000 },
31926 { name: 'ascender', type: 'FWORD', value: 0 },
31927 { name: 'descender', type: 'FWORD', value: 0 },
31928 { name: 'lineGap', type: 'FWORD', value: 0 },
31929 { name: 'advanceWidthMax', type: 'UFWORD', value: 0 },
31930 { name: 'minLeftSideBearing', type: 'FWORD', value: 0 },
31931 { name: 'minRightSideBearing', type: 'FWORD', value: 0 },
31932 { name: 'xMaxExtent', type: 'FWORD', value: 0 },
31933 { name: 'caretSlopeRise', type: 'SHORT', value: 1 },
31934 { name: 'caretSlopeRun', type: 'SHORT', value: 0 },
31935 { name: 'caretOffset', type: 'SHORT', value: 0 },
31936 { name: 'reserved1', type: 'SHORT', value: 0 },
31937 { name: 'reserved2', type: 'SHORT', value: 0 },
31938 { name: 'reserved3', type: 'SHORT', value: 0 },
31939 { name: 'reserved4', type: 'SHORT', value: 0 },
31940 { name: 'metricDataFormat', type: 'SHORT', value: 0 },
31941 { name: 'numberOfHMetrics', type: 'USHORT', value: 0 }
31942 ],
31943 options
31944 );
31945 }
31946
31947 var hhea = { parse: parseHheaTable, make: makeHheaTable };
31948
31949 // The `hmtx` table contains the horizontal metrics for all glyphs.
31950
31951 // Parse the `hmtx` table, which contains the horizontal metrics for all glyphs.
31952 // This function augments the glyph array, adding the advanceWidth and leftSideBearing to each glyph.
31953 function parseHmtxTable(data, start, numMetrics, numGlyphs, glyphs) {
31954 var advanceWidth;
31955 var leftSideBearing;
31956 var p = new parse.Parser(data, start);
31957 for (var i = 0; i < numGlyphs; i += 1) {
31958 // If the font is monospaced, only one entry is needed. This last entry applies to all subsequent glyphs.
31959 if (i < numMetrics) {
31960 advanceWidth = p.parseUShort();
31961 leftSideBearing = p.parseShort();
31962 }
31963
31964 var glyph = glyphs.get(i);
31965 glyph.advanceWidth = advanceWidth;
31966 glyph.leftSideBearing = leftSideBearing;
31967 }
31968 }
31969
31970 function makeHmtxTable(glyphs) {
31971 var t = new table.Table('hmtx', []);
31972 for (var i = 0; i < glyphs.length; i += 1) {
31973 var glyph = glyphs.get(i);
31974 var advanceWidth = glyph.advanceWidth || 0;
31975 var leftSideBearing = glyph.leftSideBearing || 0;
31976 t.fields.push({
31977 name: 'advanceWidth_' + i,
31978 type: 'USHORT',
31979 value: advanceWidth
31980 });
31981 t.fields.push({
31982 name: 'leftSideBearing_' + i,
31983 type: 'SHORT',
31984 value: leftSideBearing
31985 });
31986 }
31987
31988 return t;
31989 }
31990
31991 var hmtx = { parse: parseHmtxTable, make: makeHmtxTable };
31992
31993 // The `ltag` table stores IETF BCP-47 language tags. It allows supporting
31994
31995 function makeLtagTable(tags) {
31996 var result = new table.Table('ltag', [
31997 { name: 'version', type: 'ULONG', value: 1 },
31998 { name: 'flags', type: 'ULONG', value: 0 },
31999 { name: 'numTags', type: 'ULONG', value: tags.length }
32000 ]);
32001
32002 var stringPool = '';
32003 var stringPoolOffset = 12 + tags.length * 4;
32004 for (var i = 0; i < tags.length; ++i) {
32005 var pos = stringPool.indexOf(tags[i]);
32006 if (pos < 0) {
32007 pos = stringPool.length;
32008 stringPool += tags[i];
32009 }
32010
32011 result.fields.push({
32012 name: 'offset ' + i,
32013 type: 'USHORT',
32014 value: stringPoolOffset + pos
32015 });
32016 result.fields.push({
32017 name: 'length ' + i,
32018 type: 'USHORT',
32019 value: tags[i].length
32020 });
32021 }
32022
32023 result.fields.push({
32024 name: 'stringPool',
32025 type: 'CHARARRAY',
32026 value: stringPool
32027 });
32028 return result;
32029 }
32030
32031 function parseLtagTable(data, start) {
32032 var p = new parse.Parser(data, start);
32033 var tableVersion = p.parseULong();
32034 check.argument(tableVersion === 1, 'Unsupported ltag table version.');
32035 // The 'ltag' specification does not define any flags; skip the field.
32036 p.skip('uLong', 1);
32037 var numTags = p.parseULong();
32038
32039 var tags = [];
32040 for (var i = 0; i < numTags; i++) {
32041 var tag = '';
32042 var offset = start + p.parseUShort();
32043 var length = p.parseUShort();
32044 for (var j = offset; j < offset + length; ++j) {
32045 tag += String.fromCharCode(data.getInt8(j));
32046 }
32047
32048 tags.push(tag);
32049 }
32050
32051 return tags;
32052 }
32053
32054 var ltag = { make: makeLtagTable, parse: parseLtagTable };
32055
32056 // The `maxp` table establishes the memory requirements for the font.
32057
32058 // Parse the maximum profile `maxp` table.
32059 function parseMaxpTable(data, start) {
32060 var maxp = {};
32061 var p = new parse.Parser(data, start);
32062 maxp.version = p.parseVersion();
32063 maxp.numGlyphs = p.parseUShort();
32064 if (maxp.version === 1.0) {
32065 maxp.maxPoints = p.parseUShort();
32066 maxp.maxContours = p.parseUShort();
32067 maxp.maxCompositePoints = p.parseUShort();
32068 maxp.maxCompositeContours = p.parseUShort();
32069 maxp.maxZones = p.parseUShort();
32070 maxp.maxTwilightPoints = p.parseUShort();
32071 maxp.maxStorage = p.parseUShort();
32072 maxp.maxFunctionDefs = p.parseUShort();
32073 maxp.maxInstructionDefs = p.parseUShort();
32074 maxp.maxStackElements = p.parseUShort();
32075 maxp.maxSizeOfInstructions = p.parseUShort();
32076 maxp.maxComponentElements = p.parseUShort();
32077 maxp.maxComponentDepth = p.parseUShort();
32078 }
32079
32080 return maxp;
32081 }
32082
32083 function makeMaxpTable(numGlyphs) {
32084 return new table.Table('maxp', [
32085 { name: 'version', type: 'FIXED', value: 0x00005000 },
32086 { name: 'numGlyphs', type: 'USHORT', value: numGlyphs }
32087 ]);
32088 }
32089
32090 var maxp = { parse: parseMaxpTable, make: makeMaxpTable };
32091
32092 // The `name` naming table.
32093
32094 // NameIDs for the name table.
32095 var nameTableNames = [
32096 'copyright', // 0
32097 'fontFamily', // 1
32098 'fontSubfamily', // 2
32099 'uniqueID', // 3
32100 'fullName', // 4
32101 'version', // 5
32102 'postScriptName', // 6
32103 'trademark', // 7
32104 'manufacturer', // 8
32105 'designer', // 9
32106 'description', // 10
32107 'manufacturerURL', // 11
32108 'designerURL', // 12
32109 'license', // 13
32110 'licenseURL', // 14
32111 'reserved', // 15
32112 'preferredFamily', // 16
32113 'preferredSubfamily', // 17
32114 'compatibleFullName', // 18
32115 'sampleText', // 19
32116 'postScriptFindFontName', // 20
32117 'wwsFamily', // 21
32118 'wwsSubfamily' // 22
32119 ];
32120
32121 var macLanguages = {
32122 0: 'en',
32123 1: 'fr',
32124 2: 'de',
32125 3: 'it',
32126 4: 'nl',
32127 5: 'sv',
32128 6: 'es',
32129 7: 'da',
32130 8: 'pt',
32131 9: 'no',
32132 10: 'he',
32133 11: 'ja',
32134 12: 'ar',
32135 13: 'fi',
32136 14: 'el',
32137 15: 'is',
32138 16: 'mt',
32139 17: 'tr',
32140 18: 'hr',
32141 19: 'zh-Hant',
32142 20: 'ur',
32143 21: 'hi',
32144 22: 'th',
32145 23: 'ko',
32146 24: 'lt',
32147 25: 'pl',
32148 26: 'hu',
32149 27: 'es',
32150 28: 'lv',
32151 29: 'se',
32152 30: 'fo',
32153 31: 'fa',
32154 32: 'ru',
32155 33: 'zh',
32156 34: 'nl-BE',
32157 35: 'ga',
32158 36: 'sq',
32159 37: 'ro',
32160 38: 'cz',
32161 39: 'sk',
32162 40: 'si',
32163 41: 'yi',
32164 42: 'sr',
32165 43: 'mk',
32166 44: 'bg',
32167 45: 'uk',
32168 46: 'be',
32169 47: 'uz',
32170 48: 'kk',
32171 49: 'az-Cyrl',
32172 50: 'az-Arab',
32173 51: 'hy',
32174 52: 'ka',
32175 53: 'mo',
32176 54: 'ky',
32177 55: 'tg',
32178 56: 'tk',
32179 57: 'mn-CN',
32180 58: 'mn',
32181 59: 'ps',
32182 60: 'ks',
32183 61: 'ku',
32184 62: 'sd',
32185 63: 'bo',
32186 64: 'ne',
32187 65: 'sa',
32188 66: 'mr',
32189 67: 'bn',
32190 68: 'as',
32191 69: 'gu',
32192 70: 'pa',
32193 71: 'or',
32194 72: 'ml',
32195 73: 'kn',
32196 74: 'ta',
32197 75: 'te',
32198 76: 'si',
32199 77: 'my',
32200 78: 'km',
32201 79: 'lo',
32202 80: 'vi',
32203 81: 'id',
32204 82: 'tl',
32205 83: 'ms',
32206 84: 'ms-Arab',
32207 85: 'am',
32208 86: 'ti',
32209 87: 'om',
32210 88: 'so',
32211 89: 'sw',
32212 90: 'rw',
32213 91: 'rn',
32214 92: 'ny',
32215 93: 'mg',
32216 94: 'eo',
32217 128: 'cy',
32218 129: 'eu',
32219 130: 'ca',
32220 131: 'la',
32221 132: 'qu',
32222 133: 'gn',
32223 134: 'ay',
32224 135: 'tt',
32225 136: 'ug',
32226 137: 'dz',
32227 138: 'jv',
32228 139: 'su',
32229 140: 'gl',
32230 141: 'af',
32231 142: 'br',
32232 143: 'iu',
32233 144: 'gd',
32234 145: 'gv',
32235 146: 'ga',
32236 147: 'to',
32237 148: 'el-polyton',
32238 149: 'kl',
32239 150: 'az',
32240 151: 'nn'
32241 };
32242
32243 // MacOS language ID → MacOS script ID
32244 //
32245 // Note that the script ID is not sufficient to determine what encoding
32246 // to use in TrueType files. For some languages, MacOS used a modification
32247 // of a mainstream script. For example, an Icelandic name would be stored
32248 // with smRoman in the TrueType naming table, but the actual encoding
32249 // is a special Icelandic version of the normal Macintosh Roman encoding.
32250 // As another example, Inuktitut uses an 8-bit encoding for Canadian Aboriginal
32251 // Syllables but MacOS had run out of available script codes, so this was
32252 // done as a (pretty radical) "modification" of Ethiopic.
32253 //
32254 // http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/Readme.txt
32255 var macLanguageToScript = {
32256 0: 0, // langEnglish → smRoman
32257 1: 0, // langFrench → smRoman
32258 2: 0, // langGerman → smRoman
32259 3: 0, // langItalian → smRoman
32260 4: 0, // langDutch → smRoman
32261 5: 0, // langSwedish → smRoman
32262 6: 0, // langSpanish → smRoman
32263 7: 0, // langDanish → smRoman
32264 8: 0, // langPortuguese → smRoman
32265 9: 0, // langNorwegian → smRoman
32266 10: 5, // langHebrew → smHebrew
32267 11: 1, // langJapanese → smJapanese
32268 12: 4, // langArabic → smArabic
32269 13: 0, // langFinnish → smRoman
32270 14: 6, // langGreek → smGreek
32271 15: 0, // langIcelandic → smRoman (modified)
32272 16: 0, // langMaltese → smRoman
32273 17: 0, // langTurkish → smRoman (modified)
32274 18: 0, // langCroatian → smRoman (modified)
32275 19: 2, // langTradChinese → smTradChinese
32276 20: 4, // langUrdu → smArabic
32277 21: 9, // langHindi → smDevanagari
32278 22: 21, // langThai → smThai
32279 23: 3, // langKorean → smKorean
32280 24: 29, // langLithuanian → smCentralEuroRoman
32281 25: 29, // langPolish → smCentralEuroRoman
32282 26: 29, // langHungarian → smCentralEuroRoman
32283 27: 29, // langEstonian → smCentralEuroRoman
32284 28: 29, // langLatvian → smCentralEuroRoman
32285 29: 0, // langSami → smRoman
32286 30: 0, // langFaroese → smRoman (modified)
32287 31: 4, // langFarsi → smArabic (modified)
32288 32: 7, // langRussian → smCyrillic
32289 33: 25, // langSimpChinese → smSimpChinese
32290 34: 0, // langFlemish → smRoman
32291 35: 0, // langIrishGaelic → smRoman (modified)
32292 36: 0, // langAlbanian → smRoman
32293 37: 0, // langRomanian → smRoman (modified)
32294 38: 29, // langCzech → smCentralEuroRoman
32295 39: 29, // langSlovak → smCentralEuroRoman
32296 40: 0, // langSlovenian → smRoman (modified)
32297 41: 5, // langYiddish → smHebrew
32298 42: 7, // langSerbian → smCyrillic
32299 43: 7, // langMacedonian → smCyrillic
32300 44: 7, // langBulgarian → smCyrillic
32301 45: 7, // langUkrainian → smCyrillic (modified)
32302 46: 7, // langByelorussian → smCyrillic
32303 47: 7, // langUzbek → smCyrillic
32304 48: 7, // langKazakh → smCyrillic
32305 49: 7, // langAzerbaijani → smCyrillic
32306 50: 4, // langAzerbaijanAr → smArabic
32307 51: 24, // langArmenian → smArmenian
32308 52: 23, // langGeorgian → smGeorgian
32309 53: 7, // langMoldavian → smCyrillic
32310 54: 7, // langKirghiz → smCyrillic
32311 55: 7, // langTajiki → smCyrillic
32312 56: 7, // langTurkmen → smCyrillic
32313 57: 27, // langMongolian → smMongolian
32314 58: 7, // langMongolianCyr → smCyrillic
32315 59: 4, // langPashto → smArabic
32316 60: 4, // langKurdish → smArabic
32317 61: 4, // langKashmiri → smArabic
32318 62: 4, // langSindhi → smArabic
32319 63: 26, // langTibetan → smTibetan
32320 64: 9, // langNepali → smDevanagari
32321 65: 9, // langSanskrit → smDevanagari
32322 66: 9, // langMarathi → smDevanagari
32323 67: 13, // langBengali → smBengali
32324 68: 13, // langAssamese → smBengali
32325 69: 11, // langGujarati → smGujarati
32326 70: 10, // langPunjabi → smGurmukhi
32327 71: 12, // langOriya → smOriya
32328 72: 17, // langMalayalam → smMalayalam
32329 73: 16, // langKannada → smKannada
32330 74: 14, // langTamil → smTamil
32331 75: 15, // langTelugu → smTelugu
32332 76: 18, // langSinhalese → smSinhalese
32333 77: 19, // langBurmese → smBurmese
32334 78: 20, // langKhmer → smKhmer
32335 79: 22, // langLao → smLao
32336 80: 30, // langVietnamese → smVietnamese
32337 81: 0, // langIndonesian → smRoman
32338 82: 0, // langTagalog → smRoman
32339 83: 0, // langMalayRoman → smRoman
32340 84: 4, // langMalayArabic → smArabic
32341 85: 28, // langAmharic → smEthiopic
32342 86: 28, // langTigrinya → smEthiopic
32343 87: 28, // langOromo → smEthiopic
32344 88: 0, // langSomali → smRoman
32345 89: 0, // langSwahili → smRoman
32346 90: 0, // langKinyarwanda → smRoman
32347 91: 0, // langRundi → smRoman
32348 92: 0, // langNyanja → smRoman
32349 93: 0, // langMalagasy → smRoman
32350 94: 0, // langEsperanto → smRoman
32351 128: 0, // langWelsh → smRoman (modified)
32352 129: 0, // langBasque → smRoman
32353 130: 0, // langCatalan → smRoman
32354 131: 0, // langLatin → smRoman
32355 132: 0, // langQuechua → smRoman
32356 133: 0, // langGuarani → smRoman
32357 134: 0, // langAymara → smRoman
32358 135: 7, // langTatar → smCyrillic
32359 136: 4, // langUighur → smArabic
32360 137: 26, // langDzongkha → smTibetan
32361 138: 0, // langJavaneseRom → smRoman
32362 139: 0, // langSundaneseRom → smRoman
32363 140: 0, // langGalician → smRoman
32364 141: 0, // langAfrikaans → smRoman
32365 142: 0, // langBreton → smRoman (modified)
32366 143: 28, // langInuktitut → smEthiopic (modified)
32367 144: 0, // langScottishGaelic → smRoman (modified)
32368 145: 0, // langManxGaelic → smRoman (modified)
32369 146: 0, // langIrishGaelicScript → smRoman (modified)
32370 147: 0, // langTongan → smRoman
32371 148: 6, // langGreekAncient → smRoman
32372 149: 0, // langGreenlandic → smRoman
32373 150: 0, // langAzerbaijanRoman → smRoman
32374 151: 0 // langNynorsk → smRoman
32375 };
32376
32377 // While Microsoft indicates a region/country for all its language
32378 // IDs, we omit the region code if it's equal to the "most likely
32379 // region subtag" according to Unicode CLDR. For scripts, we omit
32380 // the subtag if it is equal to the Suppress-Script entry in the
32381 // IANA language subtag registry for IETF BCP 47.
32382 //
32383 // For example, Microsoft states that its language code 0x041A is
32384 // Croatian in Croatia. We transform this to the BCP 47 language code 'hr'
32385 // and not 'hr-HR' because Croatia is the default country for Croatian,
32386 // according to Unicode CLDR. As another example, Microsoft states
32387 // that 0x101A is Croatian (Latin) in Bosnia-Herzegovina. We transform
32388 // this to 'hr-BA' and not 'hr-Latn-BA' because Latin is the default script
32389 // for the Croatian language, according to IANA.
32390 //
32391 // http://www.unicode.org/cldr/charts/latest/supplemental/likely_subtags.html
32392 // http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry
32393 var windowsLanguages = {
32394 0x0436: 'af',
32395 0x041c: 'sq',
32396 0x0484: 'gsw',
32397 0x045e: 'am',
32398 0x1401: 'ar-DZ',
32399 0x3c01: 'ar-BH',
32400 0x0c01: 'ar',
32401 0x0801: 'ar-IQ',
32402 0x2c01: 'ar-JO',
32403 0x3401: 'ar-KW',
32404 0x3001: 'ar-LB',
32405 0x1001: 'ar-LY',
32406 0x1801: 'ary',
32407 0x2001: 'ar-OM',
32408 0x4001: 'ar-QA',
32409 0x0401: 'ar-SA',
32410 0x2801: 'ar-SY',
32411 0x1c01: 'aeb',
32412 0x3801: 'ar-AE',
32413 0x2401: 'ar-YE',
32414 0x042b: 'hy',
32415 0x044d: 'as',
32416 0x082c: 'az-Cyrl',
32417 0x042c: 'az',
32418 0x046d: 'ba',
32419 0x042d: 'eu',
32420 0x0423: 'be',
32421 0x0845: 'bn',
32422 0x0445: 'bn-IN',
32423 0x201a: 'bs-Cyrl',
32424 0x141a: 'bs',
32425 0x047e: 'br',
32426 0x0402: 'bg',
32427 0x0403: 'ca',
32428 0x0c04: 'zh-HK',
32429 0x1404: 'zh-MO',
32430 0x0804: 'zh',
32431 0x1004: 'zh-SG',
32432 0x0404: 'zh-TW',
32433 0x0483: 'co',
32434 0x041a: 'hr',
32435 0x101a: 'hr-BA',
32436 0x0405: 'cs',
32437 0x0406: 'da',
32438 0x048c: 'prs',
32439 0x0465: 'dv',
32440 0x0813: 'nl-BE',
32441 0x0413: 'nl',
32442 0x0c09: 'en-AU',
32443 0x2809: 'en-BZ',
32444 0x1009: 'en-CA',
32445 0x2409: 'en-029',
32446 0x4009: 'en-IN',
32447 0x1809: 'en-IE',
32448 0x2009: 'en-JM',
32449 0x4409: 'en-MY',
32450 0x1409: 'en-NZ',
32451 0x3409: 'en-PH',
32452 0x4809: 'en-SG',
32453 0x1c09: 'en-ZA',
32454 0x2c09: 'en-TT',
32455 0x0809: 'en-GB',
32456 0x0409: 'en',
32457 0x3009: 'en-ZW',
32458 0x0425: 'et',
32459 0x0438: 'fo',
32460 0x0464: 'fil',
32461 0x040b: 'fi',
32462 0x080c: 'fr-BE',
32463 0x0c0c: 'fr-CA',
32464 0x040c: 'fr',
32465 0x140c: 'fr-LU',
32466 0x180c: 'fr-MC',
32467 0x100c: 'fr-CH',
32468 0x0462: 'fy',
32469 0x0456: 'gl',
32470 0x0437: 'ka',
32471 0x0c07: 'de-AT',
32472 0x0407: 'de',
32473 0x1407: 'de-LI',
32474 0x1007: 'de-LU',
32475 0x0807: 'de-CH',
32476 0x0408: 'el',
32477 0x046f: 'kl',
32478 0x0447: 'gu',
32479 0x0468: 'ha',
32480 0x040d: 'he',
32481 0x0439: 'hi',
32482 0x040e: 'hu',
32483 0x040f: 'is',
32484 0x0470: 'ig',
32485 0x0421: 'id',
32486 0x045d: 'iu',
32487 0x085d: 'iu-Latn',
32488 0x083c: 'ga',
32489 0x0434: 'xh',
32490 0x0435: 'zu',
32491 0x0410: 'it',
32492 0x0810: 'it-CH',
32493 0x0411: 'ja',
32494 0x044b: 'kn',
32495 0x043f: 'kk',
32496 0x0453: 'km',
32497 0x0486: 'quc',
32498 0x0487: 'rw',
32499 0x0441: 'sw',
32500 0x0457: 'kok',
32501 0x0412: 'ko',
32502 0x0440: 'ky',
32503 0x0454: 'lo',
32504 0x0426: 'lv',
32505 0x0427: 'lt',
32506 0x082e: 'dsb',
32507 0x046e: 'lb',
32508 0x042f: 'mk',
32509 0x083e: 'ms-BN',
32510 0x043e: 'ms',
32511 0x044c: 'ml',
32512 0x043a: 'mt',
32513 0x0481: 'mi',
32514 0x047a: 'arn',
32515 0x044e: 'mr',
32516 0x047c: 'moh',
32517 0x0450: 'mn',
32518 0x0850: 'mn-CN',
32519 0x0461: 'ne',
32520 0x0414: 'nb',
32521 0x0814: 'nn',
32522 0x0482: 'oc',
32523 0x0448: 'or',
32524 0x0463: 'ps',
32525 0x0415: 'pl',
32526 0x0416: 'pt',
32527 0x0816: 'pt-PT',
32528 0x0446: 'pa',
32529 0x046b: 'qu-BO',
32530 0x086b: 'qu-EC',
32531 0x0c6b: 'qu',
32532 0x0418: 'ro',
32533 0x0417: 'rm',
32534 0x0419: 'ru',
32535 0x243b: 'smn',
32536 0x103b: 'smj-NO',
32537 0x143b: 'smj',
32538 0x0c3b: 'se-FI',
32539 0x043b: 'se',
32540 0x083b: 'se-SE',
32541 0x203b: 'sms',
32542 0x183b: 'sma-NO',
32543 0x1c3b: 'sms',
32544 0x044f: 'sa',
32545 0x1c1a: 'sr-Cyrl-BA',
32546 0x0c1a: 'sr',
32547 0x181a: 'sr-Latn-BA',
32548 0x081a: 'sr-Latn',
32549 0x046c: 'nso',
32550 0x0432: 'tn',
32551 0x045b: 'si',
32552 0x041b: 'sk',
32553 0x0424: 'sl',
32554 0x2c0a: 'es-AR',
32555 0x400a: 'es-BO',
32556 0x340a: 'es-CL',
32557 0x240a: 'es-CO',
32558 0x140a: 'es-CR',
32559 0x1c0a: 'es-DO',
32560 0x300a: 'es-EC',
32561 0x440a: 'es-SV',
32562 0x100a: 'es-GT',
32563 0x480a: 'es-HN',
32564 0x080a: 'es-MX',
32565 0x4c0a: 'es-NI',
32566 0x180a: 'es-PA',
32567 0x3c0a: 'es-PY',
32568 0x280a: 'es-PE',
32569 0x500a: 'es-PR',
32570
32571 // Microsoft has defined two different language codes for
32572 // “Spanish with modern sorting” and “Spanish with traditional
32573 // sorting”. This makes sense for collation APIs, and it would be
32574 // possible to express this in BCP 47 language tags via Unicode
32575 // extensions (eg., es-u-co-trad is Spanish with traditional
32576 // sorting). However, for storing names in fonts, the distinction
32577 // does not make sense, so we give “es” in both cases.
32578 0x0c0a: 'es',
32579 0x040a: 'es',
32580
32581 0x540a: 'es-US',
32582 0x380a: 'es-UY',
32583 0x200a: 'es-VE',
32584 0x081d: 'sv-FI',
32585 0x041d: 'sv',
32586 0x045a: 'syr',
32587 0x0428: 'tg',
32588 0x085f: 'tzm',
32589 0x0449: 'ta',
32590 0x0444: 'tt',
32591 0x044a: 'te',
32592 0x041e: 'th',
32593 0x0451: 'bo',
32594 0x041f: 'tr',
32595 0x0442: 'tk',
32596 0x0480: 'ug',
32597 0x0422: 'uk',
32598 0x042e: 'hsb',
32599 0x0420: 'ur',
32600 0x0843: 'uz-Cyrl',
32601 0x0443: 'uz',
32602 0x042a: 'vi',
32603 0x0452: 'cy',
32604 0x0488: 'wo',
32605 0x0485: 'sah',
32606 0x0478: 'ii',
32607 0x046a: 'yo'
32608 };
32609
32610 // Returns a IETF BCP 47 language code, for example 'zh-Hant'
32611 // for 'Chinese in the traditional script'.
32612 function getLanguageCode(platformID, languageID, ltag) {
32613 switch (platformID) {
32614 case 0: // Unicode
32615 if (languageID === 0xffff) {
32616 return 'und';
32617 } else if (ltag) {
32618 return ltag[languageID];
32619 }
32620
32621 break;
32622
32623 case 1: // Macintosh
32624 return macLanguages[languageID];
32625
32626 case 3: // Windows
32627 return windowsLanguages[languageID];
32628 }
32629
32630 return undefined;
32631 }
32632
32633 var utf16 = 'utf-16';
32634
32635 // MacOS script ID → encoding. This table stores the default case,
32636 // which can be overridden by macLanguageEncodings.
32637 var macScriptEncodings = {
32638 0: 'macintosh', // smRoman
32639 1: 'x-mac-japanese', // smJapanese
32640 2: 'x-mac-chinesetrad', // smTradChinese
32641 3: 'x-mac-korean', // smKorean
32642 6: 'x-mac-greek', // smGreek
32643 7: 'x-mac-cyrillic', // smCyrillic
32644 9: 'x-mac-devanagai', // smDevanagari
32645 10: 'x-mac-gurmukhi', // smGurmukhi
32646 11: 'x-mac-gujarati', // smGujarati
32647 12: 'x-mac-oriya', // smOriya
32648 13: 'x-mac-bengali', // smBengali
32649 14: 'x-mac-tamil', // smTamil
32650 15: 'x-mac-telugu', // smTelugu
32651 16: 'x-mac-kannada', // smKannada
32652 17: 'x-mac-malayalam', // smMalayalam
32653 18: 'x-mac-sinhalese', // smSinhalese
32654 19: 'x-mac-burmese', // smBurmese
32655 20: 'x-mac-khmer', // smKhmer
32656 21: 'x-mac-thai', // smThai
32657 22: 'x-mac-lao', // smLao
32658 23: 'x-mac-georgian', // smGeorgian
32659 24: 'x-mac-armenian', // smArmenian
32660 25: 'x-mac-chinesesimp', // smSimpChinese
32661 26: 'x-mac-tibetan', // smTibetan
32662 27: 'x-mac-mongolian', // smMongolian
32663 28: 'x-mac-ethiopic', // smEthiopic
32664 29: 'x-mac-ce', // smCentralEuroRoman
32665 30: 'x-mac-vietnamese', // smVietnamese
32666 31: 'x-mac-extarabic' // smExtArabic
32667 };
32668
32669 // MacOS language ID → encoding. This table stores the exceptional
32670 // cases, which override macScriptEncodings. For writing MacOS naming
32671 // tables, we need to emit a MacOS script ID. Therefore, we cannot
32672 // merge macScriptEncodings into macLanguageEncodings.
32673 //
32674 // http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/Readme.txt
32675 var macLanguageEncodings = {
32676 15: 'x-mac-icelandic', // langIcelandic
32677 17: 'x-mac-turkish', // langTurkish
32678 18: 'x-mac-croatian', // langCroatian
32679 24: 'x-mac-ce', // langLithuanian
32680 25: 'x-mac-ce', // langPolish
32681 26: 'x-mac-ce', // langHungarian
32682 27: 'x-mac-ce', // langEstonian
32683 28: 'x-mac-ce', // langLatvian
32684 30: 'x-mac-icelandic', // langFaroese
32685 37: 'x-mac-romanian', // langRomanian
32686 38: 'x-mac-ce', // langCzech
32687 39: 'x-mac-ce', // langSlovak
32688 40: 'x-mac-ce', // langSlovenian
32689 143: 'x-mac-inuit', // langInuktitut
32690 146: 'x-mac-gaelic' // langIrishGaelicScript
32691 };
32692
32693 function getEncoding(platformID, encodingID, languageID) {
32694 switch (platformID) {
32695 case 0: // Unicode
32696 return utf16;
32697
32698 case 1: // Apple Macintosh
32699 return (
32700 macLanguageEncodings[languageID] || macScriptEncodings[encodingID]
32701 );
32702
32703 case 3: // Microsoft Windows
32704 if (encodingID === 1 || encodingID === 10) {
32705 return utf16;
32706 }
32707
32708 break;
32709 }
32710
32711 return undefined;
32712 }
32713
32714 // Parse the naming `name` table.
32715 // FIXME: Format 1 additional fields are not supported yet.
32716 // ltag is the content of the `ltag' table, such as ['en', 'zh-Hans', 'de-CH-1904'].
32717 function parseNameTable(data, start, ltag) {
32718 var name = {};
32719 var p = new parse.Parser(data, start);
32720 var format = p.parseUShort();
32721 var count = p.parseUShort();
32722 var stringOffset = p.offset + p.parseUShort();
32723 for (var i = 0; i < count; i++) {
32724 var platformID = p.parseUShort();
32725 var encodingID = p.parseUShort();
32726 var languageID = p.parseUShort();
32727 var nameID = p.parseUShort();
32728 var property = nameTableNames[nameID] || nameID;
32729 var byteLength = p.parseUShort();
32730 var offset = p.parseUShort();
32731 var language = getLanguageCode(platformID, languageID, ltag);
32732 var encoding = getEncoding(platformID, encodingID, languageID);
32733 if (encoding !== undefined && language !== undefined) {
32734 var text = void 0;
32735 if (encoding === utf16) {
32736 text = decode.UTF16(data, stringOffset + offset, byteLength);
32737 } else {
32738 text = decode.MACSTRING(
32739 data,
32740 stringOffset + offset,
32741 byteLength,
32742 encoding
32743 );
32744 }
32745
32746 if (text) {
32747 var translations = name[property];
32748 if (translations === undefined) {
32749 translations = name[property] = {};
32750 }
32751
32752 translations[language] = text;
32753 }
32754 }
32755 }
32756
32757 var langTagCount = 0;
32758 if (format === 1) {
32759 // FIXME: Also handle Microsoft's 'name' table 1.
32760 langTagCount = p.parseUShort();
32761 }
32762
32763 return name;
32764 }
32765
32766 // {23: 'foo'} → {'foo': 23}
32767 // ['bar', 'baz'] → {'bar': 0, 'baz': 1}
32768 function reverseDict(dict) {
32769 var result = {};
32770 for (var key in dict) {
32771 result[dict[key]] = parseInt(key);
32772 }
32773
32774 return result;
32775 }
32776
32777 function makeNameRecord(
32778 platformID,
32779 encodingID,
32780 languageID,
32781 nameID,
32782 length,
32783 offset
32784 ) {
32785 return new table.Record('NameRecord', [
32786 { name: 'platformID', type: 'USHORT', value: platformID },
32787 { name: 'encodingID', type: 'USHORT', value: encodingID },
32788 { name: 'languageID', type: 'USHORT', value: languageID },
32789 { name: 'nameID', type: 'USHORT', value: nameID },
32790 { name: 'length', type: 'USHORT', value: length },
32791 { name: 'offset', type: 'USHORT', value: offset }
32792 ]);
32793 }
32794
32795 // Finds the position of needle in haystack, or -1 if not there.
32796 // Like String.indexOf(), but for arrays.
32797 function findSubArray(needle, haystack) {
32798 var needleLength = needle.length;
32799 var limit = haystack.length - needleLength + 1;
32800
32801 loop: for (var pos = 0; pos < limit; pos++) {
32802 for (; pos < limit; pos++) {
32803 for (var k = 0; k < needleLength; k++) {
32804 if (haystack[pos + k] !== needle[k]) {
32805 continue loop;
32806 }
32807 }
32808
32809 return pos;
32810 }
32811 }
32812
32813 return -1;
32814 }
32815
32816 function addStringToPool(s, pool) {
32817 var offset = findSubArray(s, pool);
32818 if (offset < 0) {
32819 offset = pool.length;
32820 var i = 0;
32821 var len = s.length;
32822 for (; i < len; ++i) {
32823 pool.push(s[i]);
32824 }
32825 }
32826
32827 return offset;
32828 }
32829
32830 function makeNameTable(names, ltag) {
32831 var nameID;
32832 var nameIDs = [];
32833
32834 var namesWithNumericKeys = {};
32835 var nameTableIds = reverseDict(nameTableNames);
32836 for (var key in names) {
32837 var id = nameTableIds[key];
32838 if (id === undefined) {
32839 id = key;
32840 }
32841
32842 nameID = parseInt(id);
32843
32844 if (isNaN(nameID)) {
32845 throw new Error(
32846 'Name table entry "' +
32847 key +
32848 '" does not exist, see nameTableNames for complete list.'
32849 );
32850 }
32851
32852 namesWithNumericKeys[nameID] = names[key];
32853 nameIDs.push(nameID);
32854 }
32855
32856 var macLanguageIds = reverseDict(macLanguages);
32857 var windowsLanguageIds = reverseDict(windowsLanguages);
32858
32859 var nameRecords = [];
32860 var stringPool = [];
32861
32862 for (var i = 0; i < nameIDs.length; i++) {
32863 nameID = nameIDs[i];
32864 var translations = namesWithNumericKeys[nameID];
32865 for (var lang in translations) {
32866 var text = translations[lang];
32867
32868 // For MacOS, we try to emit the name in the form that was introduced
32869 // in the initial version of the TrueType spec (in the late 1980s).
32870 // However, this can fail for various reasons: the requested BCP 47
32871 // language code might not have an old-style Mac equivalent;
32872 // we might not have a codec for the needed character encoding;
32873 // or the name might contain characters that cannot be expressed
32874 // in the old-style Macintosh encoding. In case of failure, we emit
32875 // the name in a more modern fashion (Unicode encoding with BCP 47
32876 // language tags) that is recognized by MacOS 10.5, released in 2009.
32877 // If fonts were only read by operating systems, we could simply
32878 // emit all names in the modern form; this would be much easier.
32879 // However, there are many applications and libraries that read
32880 // 'name' tables directly, and these will usually only recognize
32881 // the ancient form (silently skipping the unrecognized names).
32882 var macPlatform = 1; // Macintosh
32883 var macLanguage = macLanguageIds[lang];
32884 var macScript = macLanguageToScript[macLanguage];
32885 var macEncoding = getEncoding(macPlatform, macScript, macLanguage);
32886 var macName = encode.MACSTRING(text, macEncoding);
32887 if (macName === undefined) {
32888 macPlatform = 0; // Unicode
32889 macLanguage = ltag.indexOf(lang);
32890 if (macLanguage < 0) {
32891 macLanguage = ltag.length;
32892 ltag.push(lang);
32893 }
32894
32895 macScript = 4; // Unicode 2.0 and later
32896 macName = encode.UTF16(text);
32897 }
32898
32899 var macNameOffset = addStringToPool(macName, stringPool);
32900 nameRecords.push(
32901 makeNameRecord(
32902 macPlatform,
32903 macScript,
32904 macLanguage,
32905 nameID,
32906 macName.length,
32907 macNameOffset
32908 )
32909 );
32910
32911 var winLanguage = windowsLanguageIds[lang];
32912 if (winLanguage !== undefined) {
32913 var winName = encode.UTF16(text);
32914 var winNameOffset = addStringToPool(winName, stringPool);
32915 nameRecords.push(
32916 makeNameRecord(
32917 3,
32918 1,
32919 winLanguage,
32920 nameID,
32921 winName.length,
32922 winNameOffset
32923 )
32924 );
32925 }
32926 }
32927 }
32928
32929 nameRecords.sort(function(a, b) {
32930 return (
32931 a.platformID - b.platformID ||
32932 a.encodingID - b.encodingID ||
32933 a.languageID - b.languageID ||
32934 a.nameID - b.nameID
32935 );
32936 });
32937
32938 var t = new table.Table('name', [
32939 { name: 'format', type: 'USHORT', value: 0 },
32940 { name: 'count', type: 'USHORT', value: nameRecords.length },
32941 {
32942 name: 'stringOffset',
32943 type: 'USHORT',
32944 value: 6 + nameRecords.length * 12
32945 }
32946 ]);
32947
32948 for (var r = 0; r < nameRecords.length; r++) {
32949 t.fields.push({
32950 name: 'record_' + r,
32951 type: 'RECORD',
32952 value: nameRecords[r]
32953 });
32954 }
32955
32956 t.fields.push({ name: 'strings', type: 'LITERAL', value: stringPool });
32957 return t;
32958 }
32959
32960 var _name = { parse: parseNameTable, make: makeNameTable };
32961
32962 // The `OS/2` table contains metrics required in OpenType fonts.
32963
32964 var unicodeRanges = [
32965 { begin: 0x0000, end: 0x007f }, // Basic Latin
32966 { begin: 0x0080, end: 0x00ff }, // Latin-1 Supplement
32967 { begin: 0x0100, end: 0x017f }, // Latin Extended-A
32968 { begin: 0x0180, end: 0x024f }, // Latin Extended-B
32969 { begin: 0x0250, end: 0x02af }, // IPA Extensions
32970 { begin: 0x02b0, end: 0x02ff }, // Spacing Modifier Letters
32971 { begin: 0x0300, end: 0x036f }, // Combining Diacritical Marks
32972 { begin: 0x0370, end: 0x03ff }, // Greek and Coptic
32973 { begin: 0x2c80, end: 0x2cff }, // Coptic
32974 { begin: 0x0400, end: 0x04ff }, // Cyrillic
32975 { begin: 0x0530, end: 0x058f }, // Armenian
32976 { begin: 0x0590, end: 0x05ff }, // Hebrew
32977 { begin: 0xa500, end: 0xa63f }, // Vai
32978 { begin: 0x0600, end: 0x06ff }, // Arabic
32979 { begin: 0x07c0, end: 0x07ff }, // NKo
32980 { begin: 0x0900, end: 0x097f }, // Devanagari
32981 { begin: 0x0980, end: 0x09ff }, // Bengali
32982 { begin: 0x0a00, end: 0x0a7f }, // Gurmukhi
32983 { begin: 0x0a80, end: 0x0aff }, // Gujarati
32984 { begin: 0x0b00, end: 0x0b7f }, // Oriya
32985 { begin: 0x0b80, end: 0x0bff }, // Tamil
32986 { begin: 0x0c00, end: 0x0c7f }, // Telugu
32987 { begin: 0x0c80, end: 0x0cff }, // Kannada
32988 { begin: 0x0d00, end: 0x0d7f }, // Malayalam
32989 { begin: 0x0e00, end: 0x0e7f }, // Thai
32990 { begin: 0x0e80, end: 0x0eff }, // Lao
32991 { begin: 0x10a0, end: 0x10ff }, // Georgian
32992 { begin: 0x1b00, end: 0x1b7f }, // Balinese
32993 { begin: 0x1100, end: 0x11ff }, // Hangul Jamo
32994 { begin: 0x1e00, end: 0x1eff }, // Latin Extended Additional
32995 { begin: 0x1f00, end: 0x1fff }, // Greek Extended
32996 { begin: 0x2000, end: 0x206f }, // General Punctuation
32997 { begin: 0x2070, end: 0x209f }, // Superscripts And Subscripts
32998 { begin: 0x20a0, end: 0x20cf }, // Currency Symbol
32999 { begin: 0x20d0, end: 0x20ff }, // Combining Diacritical Marks For Symbols
33000 { begin: 0x2100, end: 0x214f }, // Letterlike Symbols
33001 { begin: 0x2150, end: 0x218f }, // Number Forms
33002 { begin: 0x2190, end: 0x21ff }, // Arrows
33003 { begin: 0x2200, end: 0x22ff }, // Mathematical Operators
33004 { begin: 0x2300, end: 0x23ff }, // Miscellaneous Technical
33005 { begin: 0x2400, end: 0x243f }, // Control Pictures
33006 { begin: 0x2440, end: 0x245f }, // Optical Character Recognition
33007 { begin: 0x2460, end: 0x24ff }, // Enclosed Alphanumerics
33008 { begin: 0x2500, end: 0x257f }, // Box Drawing
33009 { begin: 0x2580, end: 0x259f }, // Block Elements
33010 { begin: 0x25a0, end: 0x25ff }, // Geometric Shapes
33011 { begin: 0x2600, end: 0x26ff }, // Miscellaneous Symbols
33012 { begin: 0x2700, end: 0x27bf }, // Dingbats
33013 { begin: 0x3000, end: 0x303f }, // CJK Symbols And Punctuation
33014 { begin: 0x3040, end: 0x309f }, // Hiragana
33015 { begin: 0x30a0, end: 0x30ff }, // Katakana
33016 { begin: 0x3100, end: 0x312f }, // Bopomofo
33017 { begin: 0x3130, end: 0x318f }, // Hangul Compatibility Jamo
33018 { begin: 0xa840, end: 0xa87f }, // Phags-pa
33019 { begin: 0x3200, end: 0x32ff }, // Enclosed CJK Letters And Months
33020 { begin: 0x3300, end: 0x33ff }, // CJK Compatibility
33021 { begin: 0xac00, end: 0xd7af }, // Hangul Syllables
33022 { begin: 0xd800, end: 0xdfff }, // Non-Plane 0 *
33023 { begin: 0x10900, end: 0x1091f }, // Phoenicia
33024 { begin: 0x4e00, end: 0x9fff }, // CJK Unified Ideographs
33025 { begin: 0xe000, end: 0xf8ff }, // Private Use Area (plane 0)
33026 { begin: 0x31c0, end: 0x31ef }, // CJK Strokes
33027 { begin: 0xfb00, end: 0xfb4f }, // Alphabetic Presentation Forms
33028 { begin: 0xfb50, end: 0xfdff }, // Arabic Presentation Forms-A
33029 { begin: 0xfe20, end: 0xfe2f }, // Combining Half Marks
33030 { begin: 0xfe10, end: 0xfe1f }, // Vertical Forms
33031 { begin: 0xfe50, end: 0xfe6f }, // Small Form Variants
33032 { begin: 0xfe70, end: 0xfeff }, // Arabic Presentation Forms-B
33033 { begin: 0xff00, end: 0xffef }, // Halfwidth And Fullwidth Forms
33034 { begin: 0xfff0, end: 0xffff }, // Specials
33035 { begin: 0x0f00, end: 0x0fff }, // Tibetan
33036 { begin: 0x0700, end: 0x074f }, // Syriac
33037 { begin: 0x0780, end: 0x07bf }, // Thaana
33038 { begin: 0x0d80, end: 0x0dff }, // Sinhala
33039 { begin: 0x1000, end: 0x109f }, // Myanmar
33040 { begin: 0x1200, end: 0x137f }, // Ethiopic
33041 { begin: 0x13a0, end: 0x13ff }, // Cherokee
33042 { begin: 0x1400, end: 0x167f }, // Unified Canadian Aboriginal Syllabics
33043 { begin: 0x1680, end: 0x169f }, // Ogham
33044 { begin: 0x16a0, end: 0x16ff }, // Runic
33045 { begin: 0x1780, end: 0x17ff }, // Khmer
33046 { begin: 0x1800, end: 0x18af }, // Mongolian
33047 { begin: 0x2800, end: 0x28ff }, // Braille Patterns
33048 { begin: 0xa000, end: 0xa48f }, // Yi Syllables
33049 { begin: 0x1700, end: 0x171f }, // Tagalog
33050 { begin: 0x10300, end: 0x1032f }, // Old Italic
33051 { begin: 0x10330, end: 0x1034f }, // Gothic
33052 { begin: 0x10400, end: 0x1044f }, // Deseret
33053 { begin: 0x1d000, end: 0x1d0ff }, // Byzantine Musical Symbols
33054 { begin: 0x1d400, end: 0x1d7ff }, // Mathematical Alphanumeric Symbols
33055 { begin: 0xff000, end: 0xffffd }, // Private Use (plane 15)
33056 { begin: 0xfe00, end: 0xfe0f }, // Variation Selectors
33057 { begin: 0xe0000, end: 0xe007f }, // Tags
33058 { begin: 0x1900, end: 0x194f }, // Limbu
33059 { begin: 0x1950, end: 0x197f }, // Tai Le
33060 { begin: 0x1980, end: 0x19df }, // New Tai Lue
33061 { begin: 0x1a00, end: 0x1a1f }, // Buginese
33062 { begin: 0x2c00, end: 0x2c5f }, // Glagolitic
33063 { begin: 0x2d30, end: 0x2d7f }, // Tifinagh
33064 { begin: 0x4dc0, end: 0x4dff }, // Yijing Hexagram Symbols
33065 { begin: 0xa800, end: 0xa82f }, // Syloti Nagri
33066 { begin: 0x10000, end: 0x1007f }, // Linear B Syllabary
33067 { begin: 0x10140, end: 0x1018f }, // Ancient Greek Numbers
33068 { begin: 0x10380, end: 0x1039f }, // Ugaritic
33069 { begin: 0x103a0, end: 0x103df }, // Old Persian
33070 { begin: 0x10450, end: 0x1047f }, // Shavian
33071 { begin: 0x10480, end: 0x104af }, // Osmanya
33072 { begin: 0x10800, end: 0x1083f }, // Cypriot Syllabary
33073 { begin: 0x10a00, end: 0x10a5f }, // Kharoshthi
33074 { begin: 0x1d300, end: 0x1d35f }, // Tai Xuan Jing Symbols
33075 { begin: 0x12000, end: 0x123ff }, // Cuneiform
33076 { begin: 0x1d360, end: 0x1d37f }, // Counting Rod Numerals
33077 { begin: 0x1b80, end: 0x1bbf }, // Sundanese
33078 { begin: 0x1c00, end: 0x1c4f }, // Lepcha
33079 { begin: 0x1c50, end: 0x1c7f }, // Ol Chiki
33080 { begin: 0xa880, end: 0xa8df }, // Saurashtra
33081 { begin: 0xa900, end: 0xa92f }, // Kayah Li
33082 { begin: 0xa930, end: 0xa95f }, // Rejang
33083 { begin: 0xaa00, end: 0xaa5f }, // Cham
33084 { begin: 0x10190, end: 0x101cf }, // Ancient Symbols
33085 { begin: 0x101d0, end: 0x101ff }, // Phaistos Disc
33086 { begin: 0x102a0, end: 0x102df }, // Carian
33087 { begin: 0x1f030, end: 0x1f09f } // Domino Tiles
33088 ];
33089
33090 function getUnicodeRange(unicode) {
33091 for (var i = 0; i < unicodeRanges.length; i += 1) {
33092 var range = unicodeRanges[i];
33093 if (unicode >= range.begin && unicode < range.end) {
33094 return i;
33095 }
33096 }
33097
33098 return -1;
33099 }
33100
33101 // Parse the OS/2 and Windows metrics `OS/2` table
33102 function parseOS2Table(data, start) {
33103 var os2 = {};
33104 var p = new parse.Parser(data, start);
33105 os2.version = p.parseUShort();
33106 os2.xAvgCharWidth = p.parseShort();
33107 os2.usWeightClass = p.parseUShort();
33108 os2.usWidthClass = p.parseUShort();
33109 os2.fsType = p.parseUShort();
33110 os2.ySubscriptXSize = p.parseShort();
33111 os2.ySubscriptYSize = p.parseShort();
33112 os2.ySubscriptXOffset = p.parseShort();
33113 os2.ySubscriptYOffset = p.parseShort();
33114 os2.ySuperscriptXSize = p.parseShort();
33115 os2.ySuperscriptYSize = p.parseShort();
33116 os2.ySuperscriptXOffset = p.parseShort();
33117 os2.ySuperscriptYOffset = p.parseShort();
33118 os2.yStrikeoutSize = p.parseShort();
33119 os2.yStrikeoutPosition = p.parseShort();
33120 os2.sFamilyClass = p.parseShort();
33121 os2.panose = [];
33122 for (var i = 0; i < 10; i++) {
33123 os2.panose[i] = p.parseByte();
33124 }
33125
33126 os2.ulUnicodeRange1 = p.parseULong();
33127 os2.ulUnicodeRange2 = p.parseULong();
33128 os2.ulUnicodeRange3 = p.parseULong();
33129 os2.ulUnicodeRange4 = p.parseULong();
33130 os2.achVendID = String.fromCharCode(
33131 p.parseByte(),
33132 p.parseByte(),
33133 p.parseByte(),
33134 p.parseByte()
33135 );
33136 os2.fsSelection = p.parseUShort();
33137 os2.usFirstCharIndex = p.parseUShort();
33138 os2.usLastCharIndex = p.parseUShort();
33139 os2.sTypoAscender = p.parseShort();
33140 os2.sTypoDescender = p.parseShort();
33141 os2.sTypoLineGap = p.parseShort();
33142 os2.usWinAscent = p.parseUShort();
33143 os2.usWinDescent = p.parseUShort();
33144 if (os2.version >= 1) {
33145 os2.ulCodePageRange1 = p.parseULong();
33146 os2.ulCodePageRange2 = p.parseULong();
33147 }
33148
33149 if (os2.version >= 2) {
33150 os2.sxHeight = p.parseShort();
33151 os2.sCapHeight = p.parseShort();
33152 os2.usDefaultChar = p.parseUShort();
33153 os2.usBreakChar = p.parseUShort();
33154 os2.usMaxContent = p.parseUShort();
33155 }
33156
33157 return os2;
33158 }
33159
33160 function makeOS2Table(options) {
33161 return new table.Table(
33162 'OS/2',
33163 [
33164 { name: 'version', type: 'USHORT', value: 0x0003 },
33165 { name: 'xAvgCharWidth', type: 'SHORT', value: 0 },
33166 { name: 'usWeightClass', type: 'USHORT', value: 0 },
33167 { name: 'usWidthClass', type: 'USHORT', value: 0 },
33168 { name: 'fsType', type: 'USHORT', value: 0 },
33169 { name: 'ySubscriptXSize', type: 'SHORT', value: 650 },
33170 { name: 'ySubscriptYSize', type: 'SHORT', value: 699 },
33171 { name: 'ySubscriptXOffset', type: 'SHORT', value: 0 },
33172 { name: 'ySubscriptYOffset', type: 'SHORT', value: 140 },
33173 { name: 'ySuperscriptXSize', type: 'SHORT', value: 650 },
33174 { name: 'ySuperscriptYSize', type: 'SHORT', value: 699 },
33175 { name: 'ySuperscriptXOffset', type: 'SHORT', value: 0 },
33176 { name: 'ySuperscriptYOffset', type: 'SHORT', value: 479 },
33177 { name: 'yStrikeoutSize', type: 'SHORT', value: 49 },
33178 { name: 'yStrikeoutPosition', type: 'SHORT', value: 258 },
33179 { name: 'sFamilyClass', type: 'SHORT', value: 0 },
33180 { name: 'bFamilyType', type: 'BYTE', value: 0 },
33181 { name: 'bSerifStyle', type: 'BYTE', value: 0 },
33182 { name: 'bWeight', type: 'BYTE', value: 0 },
33183 { name: 'bProportion', type: 'BYTE', value: 0 },
33184 { name: 'bContrast', type: 'BYTE', value: 0 },
33185 { name: 'bStrokeVariation', type: 'BYTE', value: 0 },
33186 { name: 'bArmStyle', type: 'BYTE', value: 0 },
33187 { name: 'bLetterform', type: 'BYTE', value: 0 },
33188 { name: 'bMidline', type: 'BYTE', value: 0 },
33189 { name: 'bXHeight', type: 'BYTE', value: 0 },
33190 { name: 'ulUnicodeRange1', type: 'ULONG', value: 0 },
33191 { name: 'ulUnicodeRange2', type: 'ULONG', value: 0 },
33192 { name: 'ulUnicodeRange3', type: 'ULONG', value: 0 },
33193 { name: 'ulUnicodeRange4', type: 'ULONG', value: 0 },
33194 { name: 'achVendID', type: 'CHARARRAY', value: 'XXXX' },
33195 { name: 'fsSelection', type: 'USHORT', value: 0 },
33196 { name: 'usFirstCharIndex', type: 'USHORT', value: 0 },
33197 { name: 'usLastCharIndex', type: 'USHORT', value: 0 },
33198 { name: 'sTypoAscender', type: 'SHORT', value: 0 },
33199 { name: 'sTypoDescender', type: 'SHORT', value: 0 },
33200 { name: 'sTypoLineGap', type: 'SHORT', value: 0 },
33201 { name: 'usWinAscent', type: 'USHORT', value: 0 },
33202 { name: 'usWinDescent', type: 'USHORT', value: 0 },
33203 { name: 'ulCodePageRange1', type: 'ULONG', value: 0 },
33204 { name: 'ulCodePageRange2', type: 'ULONG', value: 0 },
33205 { name: 'sxHeight', type: 'SHORT', value: 0 },
33206 { name: 'sCapHeight', type: 'SHORT', value: 0 },
33207 { name: 'usDefaultChar', type: 'USHORT', value: 0 },
33208 { name: 'usBreakChar', type: 'USHORT', value: 0 },
33209 { name: 'usMaxContext', type: 'USHORT', value: 0 }
33210 ],
33211 options
33212 );
33213 }
33214
33215 var os2 = {
33216 parse: parseOS2Table,
33217 make: makeOS2Table,
33218 unicodeRanges: unicodeRanges,
33219 getUnicodeRange: getUnicodeRange
33220 };
33221
33222 // The `post` table stores additional PostScript information, such as glyph names.
33223
33224 // Parse the PostScript `post` table
33225 function parsePostTable(data, start) {
33226 var post = {};
33227 var p = new parse.Parser(data, start);
33228 post.version = p.parseVersion();
33229 post.italicAngle = p.parseFixed();
33230 post.underlinePosition = p.parseShort();
33231 post.underlineThickness = p.parseShort();
33232 post.isFixedPitch = p.parseULong();
33233 post.minMemType42 = p.parseULong();
33234 post.maxMemType42 = p.parseULong();
33235 post.minMemType1 = p.parseULong();
33236 post.maxMemType1 = p.parseULong();
33237 switch (post.version) {
33238 case 1:
33239 post.names = standardNames.slice();
33240 break;
33241 case 2:
33242 post.numberOfGlyphs = p.parseUShort();
33243 post.glyphNameIndex = new Array(post.numberOfGlyphs);
33244 for (var i = 0; i < post.numberOfGlyphs; i++) {
33245 post.glyphNameIndex[i] = p.parseUShort();
33246 }
33247
33248 post.names = [];
33249 for (var i$1 = 0; i$1 < post.numberOfGlyphs; i$1++) {
33250 if (post.glyphNameIndex[i$1] >= standardNames.length) {
33251 var nameLength = p.parseChar();
33252 post.names.push(p.parseString(nameLength));
33253 }
33254 }
33255
33256 break;
33257 case 2.5:
33258 post.numberOfGlyphs = p.parseUShort();
33259 post.offset = new Array(post.numberOfGlyphs);
33260 for (var i$2 = 0; i$2 < post.numberOfGlyphs; i$2++) {
33261 post.offset[i$2] = p.parseChar();
33262 }
33263
33264 break;
33265 }
33266 return post;
33267 }
33268
33269 function makePostTable() {
33270 return new table.Table('post', [
33271 { name: 'version', type: 'FIXED', value: 0x00030000 },
33272 { name: 'italicAngle', type: 'FIXED', value: 0 },
33273 { name: 'underlinePosition', type: 'FWORD', value: 0 },
33274 { name: 'underlineThickness', type: 'FWORD', value: 0 },
33275 { name: 'isFixedPitch', type: 'ULONG', value: 0 },
33276 { name: 'minMemType42', type: 'ULONG', value: 0 },
33277 { name: 'maxMemType42', type: 'ULONG', value: 0 },
33278 { name: 'minMemType1', type: 'ULONG', value: 0 },
33279 { name: 'maxMemType1', type: 'ULONG', value: 0 }
33280 ]);
33281 }
33282
33283 var post = { parse: parsePostTable, make: makePostTable };
33284
33285 // The `GSUB` table contains ligatures, among other things.
33286
33287 var subtableParsers = new Array(9); // subtableParsers[0] is unused
33288
33289 // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#SS
33290 subtableParsers[1] = function parseLookup1() {
33291 var start = this.offset + this.relativeOffset;
33292 var substFormat = this.parseUShort();
33293 if (substFormat === 1) {
33294 return {
33295 substFormat: 1,
33296 coverage: this.parsePointer(Parser.coverage),
33297 deltaGlyphId: this.parseUShort()
33298 };
33299 } else if (substFormat === 2) {
33300 return {
33301 substFormat: 2,
33302 coverage: this.parsePointer(Parser.coverage),
33303 substitute: this.parseOffset16List()
33304 };
33305 }
33306 check.assert(
33307 false,
33308 '0x' + start.toString(16) + ': lookup type 1 format must be 1 or 2.'
33309 );
33310 };
33311
33312 // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#MS
33313 subtableParsers[2] = function parseLookup2() {
33314 var substFormat = this.parseUShort();
33315 check.argument(
33316 substFormat === 1,
33317 'GSUB Multiple Substitution Subtable identifier-format must be 1'
33318 );
33319 return {
33320 substFormat: substFormat,
33321 coverage: this.parsePointer(Parser.coverage),
33322 sequences: this.parseListOfLists()
33323 };
33324 };
33325
33326 // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#AS
33327 subtableParsers[3] = function parseLookup3() {
33328 var substFormat = this.parseUShort();
33329 check.argument(
33330 substFormat === 1,
33331 'GSUB Alternate Substitution Subtable identifier-format must be 1'
33332 );
33333 return {
33334 substFormat: substFormat,
33335 coverage: this.parsePointer(Parser.coverage),
33336 alternateSets: this.parseListOfLists()
33337 };
33338 };
33339
33340 // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#LS
33341 subtableParsers[4] = function parseLookup4() {
33342 var substFormat = this.parseUShort();
33343 check.argument(
33344 substFormat === 1,
33345 'GSUB ligature table identifier-format must be 1'
33346 );
33347 return {
33348 substFormat: substFormat,
33349 coverage: this.parsePointer(Parser.coverage),
33350 ligatureSets: this.parseListOfLists(function() {
33351 return {
33352 ligGlyph: this.parseUShort(),
33353 components: this.parseUShortList(this.parseUShort() - 1)
33354 };
33355 })
33356 };
33357 };
33358
33359 var lookupRecordDesc = {
33360 sequenceIndex: Parser.uShort,
33361 lookupListIndex: Parser.uShort
33362 };
33363
33364 // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#CSF
33365 subtableParsers[5] = function parseLookup5() {
33366 var start = this.offset + this.relativeOffset;
33367 var substFormat = this.parseUShort();
33368
33369 if (substFormat === 1) {
33370 return {
33371 substFormat: substFormat,
33372 coverage: this.parsePointer(Parser.coverage),
33373 ruleSets: this.parseListOfLists(function() {
33374 var glyphCount = this.parseUShort();
33375 var substCount = this.parseUShort();
33376 return {
33377 input: this.parseUShortList(glyphCount - 1),
33378 lookupRecords: this.parseRecordList(substCount, lookupRecordDesc)
33379 };
33380 })
33381 };
33382 } else if (substFormat === 2) {
33383 return {
33384 substFormat: substFormat,
33385 coverage: this.parsePointer(Parser.coverage),
33386 classDef: this.parsePointer(Parser.classDef),
33387 classSets: this.parseListOfLists(function() {
33388 var glyphCount = this.parseUShort();
33389 var substCount = this.parseUShort();
33390 return {
33391 classes: this.parseUShortList(glyphCount - 1),
33392 lookupRecords: this.parseRecordList(substCount, lookupRecordDesc)
33393 };
33394 })
33395 };
33396 } else if (substFormat === 3) {
33397 var glyphCount = this.parseUShort();
33398 var substCount = this.parseUShort();
33399 return {
33400 substFormat: substFormat,
33401 coverages: this.parseList(glyphCount, Parser.pointer(Parser.coverage)),
33402 lookupRecords: this.parseRecordList(substCount, lookupRecordDesc)
33403 };
33404 }
33405 check.assert(
33406 false,
33407 '0x' + start.toString(16) + ': lookup type 5 format must be 1, 2 or 3.'
33408 );
33409 };
33410
33411 // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#CC
33412 subtableParsers[6] = function parseLookup6() {
33413 var start = this.offset + this.relativeOffset;
33414 var substFormat = this.parseUShort();
33415 if (substFormat === 1) {
33416 return {
33417 substFormat: 1,
33418 coverage: this.parsePointer(Parser.coverage),
33419 chainRuleSets: this.parseListOfLists(function() {
33420 return {
33421 backtrack: this.parseUShortList(),
33422 input: this.parseUShortList(this.parseShort() - 1),
33423 lookahead: this.parseUShortList(),
33424 lookupRecords: this.parseRecordList(lookupRecordDesc)
33425 };
33426 })
33427 };
33428 } else if (substFormat === 2) {
33429 return {
33430 substFormat: 2,
33431 coverage: this.parsePointer(Parser.coverage),
33432 backtrackClassDef: this.parsePointer(Parser.classDef),
33433 inputClassDef: this.parsePointer(Parser.classDef),
33434 lookaheadClassDef: this.parsePointer(Parser.classDef),
33435 chainClassSet: this.parseListOfLists(function() {
33436 return {
33437 backtrack: this.parseUShortList(),
33438 input: this.parseUShortList(this.parseShort() - 1),
33439 lookahead: this.parseUShortList(),
33440 lookupRecords: this.parseRecordList(lookupRecordDesc)
33441 };
33442 })
33443 };
33444 } else if (substFormat === 3) {
33445 return {
33446 substFormat: 3,
33447 backtrackCoverage: this.parseList(Parser.pointer(Parser.coverage)),
33448 inputCoverage: this.parseList(Parser.pointer(Parser.coverage)),
33449 lookaheadCoverage: this.parseList(Parser.pointer(Parser.coverage)),
33450 lookupRecords: this.parseRecordList(lookupRecordDesc)
33451 };
33452 }
33453 check.assert(
33454 false,
33455 '0x' + start.toString(16) + ': lookup type 6 format must be 1, 2 or 3.'
33456 );
33457 };
33458
33459 // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#ES
33460 subtableParsers[7] = function parseLookup7() {
33461 // Extension Substitution subtable
33462 var substFormat = this.parseUShort();
33463 check.argument(
33464 substFormat === 1,
33465 'GSUB Extension Substitution subtable identifier-format must be 1'
33466 );
33467 var extensionLookupType = this.parseUShort();
33468 var extensionParser = new Parser(
33469 this.data,
33470 this.offset + this.parseULong()
33471 );
33472 return {
33473 substFormat: 1,
33474 lookupType: extensionLookupType,
33475 extension: subtableParsers[extensionLookupType].call(extensionParser)
33476 };
33477 };
33478
33479 // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#RCCS
33480 subtableParsers[8] = function parseLookup8() {
33481 var substFormat = this.parseUShort();
33482 check.argument(
33483 substFormat === 1,
33484 'GSUB Reverse Chaining Contextual Single Substitution Subtable identifier-format must be 1'
33485 );
33486 return {
33487 substFormat: substFormat,
33488 coverage: this.parsePointer(Parser.coverage),
33489 backtrackCoverage: this.parseList(Parser.pointer(Parser.coverage)),
33490 lookaheadCoverage: this.parseList(Parser.pointer(Parser.coverage)),
33491 substitutes: this.parseUShortList()
33492 };
33493 };
33494
33495 // https://www.microsoft.com/typography/OTSPEC/gsub.htm
33496 function parseGsubTable(data, start) {
33497 start = start || 0;
33498 var p = new Parser(data, start);
33499 var tableVersion = p.parseVersion(1);
33500 check.argument(
33501 tableVersion === 1 || tableVersion === 1.1,
33502 'Unsupported GSUB table version.'
33503 );
33504 if (tableVersion === 1) {
33505 return {
33506 version: tableVersion,
33507 scripts: p.parseScriptList(),
33508 features: p.parseFeatureList(),
33509 lookups: p.parseLookupList(subtableParsers)
33510 };
33511 } else {
33512 return {
33513 version: tableVersion,
33514 scripts: p.parseScriptList(),
33515 features: p.parseFeatureList(),
33516 lookups: p.parseLookupList(subtableParsers),
33517 variations: p.parseFeatureVariationsList()
33518 };
33519 }
33520 }
33521
33522 // GSUB Writing //////////////////////////////////////////////
33523 var subtableMakers = new Array(9);
33524
33525 subtableMakers[1] = function makeLookup1(subtable) {
33526 if (subtable.substFormat === 1) {
33527 return new table.Table('substitutionTable', [
33528 { name: 'substFormat', type: 'USHORT', value: 1 },
33529 {
33530 name: 'coverage',
33531 type: 'TABLE',
33532 value: new table.Coverage(subtable.coverage)
33533 },
33534 { name: 'deltaGlyphID', type: 'USHORT', value: subtable.deltaGlyphId }
33535 ]);
33536 } else {
33537 return new table.Table(
33538 'substitutionTable',
33539 [
33540 { name: 'substFormat', type: 'USHORT', value: 2 },
33541 {
33542 name: 'coverage',
33543 type: 'TABLE',
33544 value: new table.Coverage(subtable.coverage)
33545 }
33546 ].concat(table.ushortList('substitute', subtable.substitute))
33547 );
33548 }
33549 check.fail('Lookup type 1 substFormat must be 1 or 2.');
33550 };
33551
33552 subtableMakers[3] = function makeLookup3(subtable) {
33553 check.assert(
33554 subtable.substFormat === 1,
33555 'Lookup type 3 substFormat must be 1.'
33556 );
33557 return new table.Table(
33558 'substitutionTable',
33559 [
33560 { name: 'substFormat', type: 'USHORT', value: 1 },
33561 {
33562 name: 'coverage',
33563 type: 'TABLE',
33564 value: new table.Coverage(subtable.coverage)
33565 }
33566 ].concat(
33567 table.tableList('altSet', subtable.alternateSets, function(
33568 alternateSet
33569 ) {
33570 return new table.Table(
33571 'alternateSetTable',
33572 table.ushortList('alternate', alternateSet)
33573 );
33574 })
33575 )
33576 );
33577 };
33578
33579 subtableMakers[4] = function makeLookup4(subtable) {
33580 check.assert(
33581 subtable.substFormat === 1,
33582 'Lookup type 4 substFormat must be 1.'
33583 );
33584 return new table.Table(
33585 'substitutionTable',
33586 [
33587 { name: 'substFormat', type: 'USHORT', value: 1 },
33588 {
33589 name: 'coverage',
33590 type: 'TABLE',
33591 value: new table.Coverage(subtable.coverage)
33592 }
33593 ].concat(
33594 table.tableList('ligSet', subtable.ligatureSets, function(ligatureSet) {
33595 return new table.Table(
33596 'ligatureSetTable',
33597 table.tableList('ligature', ligatureSet, function(ligature) {
33598 return new table.Table(
33599 'ligatureTable',
33600 [
33601 { name: 'ligGlyph', type: 'USHORT', value: ligature.ligGlyph }
33602 ].concat(
33603 table.ushortList(
33604 'component',
33605 ligature.components,
33606 ligature.components.length + 1
33607 )
33608 )
33609 );
33610 })
33611 );
33612 })
33613 )
33614 );
33615 };
33616
33617 function makeGsubTable(gsub) {
33618 return new table.Table('GSUB', [
33619 { name: 'version', type: 'ULONG', value: 0x10000 },
33620 {
33621 name: 'scripts',
33622 type: 'TABLE',
33623 value: new table.ScriptList(gsub.scripts)
33624 },
33625 {
33626 name: 'features',
33627 type: 'TABLE',
33628 value: new table.FeatureList(gsub.features)
33629 },
33630 {
33631 name: 'lookups',
33632 type: 'TABLE',
33633 value: new table.LookupList(gsub.lookups, subtableMakers)
33634 }
33635 ]);
33636 }
33637
33638 var gsub = { parse: parseGsubTable, make: makeGsubTable };
33639
33640 // The `GPOS` table contains kerning pairs, among other things.
33641
33642 // Parse the metadata `meta` table.
33643 // https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6meta.html
33644 function parseMetaTable(data, start) {
33645 var p = new parse.Parser(data, start);
33646 var tableVersion = p.parseULong();
33647 check.argument(tableVersion === 1, 'Unsupported META table version.');
33648 p.parseULong(); // flags - currently unused and set to 0
33649 p.parseULong(); // tableOffset
33650 var numDataMaps = p.parseULong();
33651
33652 var tags = {};
33653 for (var i = 0; i < numDataMaps; i++) {
33654 var tag = p.parseTag();
33655 var dataOffset = p.parseULong();
33656 var dataLength = p.parseULong();
33657 var text = decode.UTF8(data, start + dataOffset, dataLength);
33658
33659 tags[tag] = text;
33660 }
33661 return tags;
33662 }
33663
33664 function makeMetaTable(tags) {
33665 var numTags = Object.keys(tags).length;
33666 var stringPool = '';
33667 var stringPoolOffset = 16 + numTags * 12;
33668
33669 var result = new table.Table('meta', [
33670 { name: 'version', type: 'ULONG', value: 1 },
33671 { name: 'flags', type: 'ULONG', value: 0 },
33672 { name: 'offset', type: 'ULONG', value: stringPoolOffset },
33673 { name: 'numTags', type: 'ULONG', value: numTags }
33674 ]);
33675
33676 for (var tag in tags) {
33677 var pos = stringPool.length;
33678 stringPool += tags[tag];
33679
33680 result.fields.push({ name: 'tag ' + tag, type: 'TAG', value: tag });
33681 result.fields.push({
33682 name: 'offset ' + tag,
33683 type: 'ULONG',
33684 value: stringPoolOffset + pos
33685 });
33686 result.fields.push({
33687 name: 'length ' + tag,
33688 type: 'ULONG',
33689 value: tags[tag].length
33690 });
33691 }
33692
33693 result.fields.push({
33694 name: 'stringPool',
33695 type: 'CHARARRAY',
33696 value: stringPool
33697 });
33698
33699 return result;
33700 }
33701
33702 var meta = { parse: parseMetaTable, make: makeMetaTable };
33703
33704 // The `sfnt` wrapper provides organization for the tables in the font.
33705
33706 function log2(v) {
33707 return (Math.log(v) / Math.log(2)) | 0;
33708 }
33709
33710 function computeCheckSum(bytes) {
33711 while (bytes.length % 4 !== 0) {
33712 bytes.push(0);
33713 }
33714
33715 var sum = 0;
33716 for (var i = 0; i < bytes.length; i += 4) {
33717 sum +=
33718 (bytes[i] << 24) +
33719 (bytes[i + 1] << 16) +
33720 (bytes[i + 2] << 8) +
33721 bytes[i + 3];
33722 }
33723
33724 sum %= Math.pow(2, 32);
33725 return sum;
33726 }
33727
33728 function makeTableRecord(tag, checkSum, offset, length) {
33729 return new table.Record('Table Record', [
33730 { name: 'tag', type: 'TAG', value: tag !== undefined ? tag : '' },
33731 {
33732 name: 'checkSum',
33733 type: 'ULONG',
33734 value: checkSum !== undefined ? checkSum : 0
33735 },
33736 {
33737 name: 'offset',
33738 type: 'ULONG',
33739 value: offset !== undefined ? offset : 0
33740 },
33741 {
33742 name: 'length',
33743 type: 'ULONG',
33744 value: length !== undefined ? length : 0
33745 }
33746 ]);
33747 }
33748
33749 function makeSfntTable(tables) {
33750 var sfnt = new table.Table('sfnt', [
33751 { name: 'version', type: 'TAG', value: 'OTTO' },
33752 { name: 'numTables', type: 'USHORT', value: 0 },
33753 { name: 'searchRange', type: 'USHORT', value: 0 },
33754 { name: 'entrySelector', type: 'USHORT', value: 0 },
33755 { name: 'rangeShift', type: 'USHORT', value: 0 }
33756 ]);
33757 sfnt.tables = tables;
33758 sfnt.numTables = tables.length;
33759 var highestPowerOf2 = Math.pow(2, log2(sfnt.numTables));
33760 sfnt.searchRange = 16 * highestPowerOf2;
33761 sfnt.entrySelector = log2(highestPowerOf2);
33762 sfnt.rangeShift = sfnt.numTables * 16 - sfnt.searchRange;
33763
33764 var recordFields = [];
33765 var tableFields = [];
33766
33767 var offset = sfnt.sizeOf() + makeTableRecord().sizeOf() * sfnt.numTables;
33768 while (offset % 4 !== 0) {
33769 offset += 1;
33770 tableFields.push({ name: 'padding', type: 'BYTE', value: 0 });
33771 }
33772
33773 for (var i = 0; i < tables.length; i += 1) {
33774 var t = tables[i];
33775 check.argument(
33776 t.tableName.length === 4,
33777 'Table name' + t.tableName + ' is invalid.'
33778 );
33779 var tableLength = t.sizeOf();
33780 var tableRecord = makeTableRecord(
33781 t.tableName,
33782 computeCheckSum(t.encode()),
33783 offset,
33784 tableLength
33785 );
33786 recordFields.push({
33787 name: tableRecord.tag + ' Table Record',
33788 type: 'RECORD',
33789 value: tableRecord
33790 });
33791 tableFields.push({
33792 name: t.tableName + ' table',
33793 type: 'RECORD',
33794 value: t
33795 });
33796 offset += tableLength;
33797 check.argument(
33798 !isNaN(offset),
33799 'Something went wrong calculating the offset.'
33800 );
33801 while (offset % 4 !== 0) {
33802 offset += 1;
33803 tableFields.push({ name: 'padding', type: 'BYTE', value: 0 });
33804 }
33805 }
33806
33807 // Table records need to be sorted alphabetically.
33808 recordFields.sort(function(r1, r2) {
33809 if (r1.value.tag > r2.value.tag) {
33810 return 1;
33811 } else {
33812 return -1;
33813 }
33814 });
33815
33816 sfnt.fields = sfnt.fields.concat(recordFields);
33817 sfnt.fields = sfnt.fields.concat(tableFields);
33818 return sfnt;
33819 }
33820
33821 // Get the metrics for a character. If the string has more than one character
33822 // this function returns metrics for the first available character.
33823 // You can provide optional fallback metrics if no characters are available.
33824 function metricsForChar(font, chars, notFoundMetrics) {
33825 for (var i = 0; i < chars.length; i += 1) {
33826 var glyphIndex = font.charToGlyphIndex(chars[i]);
33827 if (glyphIndex > 0) {
33828 var glyph = font.glyphs.get(glyphIndex);
33829 return glyph.getMetrics();
33830 }
33831 }
33832
33833 return notFoundMetrics;
33834 }
33835
33836 function average(vs) {
33837 var sum = 0;
33838 for (var i = 0; i < vs.length; i += 1) {
33839 sum += vs[i];
33840 }
33841
33842 return sum / vs.length;
33843 }
33844
33845 // Convert the font object to a SFNT data structure.
33846 // This structure contains all the necessary tables and metadata to create a binary OTF file.
33847 function fontToSfntTable(font) {
33848 var xMins = [];
33849 var yMins = [];
33850 var xMaxs = [];
33851 var yMaxs = [];
33852 var advanceWidths = [];
33853 var leftSideBearings = [];
33854 var rightSideBearings = [];
33855 var firstCharIndex;
33856 var lastCharIndex = 0;
33857 var ulUnicodeRange1 = 0;
33858 var ulUnicodeRange2 = 0;
33859 var ulUnicodeRange3 = 0;
33860 var ulUnicodeRange4 = 0;
33861
33862 for (var i = 0; i < font.glyphs.length; i += 1) {
33863 var glyph = font.glyphs.get(i);
33864 var unicode = glyph.unicode | 0;
33865
33866 if (isNaN(glyph.advanceWidth)) {
33867 throw new Error(
33868 'Glyph ' + glyph.name + ' (' + i + '): advanceWidth is not a number.'
33869 );
33870 }
33871
33872 if (firstCharIndex > unicode || firstCharIndex === undefined) {
33873 // ignore .notdef char
33874 if (unicode > 0) {
33875 firstCharIndex = unicode;
33876 }
33877 }
33878
33879 if (lastCharIndex < unicode) {
33880 lastCharIndex = unicode;
33881 }
33882
33883 var position = os2.getUnicodeRange(unicode);
33884 if (position < 32) {
33885 ulUnicodeRange1 |= 1 << position;
33886 } else if (position < 64) {
33887 ulUnicodeRange2 |= 1 << (position - 32);
33888 } else if (position < 96) {
33889 ulUnicodeRange3 |= 1 << (position - 64);
33890 } else if (position < 123) {
33891 ulUnicodeRange4 |= 1 << (position - 96);
33892 } else {
33893 throw new Error(
33894 'Unicode ranges bits > 123 are reserved for internal usage'
33895 );
33896 }
33897 // Skip non-important characters.
33898 if (glyph.name === '.notdef') {
33899 continue;
33900 }
33901 var metrics = glyph.getMetrics();
33902 xMins.push(metrics.xMin);
33903 yMins.push(metrics.yMin);
33904 xMaxs.push(metrics.xMax);
33905 yMaxs.push(metrics.yMax);
33906 leftSideBearings.push(metrics.leftSideBearing);
33907 rightSideBearings.push(metrics.rightSideBearing);
33908 advanceWidths.push(glyph.advanceWidth);
33909 }
33910
33911 var globals = {
33912 xMin: Math.min.apply(null, xMins),
33913 yMin: Math.min.apply(null, yMins),
33914 xMax: Math.max.apply(null, xMaxs),
33915 yMax: Math.max.apply(null, yMaxs),
33916 advanceWidthMax: Math.max.apply(null, advanceWidths),
33917 advanceWidthAvg: average(advanceWidths),
33918 minLeftSideBearing: Math.min.apply(null, leftSideBearings),
33919 maxLeftSideBearing: Math.max.apply(null, leftSideBearings),
33920 minRightSideBearing: Math.min.apply(null, rightSideBearings)
33921 };
33922 globals.ascender = font.ascender;
33923 globals.descender = font.descender;
33924
33925 var headTable = head.make({
33926 flags: 3, // 00000011 (baseline for font at y=0; left sidebearing point at x=0)
33927 unitsPerEm: font.unitsPerEm,
33928 xMin: globals.xMin,
33929 yMin: globals.yMin,
33930 xMax: globals.xMax,
33931 yMax: globals.yMax,
33932 lowestRecPPEM: 3,
33933 createdTimestamp: font.createdTimestamp
33934 });
33935
33936 var hheaTable = hhea.make({
33937 ascender: globals.ascender,
33938 descender: globals.descender,
33939 advanceWidthMax: globals.advanceWidthMax,
33940 minLeftSideBearing: globals.minLeftSideBearing,
33941 minRightSideBearing: globals.minRightSideBearing,
33942 xMaxExtent: globals.maxLeftSideBearing + (globals.xMax - globals.xMin),
33943 numberOfHMetrics: font.glyphs.length
33944 });
33945
33946 var maxpTable = maxp.make(font.glyphs.length);
33947
33948 var os2Table = os2.make({
33949 xAvgCharWidth: Math.round(globals.advanceWidthAvg),
33950 usWeightClass: font.tables.os2.usWeightClass,
33951 usWidthClass: font.tables.os2.usWidthClass,
33952 usFirstCharIndex: firstCharIndex,
33953 usLastCharIndex: lastCharIndex,
33954 ulUnicodeRange1: ulUnicodeRange1,
33955 ulUnicodeRange2: ulUnicodeRange2,
33956 ulUnicodeRange3: ulUnicodeRange3,
33957 ulUnicodeRange4: ulUnicodeRange4,
33958 fsSelection: font.tables.os2.fsSelection, // REGULAR
33959 // See http://typophile.com/node/13081 for more info on vertical metrics.
33960 // We get metrics for typical characters (such as "x" for xHeight).
33961 // We provide some fallback characters if characters are unavailable: their
33962 // ordering was chosen experimentally.
33963 sTypoAscender: globals.ascender,
33964 sTypoDescender: globals.descender,
33965 sTypoLineGap: 0,
33966 usWinAscent: globals.yMax,
33967 usWinDescent: Math.abs(globals.yMin),
33968 ulCodePageRange1: 1, // FIXME: hard-code Latin 1 support for now
33969 sxHeight: metricsForChar(font, 'xyvw', {
33970 yMax: Math.round(globals.ascender / 2)
33971 }).yMax,
33972 sCapHeight: metricsForChar(font, 'HIKLEFJMNTZBDPRAGOQSUVWXY', globals)
33973 .yMax,
33974 usDefaultChar: font.hasChar(' ') ? 32 : 0, // Use space as the default character, if available.
33975 usBreakChar: font.hasChar(' ') ? 32 : 0 // Use space as the break character, if available.
33976 });
33977
33978 var hmtxTable = hmtx.make(font.glyphs);
33979 var cmapTable = cmap.make(font.glyphs);
33980
33981 var englishFamilyName = font.getEnglishName('fontFamily');
33982 var englishStyleName = font.getEnglishName('fontSubfamily');
33983 var englishFullName = englishFamilyName + ' ' + englishStyleName;
33984 var postScriptName = font.getEnglishName('postScriptName');
33985 if (!postScriptName) {
33986 postScriptName =
33987 englishFamilyName.replace(/\s/g, '') + '-' + englishStyleName;
33988 }
33989
33990 var names = {};
33991 for (var n in font.names) {
33992 names[n] = font.names[n];
33993 }
33994
33995 if (!names.uniqueID) {
33996 names.uniqueID = {
33997 en: font.getEnglishName('manufacturer') + ':' + englishFullName
33998 };
33999 }
34000
34001 if (!names.postScriptName) {
34002 names.postScriptName = { en: postScriptName };
34003 }
34004
34005 if (!names.preferredFamily) {
34006 names.preferredFamily = font.names.fontFamily;
34007 }
34008
34009 if (!names.preferredSubfamily) {
34010 names.preferredSubfamily = font.names.fontSubfamily;
34011 }
34012
34013 var languageTags = [];
34014 var nameTable = _name.make(names, languageTags);
34015 var ltagTable =
34016 languageTags.length > 0 ? ltag.make(languageTags) : undefined;
34017
34018 var postTable = post.make();
34019 var cffTable = cff.make(font.glyphs, {
34020 version: font.getEnglishName('version'),
34021 fullName: englishFullName,
34022 familyName: englishFamilyName,
34023 weightName: englishStyleName,
34024 postScriptName: postScriptName,
34025 unitsPerEm: font.unitsPerEm,
34026 fontBBox: [0, globals.yMin, globals.ascender, globals.advanceWidthMax]
34027 });
34028
34029 var metaTable =
34030 font.metas && Object.keys(font.metas).length > 0
34031 ? meta.make(font.metas)
34032 : undefined;
34033
34034 // The order does not matter because makeSfntTable() will sort them.
34035 var tables = [
34036 headTable,
34037 hheaTable,
34038 maxpTable,
34039 os2Table,
34040 nameTable,
34041 cmapTable,
34042 postTable,
34043 cffTable,
34044 hmtxTable
34045 ];
34046 if (ltagTable) {
34047 tables.push(ltagTable);
34048 }
34049 // Optional tables
34050 if (font.tables.gsub) {
34051 tables.push(gsub.make(font.tables.gsub));
34052 }
34053 if (metaTable) {
34054 tables.push(metaTable);
34055 }
34056
34057 var sfntTable = makeSfntTable(tables);
34058
34059 // Compute the font's checkSum and store it in head.checkSumAdjustment.
34060 var bytes = sfntTable.encode();
34061 var checkSum = computeCheckSum(bytes);
34062 var tableFields = sfntTable.fields;
34063 var checkSumAdjusted = false;
34064 for (var i$1 = 0; i$1 < tableFields.length; i$1 += 1) {
34065 if (tableFields[i$1].name === 'head table') {
34066 tableFields[i$1].value.checkSumAdjustment = 0xb1b0afba - checkSum;
34067 checkSumAdjusted = true;
34068 break;
34069 }
34070 }
34071
34072 if (!checkSumAdjusted) {
34073 throw new Error('Could not find head table with checkSum to adjust.');
34074 }
34075
34076 return sfntTable;
34077 }
34078
34079 var sfnt = {
34080 make: makeSfntTable,
34081 fontToTable: fontToSfntTable,
34082 computeCheckSum: computeCheckSum
34083 };
34084
34085 // The Layout object is the prototype of Substitution objects, and provides
34086
34087 function searchTag(arr, tag) {
34088 /* jshint bitwise: false */
34089 var imin = 0;
34090 var imax = arr.length - 1;
34091 while (imin <= imax) {
34092 var imid = (imin + imax) >>> 1;
34093 var val = arr[imid].tag;
34094 if (val === tag) {
34095 return imid;
34096 } else if (val < tag) {
34097 imin = imid + 1;
34098 } else {
34099 imax = imid - 1;
34100 }
34101 }
34102 // Not found: return -1-insertion point
34103 return -imin - 1;
34104 }
34105
34106 function binSearch(arr, value) {
34107 /* jshint bitwise: false */
34108 var imin = 0;
34109 var imax = arr.length - 1;
34110 while (imin <= imax) {
34111 var imid = (imin + imax) >>> 1;
34112 var val = arr[imid];
34113 if (val === value) {
34114 return imid;
34115 } else if (val < value) {
34116 imin = imid + 1;
34117 } else {
34118 imax = imid - 1;
34119 }
34120 }
34121 // Not found: return -1-insertion point
34122 return -imin - 1;
34123 }
34124
34125 // binary search in a list of ranges (coverage, class definition)
34126 function searchRange(ranges, value) {
34127 // jshint bitwise: false
34128 var range;
34129 var imin = 0;
34130 var imax = ranges.length - 1;
34131 while (imin <= imax) {
34132 var imid = (imin + imax) >>> 1;
34133 range = ranges[imid];
34134 var start = range.start;
34135 if (start === value) {
34136 return range;
34137 } else if (start < value) {
34138 imin = imid + 1;
34139 } else {
34140 imax = imid - 1;
34141 }
34142 }
34143 if (imin > 0) {
34144 range = ranges[imin - 1];
34145 if (value > range.end) {
34146 return 0;
34147 }
34148 return range;
34149 }
34150 }
34151
34152 /**
34153 * @exports opentype.Layout
34154 * @class
34155 */
34156 function Layout(font, tableName) {
34157 this.font = font;
34158 this.tableName = tableName;
34159 }
34160
34161 Layout.prototype = {
34162 /**
34163 * Binary search an object by "tag" property
34164 * @instance
34165 * @function searchTag
34166 * @memberof opentype.Layout
34167 * @param {Array} arr
34168 * @param {string} tag
34169 * @return {number}
34170 */
34171 searchTag: searchTag,
34172
34173 /**
34174 * Binary search in a list of numbers
34175 * @instance
34176 * @function binSearch
34177 * @memberof opentype.Layout
34178 * @param {Array} arr
34179 * @param {number} value
34180 * @return {number}
34181 */
34182 binSearch: binSearch,
34183
34184 /**
34185 * Get or create the Layout table (GSUB, GPOS etc).
34186 * @param {boolean} create - Whether to create a new one.
34187 * @return {Object} The GSUB or GPOS table.
34188 */
34189 getTable: function(create) {
34190 var layout = this.font.tables[this.tableName];
34191 if (!layout && create) {
34192 layout = this.font.tables[this.tableName] = this.createDefaultTable();
34193 }
34194 return layout;
34195 },
34196
34197 /**
34198 * Returns all scripts in the substitution table.
34199 * @instance
34200 * @return {Array}
34201 */
34202 getScriptNames: function() {
34203 var layout = this.getTable();
34204 if (!layout) {
34205 return [];
34206 }
34207 return layout.scripts.map(function(script) {
34208 return script.tag;
34209 });
34210 },
34211
34212 /**
34213 * Returns the best bet for a script name.
34214 * Returns 'DFLT' if it exists.
34215 * If not, returns 'latn' if it exists.
34216 * If neither exist, returns undefined.
34217 */
34218 getDefaultScriptName: function() {
34219 var layout = this.getTable();
34220 if (!layout) {
34221 return;
34222 }
34223 var hasLatn = false;
34224 for (var i = 0; i < layout.scripts.length; i++) {
34225 var name = layout.scripts[i].tag;
34226 if (name === 'DFLT') {
34227 return name;
34228 }
34229 if (name === 'latn') {
34230 hasLatn = true;
34231 }
34232 }
34233 if (hasLatn) {
34234 return 'latn';
34235 }
34236 },
34237
34238 /**
34239 * Returns all LangSysRecords in the given script.
34240 * @instance
34241 * @param {string} [script='DFLT']
34242 * @param {boolean} create - forces the creation of this script table if it doesn't exist.
34243 * @return {Object} An object with tag and script properties.
34244 */
34245 getScriptTable: function(script, create) {
34246 var layout = this.getTable(create);
34247 if (layout) {
34248 script = script || 'DFLT';
34249 var scripts = layout.scripts;
34250 var pos = searchTag(layout.scripts, script);
34251 if (pos >= 0) {
34252 return scripts[pos].script;
34253 } else if (create) {
34254 var scr = {
34255 tag: script,
34256 script: {
34257 defaultLangSys: {
34258 reserved: 0,
34259 reqFeatureIndex: 0xffff,
34260 featureIndexes: []
34261 },
34262 langSysRecords: []
34263 }
34264 };
34265 scripts.splice(-1 - pos, 0, scr);
34266 return scr.script;
34267 }
34268 }
34269 },
34270
34271 /**
34272 * Returns a language system table
34273 * @instance
34274 * @param {string} [script='DFLT']
34275 * @param {string} [language='dlft']
34276 * @param {boolean} create - forces the creation of this langSysTable if it doesn't exist.
34277 * @return {Object}
34278 */
34279 getLangSysTable: function(script, language, create) {
34280 var scriptTable = this.getScriptTable(script, create);
34281 if (scriptTable) {
34282 if (!language || language === 'dflt' || language === 'DFLT') {
34283 return scriptTable.defaultLangSys;
34284 }
34285 var pos = searchTag(scriptTable.langSysRecords, language);
34286 if (pos >= 0) {
34287 return scriptTable.langSysRecords[pos].langSys;
34288 } else if (create) {
34289 var langSysRecord = {
34290 tag: language,
34291 langSys: {
34292 reserved: 0,
34293 reqFeatureIndex: 0xffff,
34294 featureIndexes: []
34295 }
34296 };
34297 scriptTable.langSysRecords.splice(-1 - pos, 0, langSysRecord);
34298 return langSysRecord.langSys;
34299 }
34300 }
34301 },
34302
34303 /**
34304 * Get a specific feature table.
34305 * @instance
34306 * @param {string} [script='DFLT']
34307 * @param {string} [language='dlft']
34308 * @param {string} feature - One of the codes listed at https://www.microsoft.com/typography/OTSPEC/featurelist.htm
34309 * @param {boolean} create - forces the creation of the feature table if it doesn't exist.
34310 * @return {Object}
34311 */
34312 getFeatureTable: function(script, language, feature, create) {
34313 var langSysTable = this.getLangSysTable(script, language, create);
34314 if (langSysTable) {
34315 var featureRecord;
34316 var featIndexes = langSysTable.featureIndexes;
34317 var allFeatures = this.font.tables[this.tableName].features;
34318 // The FeatureIndex array of indices is in arbitrary order,
34319 // even if allFeatures is sorted alphabetically by feature tag.
34320 for (var i = 0; i < featIndexes.length; i++) {
34321 featureRecord = allFeatures[featIndexes[i]];
34322 if (featureRecord.tag === feature) {
34323 return featureRecord.feature;
34324 }
34325 }
34326 if (create) {
34327 var index = allFeatures.length;
34328 // Automatic ordering of features would require to shift feature indexes in the script list.
34329 check.assert(
34330 index === 0 || feature >= allFeatures[index - 1].tag,
34331 'Features must be added in alphabetical order.'
34332 );
34333 featureRecord = {
34334 tag: feature,
34335 feature: { params: 0, lookupListIndexes: [] }
34336 };
34337 allFeatures.push(featureRecord);
34338 featIndexes.push(index);
34339 return featureRecord.feature;
34340 }
34341 }
34342 },
34343
34344 /**
34345 * Get the lookup tables of a given type for a script/language/feature.
34346 * @instance
34347 * @param {string} [script='DFLT']
34348 * @param {string} [language='dlft']
34349 * @param {string} feature - 4-letter feature code
34350 * @param {number} lookupType - 1 to 9
34351 * @param {boolean} create - forces the creation of the lookup table if it doesn't exist, with no subtables.
34352 * @return {Object[]}
34353 */
34354 getLookupTables: function(script, language, feature, lookupType, create) {
34355 var featureTable = this.getFeatureTable(
34356 script,
34357 language,
34358 feature,
34359 create
34360 );
34361 var tables = [];
34362 if (featureTable) {
34363 var lookupTable;
34364 var lookupListIndexes = featureTable.lookupListIndexes;
34365 var allLookups = this.font.tables[this.tableName].lookups;
34366 // lookupListIndexes are in no particular order, so use naive search.
34367 for (var i = 0; i < lookupListIndexes.length; i++) {
34368 lookupTable = allLookups[lookupListIndexes[i]];
34369 if (lookupTable.lookupType === lookupType) {
34370 tables.push(lookupTable);
34371 }
34372 }
34373 if (tables.length === 0 && create) {
34374 lookupTable = {
34375 lookupType: lookupType,
34376 lookupFlag: 0,
34377 subtables: [],
34378 markFilteringSet: undefined
34379 };
34380 var index = allLookups.length;
34381 allLookups.push(lookupTable);
34382 lookupListIndexes.push(index);
34383 return [lookupTable];
34384 }
34385 }
34386 return tables;
34387 },
34388
34389 /**
34390 * Find a glyph in a class definition table
34391 * https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#class-definition-table
34392 * @param {object} classDefTable - an OpenType Layout class definition table
34393 * @param {number} glyphIndex - the index of the glyph to find
34394 * @returns {number} -1 if not found
34395 */
34396 getGlyphClass: function(classDefTable, glyphIndex) {
34397 switch (classDefTable.format) {
34398 case 1:
34399 if (
34400 classDefTable.startGlyph <= glyphIndex &&
34401 glyphIndex < classDefTable.startGlyph + classDefTable.classes.length
34402 ) {
34403 return classDefTable.classes[glyphIndex - classDefTable.startGlyph];
34404 }
34405 return 0;
34406 case 2:
34407 var range = searchRange(classDefTable.ranges, glyphIndex);
34408 return range ? range.classId : 0;
34409 }
34410 },
34411
34412 /**
34413 * Find a glyph in a coverage table
34414 * https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#coverage-table
34415 * @param {object} coverageTable - an OpenType Layout coverage table
34416 * @param {number} glyphIndex - the index of the glyph to find
34417 * @returns {number} -1 if not found
34418 */
34419 getCoverageIndex: function(coverageTable, glyphIndex) {
34420 switch (coverageTable.format) {
34421 case 1:
34422 var index = binSearch(coverageTable.glyphs, glyphIndex);
34423 return index >= 0 ? index : -1;
34424 case 2:
34425 var range = searchRange(coverageTable.ranges, glyphIndex);
34426 return range ? range.index + glyphIndex - range.start : -1;
34427 }
34428 },
34429
34430 /**
34431 * Returns the list of glyph indexes of a coverage table.
34432 * Format 1: the list is stored raw
34433 * Format 2: compact list as range records.
34434 * @instance
34435 * @param {Object} coverageTable
34436 * @return {Array}
34437 */
34438 expandCoverage: function(coverageTable) {
34439 if (coverageTable.format === 1) {
34440 return coverageTable.glyphs;
34441 } else {
34442 var glyphs = [];
34443 var ranges = coverageTable.ranges;
34444 for (var i = 0; i < ranges.length; i++) {
34445 var range = ranges[i];
34446 var start = range.start;
34447 var end = range.end;
34448 for (var j = start; j <= end; j++) {
34449 glyphs.push(j);
34450 }
34451 }
34452 return glyphs;
34453 }
34454 }
34455 };
34456
34457 // The Position object provides utility methods to manipulate
34458
34459 /**
34460 * @exports opentype.Position
34461 * @class
34462 * @extends opentype.Layout
34463 * @param {opentype.Font}
34464 * @constructor
34465 */
34466 function Position(font) {
34467 Layout.call(this, font, 'gpos');
34468 }
34469
34470 Position.prototype = Layout.prototype;
34471
34472 /**
34473 * Init some data for faster and easier access later.
34474 */
34475 Position.prototype.init = function() {
34476 var script = this.getDefaultScriptName();
34477 this.defaultKerningTables = this.getKerningTables(script);
34478 };
34479
34480 /**
34481 * Find a glyph pair in a list of lookup tables of type 2 and retrieve the xAdvance kerning value.
34482 *
34483 * @param {integer} leftIndex - left glyph index
34484 * @param {integer} rightIndex - right glyph index
34485 * @returns {integer}
34486 */
34487 Position.prototype.getKerningValue = function(
34488 kerningLookups,
34489 leftIndex,
34490 rightIndex
34491 ) {
34492 var this$1 = this;
34493
34494 for (var i = 0; i < kerningLookups.length; i++) {
34495 var subtables = kerningLookups[i].subtables;
34496 for (var j = 0; j < subtables.length; j++) {
34497 var subtable = subtables[j];
34498 var covIndex = this$1.getCoverageIndex(subtable.coverage, leftIndex);
34499 if (covIndex < 0) {
34500 continue;
34501 }
34502 switch (subtable.posFormat) {
34503 case 1:
34504 // Search Pair Adjustment Positioning Format 1
34505 var pairSet = subtable.pairSets[covIndex];
34506 for (var k = 0; k < pairSet.length; k++) {
34507 var pair = pairSet[k];
34508 if (pair.secondGlyph === rightIndex) {
34509 return (pair.value1 && pair.value1.xAdvance) || 0;
34510 }
34511 }
34512 break; // left glyph found, not right glyph - try next subtable
34513 case 2:
34514 // Search Pair Adjustment Positioning Format 2
34515 var class1 = this$1.getGlyphClass(subtable.classDef1, leftIndex);
34516 var class2 = this$1.getGlyphClass(subtable.classDef2, rightIndex);
34517 var pair$1 = subtable.classRecords[class1][class2];
34518 return (pair$1.value1 && pair$1.value1.xAdvance) || 0;
34519 }
34520 }
34521 }
34522 return 0;
34523 };
34524
34525 /**
34526 * List all kerning lookup tables.
34527 *
34528 * @param {string} [script='DFLT'] - use font.position.getDefaultScriptName() for a better default value
34529 * @param {string} [language='dflt']
34530 * @return {object[]} The list of kerning lookup tables (may be empty), or undefined if there is no GPOS table (and we should use the kern table)
34531 */
34532 Position.prototype.getKerningTables = function(script, language) {
34533 if (this.font.tables.gpos) {
34534 return this.getLookupTables(script, language, 'kern', 2);
34535 }
34536 };
34537
34538 // The Substitution object provides utility methods to manipulate
34539
34540 /**
34541 * @exports opentype.Substitution
34542 * @class
34543 * @extends opentype.Layout
34544 * @param {opentype.Font}
34545 * @constructor
34546 */
34547 function Substitution(font) {
34548 Layout.call(this, font, 'gsub');
34549 }
34550
34551 // Check if 2 arrays of primitives are equal.
34552 function arraysEqual(ar1, ar2) {
34553 var n = ar1.length;
34554 if (n !== ar2.length) {
34555 return false;
34556 }
34557 for (var i = 0; i < n; i++) {
34558 if (ar1[i] !== ar2[i]) {
34559 return false;
34560 }
34561 }
34562 return true;
34563 }
34564
34565 // Find the first subtable of a lookup table in a particular format.
34566 function getSubstFormat(lookupTable, format, defaultSubtable) {
34567 var subtables = lookupTable.subtables;
34568 for (var i = 0; i < subtables.length; i++) {
34569 var subtable = subtables[i];
34570 if (subtable.substFormat === format) {
34571 return subtable;
34572 }
34573 }
34574 if (defaultSubtable) {
34575 subtables.push(defaultSubtable);
34576 return defaultSubtable;
34577 }
34578 return undefined;
34579 }
34580
34581 Substitution.prototype = Layout.prototype;
34582
34583 /**
34584 * Create a default GSUB table.
34585 * @return {Object} gsub - The GSUB table.
34586 */
34587 Substitution.prototype.createDefaultTable = function() {
34588 // Generate a default empty GSUB table with just a DFLT script and dflt lang sys.
34589 return {
34590 version: 1,
34591 scripts: [
34592 {
34593 tag: 'DFLT',
34594 script: {
34595 defaultLangSys: {
34596 reserved: 0,
34597 reqFeatureIndex: 0xffff,
34598 featureIndexes: []
34599 },
34600 langSysRecords: []
34601 }
34602 }
34603 ],
34604 features: [],
34605 lookups: []
34606 };
34607 };
34608
34609 /**
34610 * List all single substitutions (lookup type 1) for a given script, language, and feature.
34611 * @param {string} [script='DFLT']
34612 * @param {string} [language='dflt']
34613 * @param {string} feature - 4-character feature name ('aalt', 'salt', 'ss01'...)
34614 * @return {Array} substitutions - The list of substitutions.
34615 */
34616 Substitution.prototype.getSingle = function(feature, script, language) {
34617 var this$1 = this;
34618
34619 var substitutions = [];
34620 var lookupTables = this.getLookupTables(script, language, feature, 1);
34621 for (var idx = 0; idx < lookupTables.length; idx++) {
34622 var subtables = lookupTables[idx].subtables;
34623 for (var i = 0; i < subtables.length; i++) {
34624 var subtable = subtables[i];
34625 var glyphs = this$1.expandCoverage(subtable.coverage);
34626 var j = void 0;
34627 if (subtable.substFormat === 1) {
34628 var delta = subtable.deltaGlyphId;
34629 for (j = 0; j < glyphs.length; j++) {
34630 var glyph = glyphs[j];
34631 substitutions.push({ sub: glyph, by: glyph + delta });
34632 }
34633 } else {
34634 var substitute = subtable.substitute;
34635 for (j = 0; j < glyphs.length; j++) {
34636 substitutions.push({ sub: glyphs[j], by: substitute[j] });
34637 }
34638 }
34639 }
34640 }
34641 return substitutions;
34642 };
34643
34644 /**
34645 * List all alternates (lookup type 3) for a given script, language, and feature.
34646 * @param {string} [script='DFLT']
34647 * @param {string} [language='dflt']
34648 * @param {string} feature - 4-character feature name ('aalt', 'salt'...)
34649 * @return {Array} alternates - The list of alternates
34650 */
34651 Substitution.prototype.getAlternates = function(feature, script, language) {
34652 var this$1 = this;
34653
34654 var alternates = [];
34655 var lookupTables = this.getLookupTables(script, language, feature, 3);
34656 for (var idx = 0; idx < lookupTables.length; idx++) {
34657 var subtables = lookupTables[idx].subtables;
34658 for (var i = 0; i < subtables.length; i++) {
34659 var subtable = subtables[i];
34660 var glyphs = this$1.expandCoverage(subtable.coverage);
34661 var alternateSets = subtable.alternateSets;
34662 for (var j = 0; j < glyphs.length; j++) {
34663 alternates.push({ sub: glyphs[j], by: alternateSets[j] });
34664 }
34665 }
34666 }
34667 return alternates;
34668 };
34669
34670 /**
34671 * List all ligatures (lookup type 4) for a given script, language, and feature.
34672 * The result is an array of ligature objects like { sub: [ids], by: id }
34673 * @param {string} feature - 4-letter feature name ('liga', 'rlig', 'dlig'...)
34674 * @param {string} [script='DFLT']
34675 * @param {string} [language='dflt']
34676 * @return {Array} ligatures - The list of ligatures.
34677 */
34678 Substitution.prototype.getLigatures = function(feature, script, language) {
34679 var this$1 = this;
34680
34681 var ligatures = [];
34682 var lookupTables = this.getLookupTables(script, language, feature, 4);
34683 for (var idx = 0; idx < lookupTables.length; idx++) {
34684 var subtables = lookupTables[idx].subtables;
34685 for (var i = 0; i < subtables.length; i++) {
34686 var subtable = subtables[i];
34687 var glyphs = this$1.expandCoverage(subtable.coverage);
34688 var ligatureSets = subtable.ligatureSets;
34689 for (var j = 0; j < glyphs.length; j++) {
34690 var startGlyph = glyphs[j];
34691 var ligSet = ligatureSets[j];
34692 for (var k = 0; k < ligSet.length; k++) {
34693 var lig = ligSet[k];
34694 ligatures.push({
34695 sub: [startGlyph].concat(lig.components),
34696 by: lig.ligGlyph
34697 });
34698 }
34699 }
34700 }
34701 }
34702 return ligatures;
34703 };
34704
34705 /**
34706 * Add or modify a single substitution (lookup type 1)
34707 * Format 2, more flexible, is always used.
34708 * @param {string} feature - 4-letter feature name ('liga', 'rlig', 'dlig'...)
34709 * @param {Object} substitution - { sub: id, delta: number } for format 1 or { sub: id, by: id } for format 2.
34710 * @param {string} [script='DFLT']
34711 * @param {string} [language='dflt']
34712 */
34713 Substitution.prototype.addSingle = function(
34714 feature,
34715 substitution,
34716 script,
34717 language
34718 ) {
34719 var lookupTable = this.getLookupTables(
34720 script,
34721 language,
34722 feature,
34723 1,
34724 true
34725 )[0];
34726 var subtable = getSubstFormat(lookupTable, 2, {
34727 // lookup type 1 subtable, format 2, coverage format 1
34728 substFormat: 2,
34729 coverage: { format: 1, glyphs: [] },
34730 substitute: []
34731 });
34732 check.assert(
34733 subtable.coverage.format === 1,
34734 'Ligature: unable to modify coverage table format ' +
34735 subtable.coverage.format
34736 );
34737 var coverageGlyph = substitution.sub;
34738 var pos = this.binSearch(subtable.coverage.glyphs, coverageGlyph);
34739 if (pos < 0) {
34740 pos = -1 - pos;
34741 subtable.coverage.glyphs.splice(pos, 0, coverageGlyph);
34742 subtable.substitute.splice(pos, 0, 0);
34743 }
34744 subtable.substitute[pos] = substitution.by;
34745 };
34746
34747 /**
34748 * Add or modify an alternate substitution (lookup type 1)
34749 * @param {string} feature - 4-letter feature name ('liga', 'rlig', 'dlig'...)
34750 * @param {Object} substitution - { sub: id, by: [ids] }
34751 * @param {string} [script='DFLT']
34752 * @param {string} [language='dflt']
34753 */
34754 Substitution.prototype.addAlternate = function(
34755 feature,
34756 substitution,
34757 script,
34758 language
34759 ) {
34760 var lookupTable = this.getLookupTables(
34761 script,
34762 language,
34763 feature,
34764 3,
34765 true
34766 )[0];
34767 var subtable = getSubstFormat(lookupTable, 1, {
34768 // lookup type 3 subtable, format 1, coverage format 1
34769 substFormat: 1,
34770 coverage: { format: 1, glyphs: [] },
34771 alternateSets: []
34772 });
34773 check.assert(
34774 subtable.coverage.format === 1,
34775 'Ligature: unable to modify coverage table format ' +
34776 subtable.coverage.format
34777 );
34778 var coverageGlyph = substitution.sub;
34779 var pos = this.binSearch(subtable.coverage.glyphs, coverageGlyph);
34780 if (pos < 0) {
34781 pos = -1 - pos;
34782 subtable.coverage.glyphs.splice(pos, 0, coverageGlyph);
34783 subtable.alternateSets.splice(pos, 0, 0);
34784 }
34785 subtable.alternateSets[pos] = substitution.by;
34786 };
34787
34788 /**
34789 * Add a ligature (lookup type 4)
34790 * Ligatures with more components must be stored ahead of those with fewer components in order to be found
34791 * @param {string} feature - 4-letter feature name ('liga', 'rlig', 'dlig'...)
34792 * @param {Object} ligature - { sub: [ids], by: id }
34793 * @param {string} [script='DFLT']
34794 * @param {string} [language='dflt']
34795 */
34796 Substitution.prototype.addLigature = function(
34797 feature,
34798 ligature,
34799 script,
34800 language
34801 ) {
34802 var lookupTable = this.getLookupTables(
34803 script,
34804 language,
34805 feature,
34806 4,
34807 true
34808 )[0];
34809 var subtable = lookupTable.subtables[0];
34810 if (!subtable) {
34811 subtable = {
34812 // lookup type 4 subtable, format 1, coverage format 1
34813 substFormat: 1,
34814 coverage: { format: 1, glyphs: [] },
34815 ligatureSets: []
34816 };
34817 lookupTable.subtables[0] = subtable;
34818 }
34819 check.assert(
34820 subtable.coverage.format === 1,
34821 'Ligature: unable to modify coverage table format ' +
34822 subtable.coverage.format
34823 );
34824 var coverageGlyph = ligature.sub[0];
34825 var ligComponents = ligature.sub.slice(1);
34826 var ligatureTable = {
34827 ligGlyph: ligature.by,
34828 components: ligComponents
34829 };
34830 var pos = this.binSearch(subtable.coverage.glyphs, coverageGlyph);
34831 if (pos >= 0) {
34832 // ligatureSet already exists
34833 var ligatureSet = subtable.ligatureSets[pos];
34834 for (var i = 0; i < ligatureSet.length; i++) {
34835 // If ligature already exists, return.
34836 if (arraysEqual(ligatureSet[i].components, ligComponents)) {
34837 return;
34838 }
34839 }
34840 // ligature does not exist: add it.
34841 ligatureSet.push(ligatureTable);
34842 } else {
34843 // Create a new ligatureSet and add coverage for the first glyph.
34844 pos = -1 - pos;
34845 subtable.coverage.glyphs.splice(pos, 0, coverageGlyph);
34846 subtable.ligatureSets.splice(pos, 0, [ligatureTable]);
34847 }
34848 };
34849
34850 /**
34851 * List all feature data for a given script and language.
34852 * @param {string} feature - 4-letter feature name
34853 * @param {string} [script='DFLT']
34854 * @param {string} [language='dflt']
34855 * @return {Array} substitutions - The list of substitutions.
34856 */
34857 Substitution.prototype.getFeature = function(feature, script, language) {
34858 if (/ss\d\d/.test(feature)) {
34859 // ss01 - ss20
34860 return this.getSingle(feature, script, language);
34861 }
34862 switch (feature) {
34863 case 'aalt':
34864 case 'salt':
34865 return this.getSingle(feature, script, language).concat(
34866 this.getAlternates(feature, script, language)
34867 );
34868 case 'dlig':
34869 case 'liga':
34870 case 'rlig':
34871 return this.getLigatures(feature, script, language);
34872 }
34873 return undefined;
34874 };
34875
34876 /**
34877 * Add a substitution to a feature for a given script and language.
34878 * @param {string} feature - 4-letter feature name
34879 * @param {Object} sub - the substitution to add (an object like { sub: id or [ids], by: id or [ids] })
34880 * @param {string} [script='DFLT']
34881 * @param {string} [language='dflt']
34882 */
34883 Substitution.prototype.add = function(feature, sub, script, language) {
34884 if (/ss\d\d/.test(feature)) {
34885 // ss01 - ss20
34886 return this.addSingle(feature, sub, script, language);
34887 }
34888 switch (feature) {
34889 case 'aalt':
34890 case 'salt':
34891 if (typeof sub.by === 'number') {
34892 return this.addSingle(feature, sub, script, language);
34893 }
34894 return this.addAlternate(feature, sub, script, language);
34895 case 'dlig':
34896 case 'liga':
34897 case 'rlig':
34898 return this.addLigature(feature, sub, script, language);
34899 }
34900 return undefined;
34901 };
34902
34903 function isBrowser() {
34904 return typeof window !== 'undefined';
34905 }
34906
34907 function nodeBufferToArrayBuffer(buffer) {
34908 var ab = new ArrayBuffer(buffer.length);
34909 var view = new Uint8Array(ab);
34910 for (var i = 0; i < buffer.length; ++i) {
34911 view[i] = buffer[i];
34912 }
34913
34914 return ab;
34915 }
34916
34917 function arrayBufferToNodeBuffer(ab) {
34918 var buffer = new Buffer(ab.byteLength);
34919 var view = new Uint8Array(ab);
34920 for (var i = 0; i < buffer.length; ++i) {
34921 buffer[i] = view[i];
34922 }
34923
34924 return buffer;
34925 }
34926
34927 function checkArgument(expression, message) {
34928 if (!expression) {
34929 throw message;
34930 }
34931 }
34932
34933 // The `glyf` table describes the glyphs in TrueType outline format.
34934
34935 // Parse the coordinate data for a glyph.
34936 function parseGlyphCoordinate(
34937 p,
34938 flag,
34939 previousValue,
34940 shortVectorBitMask,
34941 sameBitMask
34942 ) {
34943 var v;
34944 if ((flag & shortVectorBitMask) > 0) {
34945 // The coordinate is 1 byte long.
34946 v = p.parseByte();
34947 // The `same` bit is re-used for short values to signify the sign of the value.
34948 if ((flag & sameBitMask) === 0) {
34949 v = -v;
34950 }
34951
34952 v = previousValue + v;
34953 } else {
34954 // The coordinate is 2 bytes long.
34955 // If the `same` bit is set, the coordinate is the same as the previous coordinate.
34956 if ((flag & sameBitMask) > 0) {
34957 v = previousValue;
34958 } else {
34959 // Parse the coordinate as a signed 16-bit delta value.
34960 v = previousValue + p.parseShort();
34961 }
34962 }
34963
34964 return v;
34965 }
34966
34967 // Parse a TrueType glyph.
34968 function parseGlyph(glyph, data, start) {
34969 var p = new parse.Parser(data, start);
34970 glyph.numberOfContours = p.parseShort();
34971 glyph._xMin = p.parseShort();
34972 glyph._yMin = p.parseShort();
34973 glyph._xMax = p.parseShort();
34974 glyph._yMax = p.parseShort();
34975 var flags;
34976 var flag;
34977
34978 if (glyph.numberOfContours > 0) {
34979 // This glyph is not a composite.
34980 var endPointIndices = (glyph.endPointIndices = []);
34981 for (var i = 0; i < glyph.numberOfContours; i += 1) {
34982 endPointIndices.push(p.parseUShort());
34983 }
34984
34985 glyph.instructionLength = p.parseUShort();
34986 glyph.instructions = [];
34987 for (var i$1 = 0; i$1 < glyph.instructionLength; i$1 += 1) {
34988 glyph.instructions.push(p.parseByte());
34989 }
34990
34991 var numberOfCoordinates = endPointIndices[endPointIndices.length - 1] + 1;
34992 flags = [];
34993 for (var i$2 = 0; i$2 < numberOfCoordinates; i$2 += 1) {
34994 flag = p.parseByte();
34995 flags.push(flag);
34996 // If bit 3 is set, we repeat this flag n times, where n is the next byte.
34997 if ((flag & 8) > 0) {
34998 var repeatCount = p.parseByte();
34999 for (var j = 0; j < repeatCount; j += 1) {
35000 flags.push(flag);
35001 i$2 += 1;
35002 }
35003 }
35004 }
35005
35006 check.argument(flags.length === numberOfCoordinates, 'Bad flags.');
35007
35008 if (endPointIndices.length > 0) {
35009 var points = [];
35010 var point;
35011 // X/Y coordinates are relative to the previous point, except for the first point which is relative to 0,0.
35012 if (numberOfCoordinates > 0) {
35013 for (var i$3 = 0; i$3 < numberOfCoordinates; i$3 += 1) {
35014 flag = flags[i$3];
35015 point = {};
35016 point.onCurve = !!(flag & 1);
35017 point.lastPointOfContour = endPointIndices.indexOf(i$3) >= 0;
35018 points.push(point);
35019 }
35020
35021 var px = 0;
35022 for (var i$4 = 0; i$4 < numberOfCoordinates; i$4 += 1) {
35023 flag = flags[i$4];
35024 point = points[i$4];
35025 point.x = parseGlyphCoordinate(p, flag, px, 2, 16);
35026 px = point.x;
35027 }
35028
35029 var py = 0;
35030 for (var i$5 = 0; i$5 < numberOfCoordinates; i$5 += 1) {
35031 flag = flags[i$5];
35032 point = points[i$5];
35033 point.y = parseGlyphCoordinate(p, flag, py, 4, 32);
35034 py = point.y;
35035 }
35036 }
35037
35038 glyph.points = points;
35039 } else {
35040 glyph.points = [];
35041 }
35042 } else if (glyph.numberOfContours === 0) {
35043 glyph.points = [];
35044 } else {
35045 glyph.isComposite = true;
35046 glyph.points = [];
35047 glyph.components = [];
35048 var moreComponents = true;
35049 while (moreComponents) {
35050 flags = p.parseUShort();
35051 var component = {
35052 glyphIndex: p.parseUShort(),
35053 xScale: 1,
35054 scale01: 0,
35055 scale10: 0,
35056 yScale: 1,
35057 dx: 0,
35058 dy: 0
35059 };
35060 if ((flags & 1) > 0) {
35061 // The arguments are words
35062 if ((flags & 2) > 0) {
35063 // values are offset
35064 component.dx = p.parseShort();
35065 component.dy = p.parseShort();
35066 } else {
35067 // values are matched points
35068 component.matchedPoints = [p.parseUShort(), p.parseUShort()];
35069 }
35070 } else {
35071 // The arguments are bytes
35072 if ((flags & 2) > 0) {
35073 // values are offset
35074 component.dx = p.parseChar();
35075 component.dy = p.parseChar();
35076 } else {
35077 // values are matched points
35078 component.matchedPoints = [p.parseByte(), p.parseByte()];
35079 }
35080 }
35081
35082 if ((flags & 8) > 0) {
35083 // We have a scale
35084 component.xScale = component.yScale = p.parseF2Dot14();
35085 } else if ((flags & 64) > 0) {
35086 // We have an X / Y scale
35087 component.xScale = p.parseF2Dot14();
35088 component.yScale = p.parseF2Dot14();
35089 } else if ((flags & 128) > 0) {
35090 // We have a 2x2 transformation
35091 component.xScale = p.parseF2Dot14();
35092 component.scale01 = p.parseF2Dot14();
35093 component.scale10 = p.parseF2Dot14();
35094 component.yScale = p.parseF2Dot14();
35095 }
35096
35097 glyph.components.push(component);
35098 moreComponents = !!(flags & 32);
35099 }
35100 if (flags & 0x100) {
35101 // We have instructions
35102 glyph.instructionLength = p.parseUShort();
35103 glyph.instructions = [];
35104 for (var i$6 = 0; i$6 < glyph.instructionLength; i$6 += 1) {
35105 glyph.instructions.push(p.parseByte());
35106 }
35107 }
35108 }
35109 }
35110
35111 // Transform an array of points and return a new array.
35112 function transformPoints(points, transform) {
35113 var newPoints = [];
35114 for (var i = 0; i < points.length; i += 1) {
35115 var pt = points[i];
35116 var newPt = {
35117 x: transform.xScale * pt.x + transform.scale01 * pt.y + transform.dx,
35118 y: transform.scale10 * pt.x + transform.yScale * pt.y + transform.dy,
35119 onCurve: pt.onCurve,
35120 lastPointOfContour: pt.lastPointOfContour
35121 };
35122 newPoints.push(newPt);
35123 }
35124
35125 return newPoints;
35126 }
35127
35128 function getContours(points) {
35129 var contours = [];
35130 var currentContour = [];
35131 for (var i = 0; i < points.length; i += 1) {
35132 var pt = points[i];
35133 currentContour.push(pt);
35134 if (pt.lastPointOfContour) {
35135 contours.push(currentContour);
35136 currentContour = [];
35137 }
35138 }
35139
35140 check.argument(
35141 currentContour.length === 0,
35142 'There are still points left in the current contour.'
35143 );
35144 return contours;
35145 }
35146
35147 // Convert the TrueType glyph outline to a Path.
35148 function getPath(points) {
35149 var p = new Path();
35150 if (!points) {
35151 return p;
35152 }
35153
35154 var contours = getContours(points);
35155
35156 for (var contourIndex = 0; contourIndex < contours.length; ++contourIndex) {
35157 var contour = contours[contourIndex];
35158
35159 var prev = null;
35160 var curr = contour[contour.length - 1];
35161 var next = contour[0];
35162
35163 if (curr.onCurve) {
35164 p.moveTo(curr.x, curr.y);
35165 } else {
35166 if (next.onCurve) {
35167 p.moveTo(next.x, next.y);
35168 } else {
35169 // If both first and last points are off-curve, start at their middle.
35170 var start = {
35171 x: (curr.x + next.x) * 0.5,
35172 y: (curr.y + next.y) * 0.5
35173 };
35174 p.moveTo(start.x, start.y);
35175 }
35176 }
35177
35178 for (var i = 0; i < contour.length; ++i) {
35179 prev = curr;
35180 curr = next;
35181 next = contour[(i + 1) % contour.length];
35182
35183 if (curr.onCurve) {
35184 // This is a straight line.
35185 p.lineTo(curr.x, curr.y);
35186 } else {
35187 var prev2 = prev;
35188 var next2 = next;
35189
35190 if (!prev.onCurve) {
35191 prev2 = { x: (curr.x + prev.x) * 0.5, y: (curr.y + prev.y) * 0.5 };
35192 }
35193
35194 if (!next.onCurve) {
35195 next2 = { x: (curr.x + next.x) * 0.5, y: (curr.y + next.y) * 0.5 };
35196 }
35197
35198 p.quadraticCurveTo(curr.x, curr.y, next2.x, next2.y);
35199 }
35200 }
35201
35202 p.closePath();
35203 }
35204 return p;
35205 }
35206
35207 function buildPath(glyphs, glyph) {
35208 if (glyph.isComposite) {
35209 for (var j = 0; j < glyph.components.length; j += 1) {
35210 var component = glyph.components[j];
35211 var componentGlyph = glyphs.get(component.glyphIndex);
35212 // Force the ttfGlyphLoader to parse the glyph.
35213 componentGlyph.getPath();
35214 if (componentGlyph.points) {
35215 var transformedPoints = void 0;
35216 if (component.matchedPoints === undefined) {
35217 // component positioned by offset
35218 transformedPoints = transformPoints(
35219 componentGlyph.points,
35220 component
35221 );
35222 } else {
35223 // component positioned by matched points
35224 if (
35225 component.matchedPoints[0] > glyph.points.length - 1 ||
35226 component.matchedPoints[1] > componentGlyph.points.length - 1
35227 ) {
35228 throw Error('Matched points out of range in ' + glyph.name);
35229 }
35230 var firstPt = glyph.points[component.matchedPoints[0]];
35231 var secondPt = componentGlyph.points[component.matchedPoints[1]];
35232 var transform = {
35233 xScale: component.xScale,
35234 scale01: component.scale01,
35235 scale10: component.scale10,
35236 yScale: component.yScale,
35237 dx: 0,
35238 dy: 0
35239 };
35240 secondPt = transformPoints([secondPt], transform)[0];
35241 transform.dx = firstPt.x - secondPt.x;
35242 transform.dy = firstPt.y - secondPt.y;
35243 transformedPoints = transformPoints(
35244 componentGlyph.points,
35245 transform
35246 );
35247 }
35248 glyph.points = glyph.points.concat(transformedPoints);
35249 }
35250 }
35251 }
35252
35253 return getPath(glyph.points);
35254 }
35255
35256 // Parse all the glyphs according to the offsets from the `loca` table.
35257 function parseGlyfTable(data, start, loca, font) {
35258 var glyphs = new glyphset.GlyphSet(font);
35259
35260 // The last element of the loca table is invalid.
35261 for (var i = 0; i < loca.length - 1; i += 1) {
35262 var offset = loca[i];
35263 var nextOffset = loca[i + 1];
35264 if (offset !== nextOffset) {
35265 glyphs.push(
35266 i,
35267 glyphset.ttfGlyphLoader(
35268 font,
35269 i,
35270 parseGlyph,
35271 data,
35272 start + offset,
35273 buildPath
35274 )
35275 );
35276 } else {
35277 glyphs.push(i, glyphset.glyphLoader(font, i));
35278 }
35279 }
35280
35281 return glyphs;
35282 }
35283
35284 var glyf = { getPath: getPath, parse: parseGlyfTable };
35285
35286 /* A TrueType font hinting interpreter.
35287 *
35288 * (c) 2017 Axel Kittenberger
35289 *
35290 * This interpreter has been implemented according to this documentation:
35291 * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM05/Chap5.html
35292 *
35293 * According to the documentation F24DOT6 values are used for pixels.
35294 * That means calculation is 1/64 pixel accurate and uses integer operations.
35295 * However, Javascript has floating point operations by default and only
35296 * those are available. One could make a case to simulate the 1/64 accuracy
35297 * exactly by truncating after every division operation
35298 * (for example with << 0) to get pixel exactly results as other TrueType
35299 * implementations. It may make sense since some fonts are pixel optimized
35300 * by hand using DELTAP instructions. The current implementation doesn't
35301 * and rather uses full floating point precision.
35302 *
35303 * xScale, yScale and rotation is currently ignored.
35304 *
35305 * A few non-trivial instructions are missing as I didn't encounter yet
35306 * a font that used them to test a possible implementation.
35307 *
35308 * Some fonts seem to use undocumented features regarding the twilight zone.
35309 * Only some of them are implemented as they were encountered.
35310 *
35311 * The exports.DEBUG statements are removed on the minified distribution file.
35312 */
35313
35314 var instructionTable;
35315 var exec;
35316 var execGlyph;
35317 var execComponent;
35318
35319 /*
35320 * Creates a hinting object.
35321 *
35322 * There ought to be exactly one
35323 * for each truetype font that is used for hinting.
35324 */
35325 function Hinting(font) {
35326 // the font this hinting object is for
35327 this.font = font;
35328
35329 this.getCommands = function(hPoints) {
35330 return glyf.getPath(hPoints).commands;
35331 };
35332
35333 // cached states
35334 this._fpgmState = this._prepState = undefined;
35335
35336 // errorState
35337 // 0 ... all okay
35338 // 1 ... had an error in a glyf,
35339 // continue working but stop spamming
35340 // the console
35341 // 2 ... error at prep, stop hinting at this ppem
35342 // 3 ... error at fpeg, stop hinting for this font at all
35343 this._errorState = 0;
35344 }
35345
35346 /*
35347 * Not rounding.
35348 */
35349 function roundOff(v) {
35350 return v;
35351 }
35352
35353 /*
35354 * Rounding to grid.
35355 */
35356 function roundToGrid(v) {
35357 //Rounding in TT is supposed to "symmetrical around zero"
35358 return Math.sign(v) * Math.round(Math.abs(v));
35359 }
35360
35361 /*
35362 * Rounding to double grid.
35363 */
35364 function roundToDoubleGrid(v) {
35365 return Math.sign(v) * Math.round(Math.abs(v * 2)) / 2;
35366 }
35367
35368 /*
35369 * Rounding to half grid.
35370 */
35371 function roundToHalfGrid(v) {
35372 return Math.sign(v) * (Math.round(Math.abs(v) + 0.5) - 0.5);
35373 }
35374
35375 /*
35376 * Rounding to up to grid.
35377 */
35378 function roundUpToGrid(v) {
35379 return Math.sign(v) * Math.ceil(Math.abs(v));
35380 }
35381
35382 /*
35383 * Rounding to down to grid.
35384 */
35385 function roundDownToGrid(v) {
35386 return Math.sign(v) * Math.floor(Math.abs(v));
35387 }
35388
35389 /*
35390 * Super rounding.
35391 */
35392 var roundSuper = function(v) {
35393 var period = this.srPeriod;
35394 var phase = this.srPhase;
35395 var threshold = this.srThreshold;
35396 var sign = 1;
35397
35398 if (v < 0) {
35399 v = -v;
35400 sign = -1;
35401 }
35402
35403 v += threshold - phase;
35404
35405 v = Math.trunc(v / period) * period;
35406
35407 v += phase;
35408
35409 // according to http://xgridfit.sourceforge.net/round.html
35410 if (v < 0) {
35411 return phase * sign;
35412 }
35413
35414 return v * sign;
35415 };
35416
35417 /*
35418 * Unit vector of x-axis.
35419 */
35420 var xUnitVector = {
35421 x: 1,
35422
35423 y: 0,
35424
35425 axis: 'x',
35426
35427 // Gets the projected distance between two points.
35428 // o1/o2 ... if true, respective original position is used.
35429 distance: function(p1, p2, o1, o2) {
35430 return (o1 ? p1.xo : p1.x) - (o2 ? p2.xo : p2.x);
35431 },
35432
35433 // Moves point p so the moved position has the same relative
35434 // position to the moved positions of rp1 and rp2 than the
35435 // original positions had.
35436 //
35437 // See APPENDIX on INTERPOLATE at the bottom of this file.
35438 interpolate: function(p, rp1, rp2, pv) {
35439 var do1;
35440 var do2;
35441 var doa1;
35442 var doa2;
35443 var dm1;
35444 var dm2;
35445 var dt;
35446
35447 if (!pv || pv === this) {
35448 do1 = p.xo - rp1.xo;
35449 do2 = p.xo - rp2.xo;
35450 dm1 = rp1.x - rp1.xo;
35451 dm2 = rp2.x - rp2.xo;
35452 doa1 = Math.abs(do1);
35453 doa2 = Math.abs(do2);
35454 dt = doa1 + doa2;
35455
35456 if (dt === 0) {
35457 p.x = p.xo + (dm1 + dm2) / 2;
35458 return;
35459 }
35460
35461 p.x = p.xo + (dm1 * doa2 + dm2 * doa1) / dt;
35462 return;
35463 }
35464
35465 do1 = pv.distance(p, rp1, true, true);
35466 do2 = pv.distance(p, rp2, true, true);
35467 dm1 = pv.distance(rp1, rp1, false, true);
35468 dm2 = pv.distance(rp2, rp2, false, true);
35469 doa1 = Math.abs(do1);
35470 doa2 = Math.abs(do2);
35471 dt = doa1 + doa2;
35472
35473 if (dt === 0) {
35474 xUnitVector.setRelative(p, p, (dm1 + dm2) / 2, pv, true);
35475 return;
35476 }
35477
35478 xUnitVector.setRelative(p, p, (dm1 * doa2 + dm2 * doa1) / dt, pv, true);
35479 },
35480
35481 // Slope of line normal to this
35482 normalSlope: Number.NEGATIVE_INFINITY,
35483
35484 // Sets the point 'p' relative to point 'rp'
35485 // by the distance 'd'.
35486 //
35487 // See APPENDIX on SETRELATIVE at the bottom of this file.
35488 //
35489 // p ... point to set
35490 // rp ... reference point
35491 // d ... distance on projection vector
35492 // pv ... projection vector (undefined = this)
35493 // org ... if true, uses the original position of rp as reference.
35494 setRelative: function(p, rp, d, pv, org) {
35495 if (!pv || pv === this) {
35496 p.x = (org ? rp.xo : rp.x) + d;
35497 return;
35498 }
35499
35500 var rpx = org ? rp.xo : rp.x;
35501 var rpy = org ? rp.yo : rp.y;
35502 var rpdx = rpx + d * pv.x;
35503 var rpdy = rpy + d * pv.y;
35504
35505 p.x = rpdx + (p.y - rpdy) / pv.normalSlope;
35506 },
35507
35508 // Slope of vector line.
35509 slope: 0,
35510
35511 // Touches the point p.
35512 touch: function(p) {
35513 p.xTouched = true;
35514 },
35515
35516 // Tests if a point p is touched.
35517 touched: function(p) {
35518 return p.xTouched;
35519 },
35520
35521 // Untouches the point p.
35522 untouch: function(p) {
35523 p.xTouched = false;
35524 }
35525 };
35526
35527 /*
35528 * Unit vector of y-axis.
35529 */
35530 var yUnitVector = {
35531 x: 0,
35532
35533 y: 1,
35534
35535 axis: 'y',
35536
35537 // Gets the projected distance between two points.
35538 // o1/o2 ... if true, respective original position is used.
35539 distance: function(p1, p2, o1, o2) {
35540 return (o1 ? p1.yo : p1.y) - (o2 ? p2.yo : p2.y);
35541 },
35542
35543 // Moves point p so the moved position has the same relative
35544 // position to the moved positions of rp1 and rp2 than the
35545 // original positions had.
35546 //
35547 // See APPENDIX on INTERPOLATE at the bottom of this file.
35548 interpolate: function(p, rp1, rp2, pv) {
35549 var do1;
35550 var do2;
35551 var doa1;
35552 var doa2;
35553 var dm1;
35554 var dm2;
35555 var dt;
35556
35557 if (!pv || pv === this) {
35558 do1 = p.yo - rp1.yo;
35559 do2 = p.yo - rp2.yo;
35560 dm1 = rp1.y - rp1.yo;
35561 dm2 = rp2.y - rp2.yo;
35562 doa1 = Math.abs(do1);
35563 doa2 = Math.abs(do2);
35564 dt = doa1 + doa2;
35565
35566 if (dt === 0) {
35567 p.y = p.yo + (dm1 + dm2) / 2;
35568 return;
35569 }
35570
35571 p.y = p.yo + (dm1 * doa2 + dm2 * doa1) / dt;
35572 return;
35573 }
35574
35575 do1 = pv.distance(p, rp1, true, true);
35576 do2 = pv.distance(p, rp2, true, true);
35577 dm1 = pv.distance(rp1, rp1, false, true);
35578 dm2 = pv.distance(rp2, rp2, false, true);
35579 doa1 = Math.abs(do1);
35580 doa2 = Math.abs(do2);
35581 dt = doa1 + doa2;
35582
35583 if (dt === 0) {
35584 yUnitVector.setRelative(p, p, (dm1 + dm2) / 2, pv, true);
35585 return;
35586 }
35587
35588 yUnitVector.setRelative(p, p, (dm1 * doa2 + dm2 * doa1) / dt, pv, true);
35589 },
35590
35591 // Slope of line normal to this.
35592 normalSlope: 0,
35593
35594 // Sets the point 'p' relative to point 'rp'
35595 // by the distance 'd'
35596 //
35597 // See APPENDIX on SETRELATIVE at the bottom of this file.
35598 //
35599 // p ... point to set
35600 // rp ... reference point
35601 // d ... distance on projection vector
35602 // pv ... projection vector (undefined = this)
35603 // org ... if true, uses the original position of rp as reference.
35604 setRelative: function(p, rp, d, pv, org) {
35605 if (!pv || pv === this) {
35606 p.y = (org ? rp.yo : rp.y) + d;
35607 return;
35608 }
35609
35610 var rpx = org ? rp.xo : rp.x;
35611 var rpy = org ? rp.yo : rp.y;
35612 var rpdx = rpx + d * pv.x;
35613 var rpdy = rpy + d * pv.y;
35614
35615 p.y = rpdy + pv.normalSlope * (p.x - rpdx);
35616 },
35617
35618 // Slope of vector line.
35619 slope: Number.POSITIVE_INFINITY,
35620
35621 // Touches the point p.
35622 touch: function(p) {
35623 p.yTouched = true;
35624 },
35625
35626 // Tests if a point p is touched.
35627 touched: function(p) {
35628 return p.yTouched;
35629 },
35630
35631 // Untouches the point p.
35632 untouch: function(p) {
35633 p.yTouched = false;
35634 }
35635 };
35636
35637 Object.freeze(xUnitVector);
35638 Object.freeze(yUnitVector);
35639
35640 /*
35641 * Creates a unit vector that is not x- or y-axis.
35642 */
35643 function UnitVector(x, y) {
35644 this.x = x;
35645 this.y = y;
35646 this.axis = undefined;
35647 this.slope = y / x;
35648 this.normalSlope = -x / y;
35649 Object.freeze(this);
35650 }
35651
35652 /*
35653 * Gets the projected distance between two points.
35654 * o1/o2 ... if true, respective original position is used.
35655 */
35656 UnitVector.prototype.distance = function(p1, p2, o1, o2) {
35657 return (
35658 this.x * xUnitVector.distance(p1, p2, o1, o2) +
35659 this.y * yUnitVector.distance(p1, p2, o1, o2)
35660 );
35661 };
35662
35663 /*
35664 * Moves point p so the moved position has the same relative
35665 * position to the moved positions of rp1 and rp2 than the
35666 * original positions had.
35667 *
35668 * See APPENDIX on INTERPOLATE at the bottom of this file.
35669 */
35670 UnitVector.prototype.interpolate = function(p, rp1, rp2, pv) {
35671 var dm1;
35672 var dm2;
35673 var do1;
35674 var do2;
35675 var doa1;
35676 var doa2;
35677 var dt;
35678
35679 do1 = pv.distance(p, rp1, true, true);
35680 do2 = pv.distance(p, rp2, true, true);
35681 dm1 = pv.distance(rp1, rp1, false, true);
35682 dm2 = pv.distance(rp2, rp2, false, true);
35683 doa1 = Math.abs(do1);
35684 doa2 = Math.abs(do2);
35685 dt = doa1 + doa2;
35686
35687 if (dt === 0) {
35688 this.setRelative(p, p, (dm1 + dm2) / 2, pv, true);
35689 return;
35690 }
35691
35692 this.setRelative(p, p, (dm1 * doa2 + dm2 * doa1) / dt, pv, true);
35693 };
35694
35695 /*
35696 * Sets the point 'p' relative to point 'rp'
35697 * by the distance 'd'
35698 *
35699 * See APPENDIX on SETRELATIVE at the bottom of this file.
35700 *
35701 * p ... point to set
35702 * rp ... reference point
35703 * d ... distance on projection vector
35704 * pv ... projection vector (undefined = this)
35705 * org ... if true, uses the original position of rp as reference.
35706 */
35707 UnitVector.prototype.setRelative = function(p, rp, d, pv, org) {
35708 pv = pv || this;
35709
35710 var rpx = org ? rp.xo : rp.x;
35711 var rpy = org ? rp.yo : rp.y;
35712 var rpdx = rpx + d * pv.x;
35713 var rpdy = rpy + d * pv.y;
35714
35715 var pvns = pv.normalSlope;
35716 var fvs = this.slope;
35717
35718 var px = p.x;
35719 var py = p.y;
35720
35721 p.x = (fvs * px - pvns * rpdx + rpdy - py) / (fvs - pvns);
35722 p.y = fvs * (p.x - px) + py;
35723 };
35724
35725 /*
35726 * Touches the point p.
35727 */
35728 UnitVector.prototype.touch = function(p) {
35729 p.xTouched = true;
35730 p.yTouched = true;
35731 };
35732
35733 /*
35734 * Returns a unit vector with x/y coordinates.
35735 */
35736 function getUnitVector(x, y) {
35737 var d = Math.sqrt(x * x + y * y);
35738
35739 x /= d;
35740 y /= d;
35741
35742 if (x === 1 && y === 0) {
35743 return xUnitVector;
35744 } else if (x === 0 && y === 1) {
35745 return yUnitVector;
35746 } else {
35747 return new UnitVector(x, y);
35748 }
35749 }
35750
35751 /*
35752 * Creates a point in the hinting engine.
35753 */
35754 function HPoint(x, y, lastPointOfContour, onCurve) {
35755 this.x = this.xo = Math.round(x * 64) / 64; // hinted x value and original x-value
35756 this.y = this.yo = Math.round(y * 64) / 64; // hinted y value and original y-value
35757
35758 this.lastPointOfContour = lastPointOfContour;
35759 this.onCurve = onCurve;
35760 this.prevPointOnContour = undefined;
35761 this.nextPointOnContour = undefined;
35762 this.xTouched = false;
35763 this.yTouched = false;
35764
35765 Object.preventExtensions(this);
35766 }
35767
35768 /*
35769 * Returns the next touched point on the contour.
35770 *
35771 * v ... unit vector to test touch axis.
35772 */
35773 HPoint.prototype.nextTouched = function(v) {
35774 var p = this.nextPointOnContour;
35775
35776 while (!v.touched(p) && p !== this) {
35777 p = p.nextPointOnContour;
35778 }
35779
35780 return p;
35781 };
35782
35783 /*
35784 * Returns the previous touched point on the contour
35785 *
35786 * v ... unit vector to test touch axis.
35787 */
35788 HPoint.prototype.prevTouched = function(v) {
35789 var p = this.prevPointOnContour;
35790
35791 while (!v.touched(p) && p !== this) {
35792 p = p.prevPointOnContour;
35793 }
35794
35795 return p;
35796 };
35797
35798 /*
35799 * The zero point.
35800 */
35801 var HPZero = Object.freeze(new HPoint(0, 0));
35802
35803 /*
35804 * The default state of the interpreter.
35805 *
35806 * Note: Freezing the defaultState and then deriving from it
35807 * makes the V8 Javascript engine going awkward,
35808 * so this is avoided, albeit the defaultState shouldn't
35809 * ever change.
35810 */
35811 var defaultState = {
35812 cvCutIn: 17 / 16, // control value cut in
35813 deltaBase: 9,
35814 deltaShift: 0.125,
35815 loop: 1, // loops some instructions
35816 minDis: 1, // minimum distance
35817 autoFlip: true
35818 };
35819
35820 /*
35821 * The current state of the interpreter.
35822 *
35823 * env ... 'fpgm' or 'prep' or 'glyf'
35824 * prog ... the program
35825 */
35826 function State(env, prog) {
35827 this.env = env;
35828 this.stack = [];
35829 this.prog = prog;
35830
35831 switch (env) {
35832 case 'glyf':
35833 this.zp0 = this.zp1 = this.zp2 = 1;
35834 this.rp0 = this.rp1 = this.rp2 = 0;
35835 /* fall through */
35836 case 'prep':
35837 this.fv = this.pv = this.dpv = xUnitVector;
35838 this.round = roundToGrid;
35839 }
35840 }
35841
35842 /*
35843 * Executes a glyph program.
35844 *
35845 * This does the hinting for each glyph.
35846 *
35847 * Returns an array of moved points.
35848 *
35849 * glyph: the glyph to hint
35850 * ppem: the size the glyph is rendered for
35851 */
35852 Hinting.prototype.exec = function(glyph, ppem) {
35853 if (typeof ppem !== 'number') {
35854 throw new Error('Point size is not a number!');
35855 }
35856
35857 // Received a fatal error, don't do any hinting anymore.
35858 if (this._errorState > 2) {
35859 return;
35860 }
35861
35862 var font = this.font;
35863 var prepState = this._prepState;
35864
35865 if (!prepState || prepState.ppem !== ppem) {
35866 var fpgmState = this._fpgmState;
35867
35868 if (!fpgmState) {
35869 // Executes the fpgm state.
35870 // This is used by fonts to define functions.
35871 State.prototype = defaultState;
35872
35873 fpgmState = this._fpgmState = new State('fpgm', font.tables.fpgm);
35874
35875 fpgmState.funcs = [];
35876 fpgmState.font = font;
35877
35878 if (exports.DEBUG) {
35879 console.log('---EXEC FPGM---');
35880 fpgmState.step = -1;
35881 }
35882
35883 try {
35884 exec(fpgmState);
35885 } catch (e) {
35886 console.log('Hinting error in FPGM:' + e);
35887 this._errorState = 3;
35888 return;
35889 }
35890 }
35891
35892 // Executes the prep program for this ppem setting.
35893 // This is used by fonts to set cvt values
35894 // depending on to be rendered font size.
35895
35896 State.prototype = fpgmState;
35897 prepState = this._prepState = new State('prep', font.tables.prep);
35898
35899 prepState.ppem = ppem;
35900
35901 // Creates a copy of the cvt table
35902 // and scales it to the current ppem setting.
35903 var oCvt = font.tables.cvt;
35904 if (oCvt) {
35905 var cvt = (prepState.cvt = new Array(oCvt.length));
35906 var scale = ppem / font.unitsPerEm;
35907 for (var c = 0; c < oCvt.length; c++) {
35908 cvt[c] = oCvt[c] * scale;
35909 }
35910 } else {
35911 prepState.cvt = [];
35912 }
35913
35914 if (exports.DEBUG) {
35915 console.log('---EXEC PREP---');
35916 prepState.step = -1;
35917 }
35918
35919 try {
35920 exec(prepState);
35921 } catch (e) {
35922 if (this._errorState < 2) {
35923 console.log('Hinting error in PREP:' + e);
35924 }
35925 this._errorState = 2;
35926 }
35927 }
35928
35929 if (this._errorState > 1) {
35930 return;
35931 }
35932
35933 try {
35934 return execGlyph(glyph, prepState);
35935 } catch (e) {
35936 if (this._errorState < 1) {
35937 console.log('Hinting error:' + e);
35938 console.log('Note: further hinting errors are silenced');
35939 }
35940 this._errorState = 1;
35941 return undefined;
35942 }
35943 };
35944
35945 /*
35946 * Executes the hinting program for a glyph.
35947 */
35948 execGlyph = function(glyph, prepState) {
35949 // original point positions
35950 var xScale = prepState.ppem / prepState.font.unitsPerEm;
35951 var yScale = xScale;
35952 var components = glyph.components;
35953 var contours;
35954 var gZone;
35955 var state;
35956
35957 State.prototype = prepState;
35958 if (!components) {
35959 state = new State('glyf', glyph.instructions);
35960 if (exports.DEBUG) {
35961 console.log('---EXEC GLYPH---');
35962 state.step = -1;
35963 }
35964 execComponent(glyph, state, xScale, yScale);
35965 gZone = state.gZone;
35966 } else {
35967 var font = prepState.font;
35968 gZone = [];
35969 contours = [];
35970 for (var i = 0; i < components.length; i++) {
35971 var c = components[i];
35972 var cg = font.glyphs.get(c.glyphIndex);
35973
35974 state = new State('glyf', cg.instructions);
35975
35976 if (exports.DEBUG) {
35977 console.log('---EXEC COMP ' + i + '---');
35978 state.step = -1;
35979 }
35980
35981 execComponent(cg, state, xScale, yScale);
35982 // appends the computed points to the result array
35983 // post processes the component points
35984 var dx = Math.round(c.dx * xScale);
35985 var dy = Math.round(c.dy * yScale);
35986 var gz = state.gZone;
35987 var cc = state.contours;
35988 for (var pi = 0; pi < gz.length; pi++) {
35989 var p = gz[pi];
35990 p.xTouched = p.yTouched = false;
35991 p.xo = p.x = p.x + dx;
35992 p.yo = p.y = p.y + dy;
35993 }
35994
35995 var gLen = gZone.length;
35996 gZone.push.apply(gZone, gz);
35997 for (var j = 0; j < cc.length; j++) {
35998 contours.push(cc[j] + gLen);
35999 }
36000 }
36001
36002 if (glyph.instructions && !state.inhibitGridFit) {
36003 // the composite has instructions on its own
36004 state = new State('glyf', glyph.instructions);
36005
36006 state.gZone = state.z0 = state.z1 = state.z2 = gZone;
36007
36008 state.contours = contours;
36009
36010 // note: HPZero cannot be used here, since
36011 // the point might be modified
36012 gZone.push(
36013 new HPoint(0, 0),
36014 new HPoint(Math.round(glyph.advanceWidth * xScale), 0)
36015 );
36016
36017 if (exports.DEBUG) {
36018 console.log('---EXEC COMPOSITE---');
36019 state.step = -1;
36020 }
36021
36022 exec(state);
36023
36024 gZone.length -= 2;
36025 }
36026 }
36027
36028 return gZone;
36029 };
36030
36031 /*
36032 * Executes the hinting program for a component of a multi-component glyph
36033 * or of the glyph itself for a non-component glyph.
36034 */
36035 execComponent = function(glyph, state, xScale, yScale) {
36036 var points = glyph.points || [];
36037 var pLen = points.length;
36038 var gZone = (state.gZone = state.z0 = state.z1 = state.z2 = []);
36039 var contours = (state.contours = []);
36040
36041 // Scales the original points and
36042 // makes copies for the hinted points.
36043 var cp; // current point
36044 for (var i = 0; i < pLen; i++) {
36045 cp = points[i];
36046
36047 gZone[i] = new HPoint(
36048 cp.x * xScale,
36049 cp.y * yScale,
36050 cp.lastPointOfContour,
36051 cp.onCurve
36052 );
36053 }
36054
36055 // Chain links the contours.
36056 var sp; // start point
36057 var np; // next point
36058
36059 for (var i$1 = 0; i$1 < pLen; i$1++) {
36060 cp = gZone[i$1];
36061
36062 if (!sp) {
36063 sp = cp;
36064 contours.push(i$1);
36065 }
36066
36067 if (cp.lastPointOfContour) {
36068 cp.nextPointOnContour = sp;
36069 sp.prevPointOnContour = cp;
36070 sp = undefined;
36071 } else {
36072 np = gZone[i$1 + 1];
36073 cp.nextPointOnContour = np;
36074 np.prevPointOnContour = cp;
36075 }
36076 }
36077
36078 if (state.inhibitGridFit) {
36079 return;
36080 }
36081
36082 if (exports.DEBUG) {
36083 console.log('PROCESSING GLYPH', state.stack);
36084 for (var i$2 = 0; i$2 < pLen; i$2++) {
36085 console.log(i$2, gZone[i$2].x, gZone[i$2].y);
36086 }
36087 }
36088
36089 gZone.push(
36090 new HPoint(0, 0),
36091 new HPoint(Math.round(glyph.advanceWidth * xScale), 0)
36092 );
36093
36094 exec(state);
36095
36096 // Removes the extra points.
36097 gZone.length -= 2;
36098
36099 if (exports.DEBUG) {
36100 console.log('FINISHED GLYPH', state.stack);
36101 for (var i$3 = 0; i$3 < pLen; i$3++) {
36102 console.log(i$3, gZone[i$3].x, gZone[i$3].y);
36103 }
36104 }
36105 };
36106
36107 /*
36108 * Executes the program loaded in state.
36109 */
36110 exec = function(state) {
36111 var prog = state.prog;
36112
36113 if (!prog) {
36114 return;
36115 }
36116
36117 var pLen = prog.length;
36118 var ins;
36119
36120 for (state.ip = 0; state.ip < pLen; state.ip++) {
36121 if (exports.DEBUG) {
36122 state.step++;
36123 }
36124 ins = instructionTable[prog[state.ip]];
36125
36126 if (!ins) {
36127 throw new Error(
36128 'unknown instruction: 0x' + Number(prog[state.ip]).toString(16)
36129 );
36130 }
36131
36132 ins(state);
36133
36134 // very extensive debugging for each step
36135 /*
36136 if (exports.DEBUG) {
36137 var da;
36138 if (state.gZone) {
36139 da = [];
36140 for (let i = 0; i < state.gZone.length; i++)
36141 {
36142 da.push(i + ' ' +
36143 state.gZone[i].x * 64 + ' ' +
36144 state.gZone[i].y * 64 + ' ' +
36145 (state.gZone[i].xTouched ? 'x' : '') +
36146 (state.gZone[i].yTouched ? 'y' : '')
36147 );
36148 }
36149 console.log('GZ', da);
36150 }
36151
36152 if (state.tZone) {
36153 da = [];
36154 for (let i = 0; i < state.tZone.length; i++) {
36155 da.push(i + ' ' +
36156 state.tZone[i].x * 64 + ' ' +
36157 state.tZone[i].y * 64 + ' ' +
36158 (state.tZone[i].xTouched ? 'x' : '') +
36159 (state.tZone[i].yTouched ? 'y' : '')
36160 );
36161 }
36162 console.log('TZ', da);
36163 }
36164
36165 if (state.stack.length > 10) {
36166 console.log(
36167 state.stack.length,
36168 '...', state.stack.slice(state.stack.length - 10)
36169 );
36170 } else {
36171 console.log(state.stack.length, state.stack);
36172 }
36173 }
36174 */
36175 }
36176 };
36177
36178 /*
36179 * Initializes the twilight zone.
36180 *
36181 * This is only done if a SZPx instruction
36182 * refers to the twilight zone.
36183 */
36184 function initTZone(state) {
36185 var tZone = (state.tZone = new Array(state.gZone.length));
36186
36187 // no idea if this is actually correct...
36188 for (var i = 0; i < tZone.length; i++) {
36189 tZone[i] = new HPoint(0, 0);
36190 }
36191 }
36192
36193 /*
36194 * Skips the instruction pointer ahead over an IF/ELSE block.
36195 * handleElse .. if true breaks on matching ELSE
36196 */
36197 function skip(state, handleElse) {
36198 var prog = state.prog;
36199 var ip = state.ip;
36200 var nesting = 1;
36201 var ins;
36202
36203 do {
36204 ins = prog[++ip];
36205 if (ins === 0x58) {
36206 // IF
36207 nesting++;
36208 } else if (ins === 0x59) {
36209 // EIF
36210 nesting--;
36211 } else if (ins === 0x40) {
36212 // NPUSHB
36213 ip += prog[ip + 1] + 1;
36214 } else if (ins === 0x41) {
36215 // NPUSHW
36216 ip += 2 * prog[ip + 1] + 1;
36217 } else if (ins >= 0xb0 && ins <= 0xb7) {
36218 // PUSHB
36219 ip += ins - 0xb0 + 1;
36220 } else if (ins >= 0xb8 && ins <= 0xbf) {
36221 // PUSHW
36222 ip += (ins - 0xb8 + 1) * 2;
36223 } else if (handleElse && nesting === 1 && ins === 0x1b) {
36224 // ELSE
36225 break;
36226 }
36227 } while (nesting > 0);
36228
36229 state.ip = ip;
36230 }
36231
36232 /*----------------------------------------------------------*
36233 * And then a lot of instructions... *
36234 *----------------------------------------------------------*/
36235
36236 // SVTCA[a] Set freedom and projection Vectors To Coordinate Axis
36237 // 0x00-0x01
36238 function SVTCA(v, state) {
36239 if (exports.DEBUG) {
36240 console.log(state.step, 'SVTCA[' + v.axis + ']');
36241 }
36242
36243 state.fv = state.pv = state.dpv = v;
36244 }
36245
36246 // SPVTCA[a] Set Projection Vector to Coordinate Axis
36247 // 0x02-0x03
36248 function SPVTCA(v, state) {
36249 if (exports.DEBUG) {
36250 console.log(state.step, 'SPVTCA[' + v.axis + ']');
36251 }
36252
36253 state.pv = state.dpv = v;
36254 }
36255
36256 // SFVTCA[a] Set Freedom Vector to Coordinate Axis
36257 // 0x04-0x05
36258 function SFVTCA(v, state) {
36259 if (exports.DEBUG) {
36260 console.log(state.step, 'SFVTCA[' + v.axis + ']');
36261 }
36262
36263 state.fv = v;
36264 }
36265
36266 // SPVTL[a] Set Projection Vector To Line
36267 // 0x06-0x07
36268 function SPVTL(a, state) {
36269 var stack = state.stack;
36270 var p2i = stack.pop();
36271 var p1i = stack.pop();
36272 var p2 = state.z2[p2i];
36273 var p1 = state.z1[p1i];
36274
36275 if (exports.DEBUG) {
36276 console.log('SPVTL[' + a + ']', p2i, p1i);
36277 }
36278
36279 var dx;
36280 var dy;
36281
36282 if (!a) {
36283 dx = p1.x - p2.x;
36284 dy = p1.y - p2.y;
36285 } else {
36286 dx = p2.y - p1.y;
36287 dy = p1.x - p2.x;
36288 }
36289
36290 state.pv = state.dpv = getUnitVector(dx, dy);
36291 }
36292
36293 // SFVTL[a] Set Freedom Vector To Line
36294 // 0x08-0x09
36295 function SFVTL(a, state) {
36296 var stack = state.stack;
36297 var p2i = stack.pop();
36298 var p1i = stack.pop();
36299 var p2 = state.z2[p2i];
36300 var p1 = state.z1[p1i];
36301
36302 if (exports.DEBUG) {
36303 console.log('SFVTL[' + a + ']', p2i, p1i);
36304 }
36305
36306 var dx;
36307 var dy;
36308
36309 if (!a) {
36310 dx = p1.x - p2.x;
36311 dy = p1.y - p2.y;
36312 } else {
36313 dx = p2.y - p1.y;
36314 dy = p1.x - p2.x;
36315 }
36316
36317 state.fv = getUnitVector(dx, dy);
36318 }
36319
36320 // SPVFS[] Set Projection Vector From Stack
36321 // 0x0A
36322 function SPVFS(state) {
36323 var stack = state.stack;
36324 var y = stack.pop();
36325 var x = stack.pop();
36326
36327 if (exports.DEBUG) {
36328 console.log(state.step, 'SPVFS[]', y, x);
36329 }
36330
36331 state.pv = state.dpv = getUnitVector(x, y);
36332 }
36333
36334 // SFVFS[] Set Freedom Vector From Stack
36335 // 0x0B
36336 function SFVFS(state) {
36337 var stack = state.stack;
36338 var y = stack.pop();
36339 var x = stack.pop();
36340
36341 if (exports.DEBUG) {
36342 console.log(state.step, 'SPVFS[]', y, x);
36343 }
36344
36345 state.fv = getUnitVector(x, y);
36346 }
36347
36348 // GPV[] Get Projection Vector
36349 // 0x0C
36350 function GPV(state) {
36351 var stack = state.stack;
36352 var pv = state.pv;
36353
36354 if (exports.DEBUG) {
36355 console.log(state.step, 'GPV[]');
36356 }
36357
36358 stack.push(pv.x * 0x4000);
36359 stack.push(pv.y * 0x4000);
36360 }
36361
36362 // GFV[] Get Freedom Vector
36363 // 0x0C
36364 function GFV(state) {
36365 var stack = state.stack;
36366 var fv = state.fv;
36367
36368 if (exports.DEBUG) {
36369 console.log(state.step, 'GFV[]');
36370 }
36371
36372 stack.push(fv.x * 0x4000);
36373 stack.push(fv.y * 0x4000);
36374 }
36375
36376 // SFVTPV[] Set Freedom Vector To Projection Vector
36377 // 0x0E
36378 function SFVTPV(state) {
36379 state.fv = state.pv;
36380
36381 if (exports.DEBUG) {
36382 console.log(state.step, 'SFVTPV[]');
36383 }
36384 }
36385
36386 // ISECT[] moves point p to the InterSECTion of two lines
36387 // 0x0F
36388 function ISECT(state) {
36389 var stack = state.stack;
36390 var pa0i = stack.pop();
36391 var pa1i = stack.pop();
36392 var pb0i = stack.pop();
36393 var pb1i = stack.pop();
36394 var pi = stack.pop();
36395 var z0 = state.z0;
36396 var z1 = state.z1;
36397 var pa0 = z0[pa0i];
36398 var pa1 = z0[pa1i];
36399 var pb0 = z1[pb0i];
36400 var pb1 = z1[pb1i];
36401 var p = state.z2[pi];
36402
36403 if (exports.DEBUG) {
36404 console.log('ISECT[], ', pa0i, pa1i, pb0i, pb1i, pi);
36405 }
36406
36407 // math from
36408 // en.wikipedia.org/wiki/Line%E2%80%93line_intersection#Given_two_points_on_each_line
36409
36410 var x1 = pa0.x;
36411 var y1 = pa0.y;
36412 var x2 = pa1.x;
36413 var y2 = pa1.y;
36414 var x3 = pb0.x;
36415 var y3 = pb0.y;
36416 var x4 = pb1.x;
36417 var y4 = pb1.y;
36418
36419 var div = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
36420 var f1 = x1 * y2 - y1 * x2;
36421 var f2 = x3 * y4 - y3 * x4;
36422
36423 p.x = (f1 * (x3 - x4) - f2 * (x1 - x2)) / div;
36424 p.y = (f1 * (y3 - y4) - f2 * (y1 - y2)) / div;
36425 }
36426
36427 // SRP0[] Set Reference Point 0
36428 // 0x10
36429 function SRP0(state) {
36430 state.rp0 = state.stack.pop();
36431
36432 if (exports.DEBUG) {
36433 console.log(state.step, 'SRP0[]', state.rp0);
36434 }
36435 }
36436
36437 // SRP1[] Set Reference Point 1
36438 // 0x11
36439 function SRP1(state) {
36440 state.rp1 = state.stack.pop();
36441
36442 if (exports.DEBUG) {
36443 console.log(state.step, 'SRP1[]', state.rp1);
36444 }
36445 }
36446
36447 // SRP1[] Set Reference Point 2
36448 // 0x12
36449 function SRP2(state) {
36450 state.rp2 = state.stack.pop();
36451
36452 if (exports.DEBUG) {
36453 console.log(state.step, 'SRP2[]', state.rp2);
36454 }
36455 }
36456
36457 // SZP0[] Set Zone Pointer 0
36458 // 0x13
36459 function SZP0(state) {
36460 var n = state.stack.pop();
36461
36462 if (exports.DEBUG) {
36463 console.log(state.step, 'SZP0[]', n);
36464 }
36465
36466 state.zp0 = n;
36467
36468 switch (n) {
36469 case 0:
36470 if (!state.tZone) {
36471 initTZone(state);
36472 }
36473 state.z0 = state.tZone;
36474 break;
36475 case 1:
36476 state.z0 = state.gZone;
36477 break;
36478 default:
36479 throw new Error('Invalid zone pointer');
36480 }
36481 }
36482
36483 // SZP1[] Set Zone Pointer 1
36484 // 0x14
36485 function SZP1(state) {
36486 var n = state.stack.pop();
36487
36488 if (exports.DEBUG) {
36489 console.log(state.step, 'SZP1[]', n);
36490 }
36491
36492 state.zp1 = n;
36493
36494 switch (n) {
36495 case 0:
36496 if (!state.tZone) {
36497 initTZone(state);
36498 }
36499 state.z1 = state.tZone;
36500 break;
36501 case 1:
36502 state.z1 = state.gZone;
36503 break;
36504 default:
36505 throw new Error('Invalid zone pointer');
36506 }
36507 }
36508
36509 // SZP2[] Set Zone Pointer 2
36510 // 0x15
36511 function SZP2(state) {
36512 var n = state.stack.pop();
36513
36514 if (exports.DEBUG) {
36515 console.log(state.step, 'SZP2[]', n);
36516 }
36517
36518 state.zp2 = n;
36519
36520 switch (n) {
36521 case 0:
36522 if (!state.tZone) {
36523 initTZone(state);
36524 }
36525 state.z2 = state.tZone;
36526 break;
36527 case 1:
36528 state.z2 = state.gZone;
36529 break;
36530 default:
36531 throw new Error('Invalid zone pointer');
36532 }
36533 }
36534
36535 // SZPS[] Set Zone PointerS
36536 // 0x16
36537 function SZPS(state) {
36538 var n = state.stack.pop();
36539
36540 if (exports.DEBUG) {
36541 console.log(state.step, 'SZPS[]', n);
36542 }
36543
36544 state.zp0 = state.zp1 = state.zp2 = n;
36545
36546 switch (n) {
36547 case 0:
36548 if (!state.tZone) {
36549 initTZone(state);
36550 }
36551 state.z0 = state.z1 = state.z2 = state.tZone;
36552 break;
36553 case 1:
36554 state.z0 = state.z1 = state.z2 = state.gZone;
36555 break;
36556 default:
36557 throw new Error('Invalid zone pointer');
36558 }
36559 }
36560
36561 // SLOOP[] Set LOOP variable
36562 // 0x17
36563 function SLOOP(state) {
36564 state.loop = state.stack.pop();
36565
36566 if (exports.DEBUG) {
36567 console.log(state.step, 'SLOOP[]', state.loop);
36568 }
36569 }
36570
36571 // RTG[] Round To Grid
36572 // 0x18
36573 function RTG(state) {
36574 if (exports.DEBUG) {
36575 console.log(state.step, 'RTG[]');
36576 }
36577
36578 state.round = roundToGrid;
36579 }
36580
36581 // RTHG[] Round To Half Grid
36582 // 0x19
36583 function RTHG(state) {
36584 if (exports.DEBUG) {
36585 console.log(state.step, 'RTHG[]');
36586 }
36587
36588 state.round = roundToHalfGrid;
36589 }
36590
36591 // SMD[] Set Minimum Distance
36592 // 0x1A
36593 function SMD(state) {
36594 var d = state.stack.pop();
36595
36596 if (exports.DEBUG) {
36597 console.log(state.step, 'SMD[]', d);
36598 }
36599
36600 state.minDis = d / 0x40;
36601 }
36602
36603 // ELSE[] ELSE clause
36604 // 0x1B
36605 function ELSE(state) {
36606 // This instruction has been reached by executing a then branch
36607 // so it just skips ahead until matching EIF.
36608 //
36609 // In case the IF was negative the IF[] instruction already
36610 // skipped forward over the ELSE[]
36611
36612 if (exports.DEBUG) {
36613 console.log(state.step, 'ELSE[]');
36614 }
36615
36616 skip(state, false);
36617 }
36618
36619 // JMPR[] JuMP Relative
36620 // 0x1C
36621 function JMPR(state) {
36622 var o = state.stack.pop();
36623
36624 if (exports.DEBUG) {
36625 console.log(state.step, 'JMPR[]', o);
36626 }
36627
36628 // A jump by 1 would do nothing.
36629 state.ip += o - 1;
36630 }
36631
36632 // SCVTCI[] Set Control Value Table Cut-In
36633 // 0x1D
36634 function SCVTCI(state) {
36635 var n = state.stack.pop();
36636
36637 if (exports.DEBUG) {
36638 console.log(state.step, 'SCVTCI[]', n);
36639 }
36640
36641 state.cvCutIn = n / 0x40;
36642 }
36643
36644 // DUP[] DUPlicate top stack element
36645 // 0x20
36646 function DUP(state) {
36647 var stack = state.stack;
36648
36649 if (exports.DEBUG) {
36650 console.log(state.step, 'DUP[]');
36651 }
36652
36653 stack.push(stack[stack.length - 1]);
36654 }
36655
36656 // POP[] POP top stack element
36657 // 0x21
36658 function POP(state) {
36659 if (exports.DEBUG) {
36660 console.log(state.step, 'POP[]');
36661 }
36662
36663 state.stack.pop();
36664 }
36665
36666 // CLEAR[] CLEAR the stack
36667 // 0x22
36668 function CLEAR(state) {
36669 if (exports.DEBUG) {
36670 console.log(state.step, 'CLEAR[]');
36671 }
36672
36673 state.stack.length = 0;
36674 }
36675
36676 // SWAP[] SWAP the top two elements on the stack
36677 // 0x23
36678 function SWAP(state) {
36679 var stack = state.stack;
36680
36681 var a = stack.pop();
36682 var b = stack.pop();
36683
36684 if (exports.DEBUG) {
36685 console.log(state.step, 'SWAP[]');
36686 }
36687
36688 stack.push(a);
36689 stack.push(b);
36690 }
36691
36692 // DEPTH[] DEPTH of the stack
36693 // 0x24
36694 function DEPTH(state) {
36695 var stack = state.stack;
36696
36697 if (exports.DEBUG) {
36698 console.log(state.step, 'DEPTH[]');
36699 }
36700
36701 stack.push(stack.length);
36702 }
36703
36704 // LOOPCALL[] LOOPCALL function
36705 // 0x2A
36706 function LOOPCALL(state) {
36707 var stack = state.stack;
36708 var fn = stack.pop();
36709 var c = stack.pop();
36710
36711 if (exports.DEBUG) {
36712 console.log(state.step, 'LOOPCALL[]', fn, c);
36713 }
36714
36715 // saves callers program
36716 var cip = state.ip;
36717 var cprog = state.prog;
36718
36719 state.prog = state.funcs[fn];
36720
36721 // executes the function
36722 for (var i = 0; i < c; i++) {
36723 exec(state);
36724
36725 if (exports.DEBUG) {
36726 console.log(
36727 ++state.step,
36728 i + 1 < c ? 'next loopcall' : 'done loopcall',
36729 i
36730 );
36731 }
36732 }
36733
36734 // restores the callers program
36735 state.ip = cip;
36736 state.prog = cprog;
36737 }
36738
36739 // CALL[] CALL function
36740 // 0x2B
36741 function CALL(state) {
36742 var fn = state.stack.pop();
36743
36744 if (exports.DEBUG) {
36745 console.log(state.step, 'CALL[]', fn);
36746 }
36747
36748 // saves callers program
36749 var cip = state.ip;
36750 var cprog = state.prog;
36751
36752 state.prog = state.funcs[fn];
36753
36754 // executes the function
36755 exec(state);
36756
36757 // restores the callers program
36758 state.ip = cip;
36759 state.prog = cprog;
36760
36761 if (exports.DEBUG) {
36762 console.log(++state.step, 'returning from', fn);
36763 }
36764 }
36765
36766 // CINDEX[] Copy the INDEXed element to the top of the stack
36767 // 0x25
36768 function CINDEX(state) {
36769 var stack = state.stack;
36770 var k = stack.pop();
36771
36772 if (exports.DEBUG) {
36773 console.log(state.step, 'CINDEX[]', k);
36774 }
36775
36776 // In case of k == 1, it copies the last element after popping
36777 // thus stack.length - k.
36778 stack.push(stack[stack.length - k]);
36779 }
36780
36781 // MINDEX[] Move the INDEXed element to the top of the stack
36782 // 0x26
36783 function MINDEX(state) {
36784 var stack = state.stack;
36785 var k = stack.pop();
36786
36787 if (exports.DEBUG) {
36788 console.log(state.step, 'MINDEX[]', k);
36789 }
36790
36791 stack.push(stack.splice(stack.length - k, 1)[0]);
36792 }
36793
36794 // FDEF[] Function DEFinition
36795 // 0x2C
36796 function FDEF(state) {
36797 if (state.env !== 'fpgm') {
36798 throw new Error('FDEF not allowed here');
36799 }
36800 var stack = state.stack;
36801 var prog = state.prog;
36802 var ip = state.ip;
36803
36804 var fn = stack.pop();
36805 var ipBegin = ip;
36806
36807 if (exports.DEBUG) {
36808 console.log(state.step, 'FDEF[]', fn);
36809 }
36810
36811 while (prog[++ip] !== 0x2d) {}
36812
36813 state.ip = ip;
36814 state.funcs[fn] = prog.slice(ipBegin + 1, ip);
36815 }
36816
36817 // MDAP[a] Move Direct Absolute Point
36818 // 0x2E-0x2F
36819 function MDAP(round, state) {
36820 var pi = state.stack.pop();
36821 var p = state.z0[pi];
36822 var fv = state.fv;
36823 var pv = state.pv;
36824
36825 if (exports.DEBUG) {
36826 console.log(state.step, 'MDAP[' + round + ']', pi);
36827 }
36828
36829 var d = pv.distance(p, HPZero);
36830
36831 if (round) {
36832 d = state.round(d);
36833 }
36834
36835 fv.setRelative(p, HPZero, d, pv);
36836 fv.touch(p);
36837
36838 state.rp0 = state.rp1 = pi;
36839 }
36840
36841 // IUP[a] Interpolate Untouched Points through the outline
36842 // 0x30
36843 function IUP(v, state) {
36844 var z2 = state.z2;
36845 var pLen = z2.length - 2;
36846 var cp;
36847 var pp;
36848 var np;
36849
36850 if (exports.DEBUG) {
36851 console.log(state.step, 'IUP[' + v.axis + ']');
36852 }
36853
36854 for (var i = 0; i < pLen; i++) {
36855 cp = z2[i]; // current point
36856
36857 // if this point has been touched go on
36858 if (v.touched(cp)) {
36859 continue;
36860 }
36861
36862 pp = cp.prevTouched(v);
36863
36864 // no point on the contour has been touched?
36865 if (pp === cp) {
36866 continue;
36867 }
36868
36869 np = cp.nextTouched(v);
36870
36871 if (pp === np) {
36872 // only one point on the contour has been touched
36873 // so simply moves the point like that
36874
36875 v.setRelative(cp, cp, v.distance(pp, pp, false, true), v, true);
36876 }
36877
36878 v.interpolate(cp, pp, np, v);
36879 }
36880 }
36881
36882 // SHP[] SHift Point using reference point
36883 // 0x32-0x33
36884 function SHP(a, state) {
36885 var stack = state.stack;
36886 var rpi = a ? state.rp1 : state.rp2;
36887 var rp = (a ? state.z0 : state.z1)[rpi];
36888 var fv = state.fv;
36889 var pv = state.pv;
36890 var loop = state.loop;
36891 var z2 = state.z2;
36892
36893 while (loop--) {
36894 var pi = stack.pop();
36895 var p = z2[pi];
36896
36897 var d = pv.distance(rp, rp, false, true);
36898 fv.setRelative(p, p, d, pv);
36899 fv.touch(p);
36900
36901 if (exports.DEBUG) {
36902 console.log(
36903 state.step,
36904 (state.loop > 1 ? 'loop ' + (state.loop - loop) + ': ' : '') +
36905 'SHP[' +
36906 (a ? 'rp1' : 'rp2') +
36907 ']',
36908 pi
36909 );
36910 }
36911 }
36912
36913 state.loop = 1;
36914 }
36915
36916 // SHC[] SHift Contour using reference point
36917 // 0x36-0x37
36918 function SHC(a, state) {
36919 var stack = state.stack;
36920 var rpi = a ? state.rp1 : state.rp2;
36921 var rp = (a ? state.z0 : state.z1)[rpi];
36922 var fv = state.fv;
36923 var pv = state.pv;
36924 var ci = stack.pop();
36925 var sp = state.z2[state.contours[ci]];
36926 var p = sp;
36927
36928 if (exports.DEBUG) {
36929 console.log(state.step, 'SHC[' + a + ']', ci);
36930 }
36931
36932 var d = pv.distance(rp, rp, false, true);
36933
36934 do {
36935 if (p !== rp) {
36936 fv.setRelative(p, p, d, pv);
36937 }
36938 p = p.nextPointOnContour;
36939 } while (p !== sp);
36940 }
36941
36942 // SHZ[] SHift Zone using reference point
36943 // 0x36-0x37
36944 function SHZ(a, state) {
36945 var stack = state.stack;
36946 var rpi = a ? state.rp1 : state.rp2;
36947 var rp = (a ? state.z0 : state.z1)[rpi];
36948 var fv = state.fv;
36949 var pv = state.pv;
36950
36951 var e = stack.pop();
36952
36953 if (exports.DEBUG) {
36954 console.log(state.step, 'SHZ[' + a + ']', e);
36955 }
36956
36957 var z;
36958 switch (e) {
36959 case 0:
36960 z = state.tZone;
36961 break;
36962 case 1:
36963 z = state.gZone;
36964 break;
36965 default:
36966 throw new Error('Invalid zone');
36967 }
36968
36969 var p;
36970 var d = pv.distance(rp, rp, false, true);
36971 var pLen = z.length - 2;
36972 for (var i = 0; i < pLen; i++) {
36973 p = z[i];
36974 fv.setRelative(p, p, d, pv);
36975 //if (p !== rp) fv.setRelative(p, p, d, pv);
36976 }
36977 }
36978
36979 // SHPIX[] SHift point by a PIXel amount
36980 // 0x38
36981 function SHPIX(state) {
36982 var stack = state.stack;
36983 var loop = state.loop;
36984 var fv = state.fv;
36985 var d = stack.pop() / 0x40;
36986 var z2 = state.z2;
36987
36988 while (loop--) {
36989 var pi = stack.pop();
36990 var p = z2[pi];
36991
36992 if (exports.DEBUG) {
36993 console.log(
36994 state.step,
36995 (state.loop > 1 ? 'loop ' + (state.loop - loop) + ': ' : '') +
36996 'SHPIX[]',
36997 pi,
36998 d
36999 );
37000 }
37001
37002 fv.setRelative(p, p, d);
37003 fv.touch(p);
37004 }
37005
37006 state.loop = 1;
37007 }
37008
37009 // IP[] Interpolate Point
37010 // 0x39
37011 function IP(state) {
37012 var stack = state.stack;
37013 var rp1i = state.rp1;
37014 var rp2i = state.rp2;
37015 var loop = state.loop;
37016 var rp1 = state.z0[rp1i];
37017 var rp2 = state.z1[rp2i];
37018 var fv = state.fv;
37019 var pv = state.dpv;
37020 var z2 = state.z2;
37021
37022 while (loop--) {
37023 var pi = stack.pop();
37024 var p = z2[pi];
37025
37026 if (exports.DEBUG) {
37027 console.log(
37028 state.step,
37029 (state.loop > 1 ? 'loop ' + (state.loop - loop) + ': ' : '') + 'IP[]',
37030 pi,
37031 rp1i,
37032 '<->',
37033 rp2i
37034 );
37035 }
37036
37037 fv.interpolate(p, rp1, rp2, pv);
37038
37039 fv.touch(p);
37040 }
37041
37042 state.loop = 1;
37043 }
37044
37045 // MSIRP[a] Move Stack Indirect Relative Point
37046 // 0x3A-0x3B
37047 function MSIRP(a, state) {
37048 var stack = state.stack;
37049 var d = stack.pop() / 64;
37050 var pi = stack.pop();
37051 var p = state.z1[pi];
37052 var rp0 = state.z0[state.rp0];
37053 var fv = state.fv;
37054 var pv = state.pv;
37055
37056 fv.setRelative(p, rp0, d, pv);
37057 fv.touch(p);
37058
37059 if (exports.DEBUG) {
37060 console.log(state.step, 'MSIRP[' + a + ']', d, pi);
37061 }
37062
37063 state.rp1 = state.rp0;
37064 state.rp2 = pi;
37065 if (a) {
37066 state.rp0 = pi;
37067 }
37068 }
37069
37070 // ALIGNRP[] Align to reference point.
37071 // 0x3C
37072 function ALIGNRP(state) {
37073 var stack = state.stack;
37074 var rp0i = state.rp0;
37075 var rp0 = state.z0[rp0i];
37076 var loop = state.loop;
37077 var fv = state.fv;
37078 var pv = state.pv;
37079 var z1 = state.z1;
37080
37081 while (loop--) {
37082 var pi = stack.pop();
37083 var p = z1[pi];
37084
37085 if (exports.DEBUG) {
37086 console.log(
37087 state.step,
37088 (state.loop > 1 ? 'loop ' + (state.loop - loop) + ': ' : '') +
37089 'ALIGNRP[]',
37090 pi
37091 );
37092 }
37093
37094 fv.setRelative(p, rp0, 0, pv);
37095 fv.touch(p);
37096 }
37097
37098 state.loop = 1;
37099 }
37100
37101 // RTG[] Round To Double Grid
37102 // 0x3D
37103 function RTDG(state) {
37104 if (exports.DEBUG) {
37105 console.log(state.step, 'RTDG[]');
37106 }
37107
37108 state.round = roundToDoubleGrid;
37109 }
37110
37111 // MIAP[a] Move Indirect Absolute Point
37112 // 0x3E-0x3F
37113 function MIAP(round, state) {
37114 var stack = state.stack;
37115 var n = stack.pop();
37116 var pi = stack.pop();
37117 var p = state.z0[pi];
37118 var fv = state.fv;
37119 var pv = state.pv;
37120 var cv = state.cvt[n];
37121
37122 if (exports.DEBUG) {
37123 console.log(state.step, 'MIAP[' + round + ']', n, '(', cv, ')', pi);
37124 }
37125
37126 var d = pv.distance(p, HPZero);
37127
37128 if (round) {
37129 if (Math.abs(d - cv) < state.cvCutIn) {
37130 d = cv;
37131 }
37132
37133 d = state.round(d);
37134 }
37135
37136 fv.setRelative(p, HPZero, d, pv);
37137
37138 if (state.zp0 === 0) {
37139 p.xo = p.x;
37140 p.yo = p.y;
37141 }
37142
37143 fv.touch(p);
37144
37145 state.rp0 = state.rp1 = pi;
37146 }
37147
37148 // NPUSB[] PUSH N Bytes
37149 // 0x40
37150 function NPUSHB(state) {
37151 var prog = state.prog;
37152 var ip = state.ip;
37153 var stack = state.stack;
37154
37155 var n = prog[++ip];
37156
37157 if (exports.DEBUG) {
37158 console.log(state.step, 'NPUSHB[]', n);
37159 }
37160
37161 for (var i = 0; i < n; i++) {
37162 stack.push(prog[++ip]);
37163 }
37164
37165 state.ip = ip;
37166 }
37167
37168 // NPUSHW[] PUSH N Words
37169 // 0x41
37170 function NPUSHW(state) {
37171 var ip = state.ip;
37172 var prog = state.prog;
37173 var stack = state.stack;
37174 var n = prog[++ip];
37175
37176 if (exports.DEBUG) {
37177 console.log(state.step, 'NPUSHW[]', n);
37178 }
37179
37180 for (var i = 0; i < n; i++) {
37181 var w = (prog[++ip] << 8) | prog[++ip];
37182 if (w & 0x8000) {
37183 w = -((w ^ 0xffff) + 1);
37184 }
37185 stack.push(w);
37186 }
37187
37188 state.ip = ip;
37189 }
37190
37191 // WS[] Write Store
37192 // 0x42
37193 function WS(state) {
37194 var stack = state.stack;
37195 var store = state.store;
37196
37197 if (!store) {
37198 store = state.store = [];
37199 }
37200
37201 var v = stack.pop();
37202 var l = stack.pop();
37203
37204 if (exports.DEBUG) {
37205 console.log(state.step, 'WS', v, l);
37206 }
37207
37208 store[l] = v;
37209 }
37210
37211 // RS[] Read Store
37212 // 0x43
37213 function RS(state) {
37214 var stack = state.stack;
37215 var store = state.store;
37216
37217 var l = stack.pop();
37218
37219 if (exports.DEBUG) {
37220 console.log(state.step, 'RS', l);
37221 }
37222
37223 var v = (store && store[l]) || 0;
37224
37225 stack.push(v);
37226 }
37227
37228 // WCVTP[] Write Control Value Table in Pixel units
37229 // 0x44
37230 function WCVTP(state) {
37231 var stack = state.stack;
37232
37233 var v = stack.pop();
37234 var l = stack.pop();
37235
37236 if (exports.DEBUG) {
37237 console.log(state.step, 'WCVTP', v, l);
37238 }
37239
37240 state.cvt[l] = v / 0x40;
37241 }
37242
37243 // RCVT[] Read Control Value Table entry
37244 // 0x45
37245 function RCVT(state) {
37246 var stack = state.stack;
37247 var cvte = stack.pop();
37248
37249 if (exports.DEBUG) {
37250 console.log(state.step, 'RCVT', cvte);
37251 }
37252
37253 stack.push(state.cvt[cvte] * 0x40);
37254 }
37255
37256 // GC[] Get Coordinate projected onto the projection vector
37257 // 0x46-0x47
37258 function GC(a, state) {
37259 var stack = state.stack;
37260 var pi = stack.pop();
37261 var p = state.z2[pi];
37262
37263 if (exports.DEBUG) {
37264 console.log(state.step, 'GC[' + a + ']', pi);
37265 }
37266
37267 stack.push(state.dpv.distance(p, HPZero, a, false) * 0x40);
37268 }
37269
37270 // MD[a] Measure Distance
37271 // 0x49-0x4A
37272 function MD(a, state) {
37273 var stack = state.stack;
37274 var pi2 = stack.pop();
37275 var pi1 = stack.pop();
37276 var p2 = state.z1[pi2];
37277 var p1 = state.z0[pi1];
37278 var d = state.dpv.distance(p1, p2, a, a);
37279
37280 if (exports.DEBUG) {
37281 console.log(state.step, 'MD[' + a + ']', pi2, pi1, '->', d);
37282 }
37283
37284 state.stack.push(Math.round(d * 64));
37285 }
37286
37287 // MPPEM[] Measure Pixels Per EM
37288 // 0x4B
37289 function MPPEM(state) {
37290 if (exports.DEBUG) {
37291 console.log(state.step, 'MPPEM[]');
37292 }
37293 state.stack.push(state.ppem);
37294 }
37295
37296 // FLIPON[] set the auto FLIP Boolean to ON
37297 // 0x4D
37298 function FLIPON(state) {
37299 if (exports.DEBUG) {
37300 console.log(state.step, 'FLIPON[]');
37301 }
37302 state.autoFlip = true;
37303 }
37304
37305 // LT[] Less Than
37306 // 0x50
37307 function LT(state) {
37308 var stack = state.stack;
37309 var e2 = stack.pop();
37310 var e1 = stack.pop();
37311
37312 if (exports.DEBUG) {
37313 console.log(state.step, 'LT[]', e2, e1);
37314 }
37315
37316 stack.push(e1 < e2 ? 1 : 0);
37317 }
37318
37319 // LTEQ[] Less Than or EQual
37320 // 0x53
37321 function LTEQ(state) {
37322 var stack = state.stack;
37323 var e2 = stack.pop();
37324 var e1 = stack.pop();
37325
37326 if (exports.DEBUG) {
37327 console.log(state.step, 'LTEQ[]', e2, e1);
37328 }
37329
37330 stack.push(e1 <= e2 ? 1 : 0);
37331 }
37332
37333 // GTEQ[] Greater Than
37334 // 0x52
37335 function GT(state) {
37336 var stack = state.stack;
37337 var e2 = stack.pop();
37338 var e1 = stack.pop();
37339
37340 if (exports.DEBUG) {
37341 console.log(state.step, 'GT[]', e2, e1);
37342 }
37343
37344 stack.push(e1 > e2 ? 1 : 0);
37345 }
37346
37347 // GTEQ[] Greater Than or EQual
37348 // 0x53
37349 function GTEQ(state) {
37350 var stack = state.stack;
37351 var e2 = stack.pop();
37352 var e1 = stack.pop();
37353
37354 if (exports.DEBUG) {
37355 console.log(state.step, 'GTEQ[]', e2, e1);
37356 }
37357
37358 stack.push(e1 >= e2 ? 1 : 0);
37359 }
37360
37361 // EQ[] EQual
37362 // 0x54
37363 function EQ(state) {
37364 var stack = state.stack;
37365 var e2 = stack.pop();
37366 var e1 = stack.pop();
37367
37368 if (exports.DEBUG) {
37369 console.log(state.step, 'EQ[]', e2, e1);
37370 }
37371
37372 stack.push(e2 === e1 ? 1 : 0);
37373 }
37374
37375 // NEQ[] Not EQual
37376 // 0x55
37377 function NEQ(state) {
37378 var stack = state.stack;
37379 var e2 = stack.pop();
37380 var e1 = stack.pop();
37381
37382 if (exports.DEBUG) {
37383 console.log(state.step, 'NEQ[]', e2, e1);
37384 }
37385
37386 stack.push(e2 !== e1 ? 1 : 0);
37387 }
37388
37389 // ODD[] ODD
37390 // 0x56
37391 function ODD(state) {
37392 var stack = state.stack;
37393 var n = stack.pop();
37394
37395 if (exports.DEBUG) {
37396 console.log(state.step, 'ODD[]', n);
37397 }
37398
37399 stack.push(Math.trunc(n) % 2 ? 1 : 0);
37400 }
37401
37402 // EVEN[] EVEN
37403 // 0x57
37404 function EVEN(state) {
37405 var stack = state.stack;
37406 var n = stack.pop();
37407
37408 if (exports.DEBUG) {
37409 console.log(state.step, 'EVEN[]', n);
37410 }
37411
37412 stack.push(Math.trunc(n) % 2 ? 0 : 1);
37413 }
37414
37415 // IF[] IF test
37416 // 0x58
37417 function IF(state) {
37418 var test = state.stack.pop();
37419
37420 if (exports.DEBUG) {
37421 console.log(state.step, 'IF[]', test);
37422 }
37423
37424 // if test is true it just continues
37425 // if not the ip is skipped until matching ELSE or EIF
37426 if (!test) {
37427 skip(state, true);
37428
37429 if (exports.DEBUG) {
37430 console.log(state.step, 'EIF[]');
37431 }
37432 }
37433 }
37434
37435 // EIF[] End IF
37436 // 0x59
37437 function EIF(state) {
37438 // this can be reached normally when
37439 // executing an else branch.
37440 // -> just ignore it
37441
37442 if (exports.DEBUG) {
37443 console.log(state.step, 'EIF[]');
37444 }
37445 }
37446
37447 // AND[] logical AND
37448 // 0x5A
37449 function AND(state) {
37450 var stack = state.stack;
37451 var e2 = stack.pop();
37452 var e1 = stack.pop();
37453
37454 if (exports.DEBUG) {
37455 console.log(state.step, 'AND[]', e2, e1);
37456 }
37457
37458 stack.push(e2 && e1 ? 1 : 0);
37459 }
37460
37461 // OR[] logical OR
37462 // 0x5B
37463 function OR(state) {
37464 var stack = state.stack;
37465 var e2 = stack.pop();
37466 var e1 = stack.pop();
37467
37468 if (exports.DEBUG) {
37469 console.log(state.step, 'OR[]', e2, e1);
37470 }
37471
37472 stack.push(e2 || e1 ? 1 : 0);
37473 }
37474
37475 // NOT[] logical NOT
37476 // 0x5C
37477 function NOT(state) {
37478 var stack = state.stack;
37479 var e = stack.pop();
37480
37481 if (exports.DEBUG) {
37482 console.log(state.step, 'NOT[]', e);
37483 }
37484
37485 stack.push(e ? 0 : 1);
37486 }
37487
37488 // DELTAP1[] DELTA exception P1
37489 // DELTAP2[] DELTA exception P2
37490 // DELTAP3[] DELTA exception P3
37491 // 0x5D, 0x71, 0x72
37492 function DELTAP123(b, state) {
37493 var stack = state.stack;
37494 var n = stack.pop();
37495 var fv = state.fv;
37496 var pv = state.pv;
37497 var ppem = state.ppem;
37498 var base = state.deltaBase + (b - 1) * 16;
37499 var ds = state.deltaShift;
37500 var z0 = state.z0;
37501
37502 if (exports.DEBUG) {
37503 console.log(state.step, 'DELTAP[' + b + ']', n, stack);
37504 }
37505
37506 for (var i = 0; i < n; i++) {
37507 var pi = stack.pop();
37508 var arg = stack.pop();
37509 var appem = base + ((arg & 0xf0) >> 4);
37510 if (appem !== ppem) {
37511 continue;
37512 }
37513
37514 var mag = (arg & 0x0f) - 8;
37515 if (mag >= 0) {
37516 mag++;
37517 }
37518 if (exports.DEBUG) {
37519 console.log(state.step, 'DELTAPFIX', pi, 'by', mag * ds);
37520 }
37521
37522 var p = z0[pi];
37523 fv.setRelative(p, p, mag * ds, pv);
37524 }
37525 }
37526
37527 // SDB[] Set Delta Base in the graphics state
37528 // 0x5E
37529 function SDB(state) {
37530 var stack = state.stack;
37531 var n = stack.pop();
37532
37533 if (exports.DEBUG) {
37534 console.log(state.step, 'SDB[]', n);
37535 }
37536
37537 state.deltaBase = n;
37538 }
37539
37540 // SDS[] Set Delta Shift in the graphics state
37541 // 0x5F
37542 function SDS(state) {
37543 var stack = state.stack;
37544 var n = stack.pop();
37545
37546 if (exports.DEBUG) {
37547 console.log(state.step, 'SDS[]', n);
37548 }
37549
37550 state.deltaShift = Math.pow(0.5, n);
37551 }
37552
37553 // ADD[] ADD
37554 // 0x60
37555 function ADD(state) {
37556 var stack = state.stack;
37557 var n2 = stack.pop();
37558 var n1 = stack.pop();
37559
37560 if (exports.DEBUG) {
37561 console.log(state.step, 'ADD[]', n2, n1);
37562 }
37563
37564 stack.push(n1 + n2);
37565 }
37566
37567 // SUB[] SUB
37568 // 0x61
37569 function SUB(state) {
37570 var stack = state.stack;
37571 var n2 = stack.pop();
37572 var n1 = stack.pop();
37573
37574 if (exports.DEBUG) {
37575 console.log(state.step, 'SUB[]', n2, n1);
37576 }
37577
37578 stack.push(n1 - n2);
37579 }
37580
37581 // DIV[] DIV
37582 // 0x62
37583 function DIV(state) {
37584 var stack = state.stack;
37585 var n2 = stack.pop();
37586 var n1 = stack.pop();
37587
37588 if (exports.DEBUG) {
37589 console.log(state.step, 'DIV[]', n2, n1);
37590 }
37591
37592 stack.push(n1 * 64 / n2);
37593 }
37594
37595 // MUL[] MUL
37596 // 0x63
37597 function MUL(state) {
37598 var stack = state.stack;
37599 var n2 = stack.pop();
37600 var n1 = stack.pop();
37601
37602 if (exports.DEBUG) {
37603 console.log(state.step, 'MUL[]', n2, n1);
37604 }
37605
37606 stack.push(n1 * n2 / 64);
37607 }
37608
37609 // ABS[] ABSolute value
37610 // 0x64
37611 function ABS(state) {
37612 var stack = state.stack;
37613 var n = stack.pop();
37614
37615 if (exports.DEBUG) {
37616 console.log(state.step, 'ABS[]', n);
37617 }
37618
37619 stack.push(Math.abs(n));
37620 }
37621
37622 // NEG[] NEGate
37623 // 0x65
37624 function NEG(state) {
37625 var stack = state.stack;
37626 var n = stack.pop();
37627
37628 if (exports.DEBUG) {
37629 console.log(state.step, 'NEG[]', n);
37630 }
37631
37632 stack.push(-n);
37633 }
37634
37635 // FLOOR[] FLOOR
37636 // 0x66
37637 function FLOOR(state) {
37638 var stack = state.stack;
37639 var n = stack.pop();
37640
37641 if (exports.DEBUG) {
37642 console.log(state.step, 'FLOOR[]', n);
37643 }
37644
37645 stack.push(Math.floor(n / 0x40) * 0x40);
37646 }
37647
37648 // CEILING[] CEILING
37649 // 0x67
37650 function CEILING(state) {
37651 var stack = state.stack;
37652 var n = stack.pop();
37653
37654 if (exports.DEBUG) {
37655 console.log(state.step, 'CEILING[]', n);
37656 }
37657
37658 stack.push(Math.ceil(n / 0x40) * 0x40);
37659 }
37660
37661 // ROUND[ab] ROUND value
37662 // 0x68-0x6B
37663 function ROUND(dt, state) {
37664 var stack = state.stack;
37665 var n = stack.pop();
37666
37667 if (exports.DEBUG) {
37668 console.log(state.step, 'ROUND[]');
37669 }
37670
37671 stack.push(state.round(n / 0x40) * 0x40);
37672 }
37673
37674 // WCVTF[] Write Control Value Table in Funits
37675 // 0x70
37676 function WCVTF(state) {
37677 var stack = state.stack;
37678 var v = stack.pop();
37679 var l = stack.pop();
37680
37681 if (exports.DEBUG) {
37682 console.log(state.step, 'WCVTF[]', v, l);
37683 }
37684
37685 state.cvt[l] = v * state.ppem / state.font.unitsPerEm;
37686 }
37687
37688 // DELTAC1[] DELTA exception C1
37689 // DELTAC2[] DELTA exception C2
37690 // DELTAC3[] DELTA exception C3
37691 // 0x73, 0x74, 0x75
37692 function DELTAC123(b, state) {
37693 var stack = state.stack;
37694 var n = stack.pop();
37695 var ppem = state.ppem;
37696 var base = state.deltaBase + (b - 1) * 16;
37697 var ds = state.deltaShift;
37698
37699 if (exports.DEBUG) {
37700 console.log(state.step, 'DELTAC[' + b + ']', n, stack);
37701 }
37702
37703 for (var i = 0; i < n; i++) {
37704 var c = stack.pop();
37705 var arg = stack.pop();
37706 var appem = base + ((arg & 0xf0) >> 4);
37707 if (appem !== ppem) {
37708 continue;
37709 }
37710
37711 var mag = (arg & 0x0f) - 8;
37712 if (mag >= 0) {
37713 mag++;
37714 }
37715
37716 var delta = mag * ds;
37717
37718 if (exports.DEBUG) {
37719 console.log(state.step, 'DELTACFIX', c, 'by', delta);
37720 }
37721
37722 state.cvt[c] += delta;
37723 }
37724 }
37725
37726 // SROUND[] Super ROUND
37727 // 0x76
37728 function SROUND(state) {
37729 var n = state.stack.pop();
37730
37731 if (exports.DEBUG) {
37732 console.log(state.step, 'SROUND[]', n);
37733 }
37734
37735 state.round = roundSuper;
37736
37737 var period;
37738
37739 switch (n & 0xc0) {
37740 case 0x00:
37741 period = 0.5;
37742 break;
37743 case 0x40:
37744 period = 1;
37745 break;
37746 case 0x80:
37747 period = 2;
37748 break;
37749 default:
37750 throw new Error('invalid SROUND value');
37751 }
37752
37753 state.srPeriod = period;
37754
37755 switch (n & 0x30) {
37756 case 0x00:
37757 state.srPhase = 0;
37758 break;
37759 case 0x10:
37760 state.srPhase = 0.25 * period;
37761 break;
37762 case 0x20:
37763 state.srPhase = 0.5 * period;
37764 break;
37765 case 0x30:
37766 state.srPhase = 0.75 * period;
37767 break;
37768 default:
37769 throw new Error('invalid SROUND value');
37770 }
37771
37772 n &= 0x0f;
37773
37774 if (n === 0) {
37775 state.srThreshold = 0;
37776 } else {
37777 state.srThreshold = (n / 8 - 0.5) * period;
37778 }
37779 }
37780
37781 // S45ROUND[] Super ROUND 45 degrees
37782 // 0x77
37783 function S45ROUND(state) {
37784 var n = state.stack.pop();
37785
37786 if (exports.DEBUG) {
37787 console.log(state.step, 'S45ROUND[]', n);
37788 }
37789
37790 state.round = roundSuper;
37791
37792 var period;
37793
37794 switch (n & 0xc0) {
37795 case 0x00:
37796 period = Math.sqrt(2) / 2;
37797 break;
37798 case 0x40:
37799 period = Math.sqrt(2);
37800 break;
37801 case 0x80:
37802 period = 2 * Math.sqrt(2);
37803 break;
37804 default:
37805 throw new Error('invalid S45ROUND value');
37806 }
37807
37808 state.srPeriod = period;
37809
37810 switch (n & 0x30) {
37811 case 0x00:
37812 state.srPhase = 0;
37813 break;
37814 case 0x10:
37815 state.srPhase = 0.25 * period;
37816 break;
37817 case 0x20:
37818 state.srPhase = 0.5 * period;
37819 break;
37820 case 0x30:
37821 state.srPhase = 0.75 * period;
37822 break;
37823 default:
37824 throw new Error('invalid S45ROUND value');
37825 }
37826
37827 n &= 0x0f;
37828
37829 if (n === 0) {
37830 state.srThreshold = 0;
37831 } else {
37832 state.srThreshold = (n / 8 - 0.5) * period;
37833 }
37834 }
37835
37836 // ROFF[] Round Off
37837 // 0x7A
37838 function ROFF(state) {
37839 if (exports.DEBUG) {
37840 console.log(state.step, 'ROFF[]');
37841 }
37842
37843 state.round = roundOff;
37844 }
37845
37846 // RUTG[] Round Up To Grid
37847 // 0x7C
37848 function RUTG(state) {
37849 if (exports.DEBUG) {
37850 console.log(state.step, 'RUTG[]');
37851 }
37852
37853 state.round = roundUpToGrid;
37854 }
37855
37856 // RDTG[] Round Down To Grid
37857 // 0x7D
37858 function RDTG(state) {
37859 if (exports.DEBUG) {
37860 console.log(state.step, 'RDTG[]');
37861 }
37862
37863 state.round = roundDownToGrid;
37864 }
37865
37866 // SCANCTRL[] SCAN conversion ConTRoL
37867 // 0x85
37868 function SCANCTRL(state) {
37869 var n = state.stack.pop();
37870
37871 // ignored by opentype.js
37872
37873 if (exports.DEBUG) {
37874 console.log(state.step, 'SCANCTRL[]', n);
37875 }
37876 }
37877
37878 // SDPVTL[a] Set Dual Projection Vector To Line
37879 // 0x86-0x87
37880 function SDPVTL(a, state) {
37881 var stack = state.stack;
37882 var p2i = stack.pop();
37883 var p1i = stack.pop();
37884 var p2 = state.z2[p2i];
37885 var p1 = state.z1[p1i];
37886
37887 if (exports.DEBUG) {
37888 console.log(state.step, 'SDPVTL[' + a + ']', p2i, p1i);
37889 }
37890
37891 var dx;
37892 var dy;
37893
37894 if (!a) {
37895 dx = p1.x - p2.x;
37896 dy = p1.y - p2.y;
37897 } else {
37898 dx = p2.y - p1.y;
37899 dy = p1.x - p2.x;
37900 }
37901
37902 state.dpv = getUnitVector(dx, dy);
37903 }
37904
37905 // GETINFO[] GET INFOrmation
37906 // 0x88
37907 function GETINFO(state) {
37908 var stack = state.stack;
37909 var sel = stack.pop();
37910 var r = 0;
37911
37912 if (exports.DEBUG) {
37913 console.log(state.step, 'GETINFO[]', sel);
37914 }
37915
37916 // v35 as in no subpixel hinting
37917 if (sel & 0x01) {
37918 r = 35;
37919 }
37920
37921 // TODO rotation and stretch currently not supported
37922 // and thus those GETINFO are always 0.
37923
37924 // opentype.js is always gray scaling
37925 if (sel & 0x20) {
37926 r |= 0x1000;
37927 }
37928
37929 stack.push(r);
37930 }
37931
37932 // ROLL[] ROLL the top three stack elements
37933 // 0x8A
37934 function ROLL(state) {
37935 var stack = state.stack;
37936 var a = stack.pop();
37937 var b = stack.pop();
37938 var c = stack.pop();
37939
37940 if (exports.DEBUG) {
37941 console.log(state.step, 'ROLL[]');
37942 }
37943
37944 stack.push(b);
37945 stack.push(a);
37946 stack.push(c);
37947 }
37948
37949 // MAX[] MAXimum of top two stack elements
37950 // 0x8B
37951 function MAX(state) {
37952 var stack = state.stack;
37953 var e2 = stack.pop();
37954 var e1 = stack.pop();
37955
37956 if (exports.DEBUG) {
37957 console.log(state.step, 'MAX[]', e2, e1);
37958 }
37959
37960 stack.push(Math.max(e1, e2));
37961 }
37962
37963 // MIN[] MINimum of top two stack elements
37964 // 0x8C
37965 function MIN(state) {
37966 var stack = state.stack;
37967 var e2 = stack.pop();
37968 var e1 = stack.pop();
37969
37970 if (exports.DEBUG) {
37971 console.log(state.step, 'MIN[]', e2, e1);
37972 }
37973
37974 stack.push(Math.min(e1, e2));
37975 }
37976
37977 // SCANTYPE[] SCANTYPE
37978 // 0x8D
37979 function SCANTYPE(state) {
37980 var n = state.stack.pop();
37981 // ignored by opentype.js
37982 if (exports.DEBUG) {
37983 console.log(state.step, 'SCANTYPE[]', n);
37984 }
37985 }
37986
37987 // INSTCTRL[] INSTCTRL
37988 // 0x8D
37989 function INSTCTRL(state) {
37990 var s = state.stack.pop();
37991 var v = state.stack.pop();
37992
37993 if (exports.DEBUG) {
37994 console.log(state.step, 'INSTCTRL[]', s, v);
37995 }
37996
37997 switch (s) {
37998 case 1:
37999 state.inhibitGridFit = !!v;
38000 return;
38001 case 2:
38002 state.ignoreCvt = !!v;
38003 return;
38004 default:
38005 throw new Error('invalid INSTCTRL[] selector');
38006 }
38007 }
38008
38009 // PUSHB[abc] PUSH Bytes
38010 // 0xB0-0xB7
38011 function PUSHB(n, state) {
38012 var stack = state.stack;
38013 var prog = state.prog;
38014 var ip = state.ip;
38015
38016 if (exports.DEBUG) {
38017 console.log(state.step, 'PUSHB[' + n + ']');
38018 }
38019
38020 for (var i = 0; i < n; i++) {
38021 stack.push(prog[++ip]);
38022 }
38023
38024 state.ip = ip;
38025 }
38026
38027 // PUSHW[abc] PUSH Words
38028 // 0xB8-0xBF
38029 function PUSHW(n, state) {
38030 var ip = state.ip;
38031 var prog = state.prog;
38032 var stack = state.stack;
38033
38034 if (exports.DEBUG) {
38035 console.log(state.ip, 'PUSHW[' + n + ']');
38036 }
38037
38038 for (var i = 0; i < n; i++) {
38039 var w = (prog[++ip] << 8) | prog[++ip];
38040 if (w & 0x8000) {
38041 w = -((w ^ 0xffff) + 1);
38042 }
38043 stack.push(w);
38044 }
38045
38046 state.ip = ip;
38047 }
38048
38049 // MDRP[abcde] Move Direct Relative Point
38050 // 0xD0-0xEF
38051 // (if indirect is 0)
38052 //
38053 // and
38054 //
38055 // MIRP[abcde] Move Indirect Relative Point
38056 // 0xE0-0xFF
38057 // (if indirect is 1)
38058
38059 function MDRP_MIRP(indirect, setRp0, keepD, ro, dt, state) {
38060 var stack = state.stack;
38061 var cvte = indirect && stack.pop();
38062 var pi = stack.pop();
38063 var rp0i = state.rp0;
38064 var rp = state.z0[rp0i];
38065 var p = state.z1[pi];
38066
38067 var md = state.minDis;
38068 var fv = state.fv;
38069 var pv = state.dpv;
38070 var od; // original distance
38071 var d; // moving distance
38072 var sign; // sign of distance
38073 var cv;
38074
38075 d = od = pv.distance(p, rp, true, true);
38076 sign = d >= 0 ? 1 : -1; // Math.sign would be 0 in case of 0
38077
38078 // TODO consider autoFlip
38079 d = Math.abs(d);
38080
38081 if (indirect) {
38082 cv = state.cvt[cvte];
38083
38084 if (ro && Math.abs(d - cv) < state.cvCutIn) {
38085 d = cv;
38086 }
38087 }
38088
38089 if (keepD && d < md) {
38090 d = md;
38091 }
38092
38093 if (ro) {
38094 d = state.round(d);
38095 }
38096
38097 fv.setRelative(p, rp, sign * d, pv);
38098 fv.touch(p);
38099
38100 if (exports.DEBUG) {
38101 console.log(
38102 state.step,
38103 (indirect ? 'MIRP[' : 'MDRP[') +
38104 (setRp0 ? 'M' : 'm') +
38105 (keepD ? '>' : '_') +
38106 (ro ? 'R' : '_') +
38107 (dt === 0 ? 'Gr' : dt === 1 ? 'Bl' : dt === 2 ? 'Wh' : '') +
38108 ']',
38109 indirect ? cvte + '(' + state.cvt[cvte] + ',' + cv + ')' : '',
38110 pi,
38111 '(d =',
38112 od,
38113 '->',
38114 sign * d,
38115 ')'
38116 );
38117 }
38118
38119 state.rp1 = state.rp0;
38120 state.rp2 = pi;
38121 if (setRp0) {
38122 state.rp0 = pi;
38123 }
38124 }
38125
38126 /*
38127 * The instruction table.
38128 */
38129 instructionTable = [
38130 /* 0x00 */ SVTCA.bind(undefined, yUnitVector),
38131 /* 0x01 */ SVTCA.bind(undefined, xUnitVector),
38132 /* 0x02 */ SPVTCA.bind(undefined, yUnitVector),
38133 /* 0x03 */ SPVTCA.bind(undefined, xUnitVector),
38134 /* 0x04 */ SFVTCA.bind(undefined, yUnitVector),
38135 /* 0x05 */ SFVTCA.bind(undefined, xUnitVector),
38136 /* 0x06 */ SPVTL.bind(undefined, 0),
38137 /* 0x07 */ SPVTL.bind(undefined, 1),
38138 /* 0x08 */ SFVTL.bind(undefined, 0),
38139 /* 0x09 */ SFVTL.bind(undefined, 1),
38140 /* 0x0A */ SPVFS,
38141 /* 0x0B */ SFVFS,
38142 /* 0x0C */ GPV,
38143 /* 0x0D */ GFV,
38144 /* 0x0E */ SFVTPV,
38145 /* 0x0F */ ISECT,
38146 /* 0x10 */ SRP0,
38147 /* 0x11 */ SRP1,
38148 /* 0x12 */ SRP2,
38149 /* 0x13 */ SZP0,
38150 /* 0x14 */ SZP1,
38151 /* 0x15 */ SZP2,
38152 /* 0x16 */ SZPS,
38153 /* 0x17 */ SLOOP,
38154 /* 0x18 */ RTG,
38155 /* 0x19 */ RTHG,
38156 /* 0x1A */ SMD,
38157 /* 0x1B */ ELSE,
38158 /* 0x1C */ JMPR,
38159 /* 0x1D */ SCVTCI,
38160 /* 0x1E */ undefined, // TODO SSWCI
38161 /* 0x1F */ undefined, // TODO SSW
38162 /* 0x20 */ DUP,
38163 /* 0x21 */ POP,
38164 /* 0x22 */ CLEAR,
38165 /* 0x23 */ SWAP,
38166 /* 0x24 */ DEPTH,
38167 /* 0x25 */ CINDEX,
38168 /* 0x26 */ MINDEX,
38169 /* 0x27 */ undefined, // TODO ALIGNPTS
38170 /* 0x28 */ undefined,
38171 /* 0x29 */ undefined, // TODO UTP
38172 /* 0x2A */ LOOPCALL,
38173 /* 0x2B */ CALL,
38174 /* 0x2C */ FDEF,
38175 /* 0x2D */ undefined, // ENDF (eaten by FDEF)
38176 /* 0x2E */ MDAP.bind(undefined, 0),
38177 /* 0x2F */ MDAP.bind(undefined, 1),
38178 /* 0x30 */ IUP.bind(undefined, yUnitVector),
38179 /* 0x31 */ IUP.bind(undefined, xUnitVector),
38180 /* 0x32 */ SHP.bind(undefined, 0),
38181 /* 0x33 */ SHP.bind(undefined, 1),
38182 /* 0x34 */ SHC.bind(undefined, 0),
38183 /* 0x35 */ SHC.bind(undefined, 1),
38184 /* 0x36 */ SHZ.bind(undefined, 0),
38185 /* 0x37 */ SHZ.bind(undefined, 1),
38186 /* 0x38 */ SHPIX,
38187 /* 0x39 */ IP,
38188 /* 0x3A */ MSIRP.bind(undefined, 0),
38189 /* 0x3B */ MSIRP.bind(undefined, 1),
38190 /* 0x3C */ ALIGNRP,
38191 /* 0x3D */ RTDG,
38192 /* 0x3E */ MIAP.bind(undefined, 0),
38193 /* 0x3F */ MIAP.bind(undefined, 1),
38194 /* 0x40 */ NPUSHB,
38195 /* 0x41 */ NPUSHW,
38196 /* 0x42 */ WS,
38197 /* 0x43 */ RS,
38198 /* 0x44 */ WCVTP,
38199 /* 0x45 */ RCVT,
38200 /* 0x46 */ GC.bind(undefined, 0),
38201 /* 0x47 */ GC.bind(undefined, 1),
38202 /* 0x48 */ undefined, // TODO SCFS
38203 /* 0x49 */ MD.bind(undefined, 0),
38204 /* 0x4A */ MD.bind(undefined, 1),
38205 /* 0x4B */ MPPEM,
38206 /* 0x4C */ undefined, // TODO MPS
38207 /* 0x4D */ FLIPON,
38208 /* 0x4E */ undefined, // TODO FLIPOFF
38209 /* 0x4F */ undefined, // TODO DEBUG
38210 /* 0x50 */ LT,
38211 /* 0x51 */ LTEQ,
38212 /* 0x52 */ GT,
38213 /* 0x53 */ GTEQ,
38214 /* 0x54 */ EQ,
38215 /* 0x55 */ NEQ,
38216 /* 0x56 */ ODD,
38217 /* 0x57 */ EVEN,
38218 /* 0x58 */ IF,
38219 /* 0x59 */ EIF,
38220 /* 0x5A */ AND,
38221 /* 0x5B */ OR,
38222 /* 0x5C */ NOT,
38223 /* 0x5D */ DELTAP123.bind(undefined, 1),
38224 /* 0x5E */ SDB,
38225 /* 0x5F */ SDS,
38226 /* 0x60 */ ADD,
38227 /* 0x61 */ SUB,
38228 /* 0x62 */ DIV,
38229 /* 0x63 */ MUL,
38230 /* 0x64 */ ABS,
38231 /* 0x65 */ NEG,
38232 /* 0x66 */ FLOOR,
38233 /* 0x67 */ CEILING,
38234 /* 0x68 */ ROUND.bind(undefined, 0),
38235 /* 0x69 */ ROUND.bind(undefined, 1),
38236 /* 0x6A */ ROUND.bind(undefined, 2),
38237 /* 0x6B */ ROUND.bind(undefined, 3),
38238 /* 0x6C */ undefined, // TODO NROUND[ab]
38239 /* 0x6D */ undefined, // TODO NROUND[ab]
38240 /* 0x6E */ undefined, // TODO NROUND[ab]
38241 /* 0x6F */ undefined, // TODO NROUND[ab]
38242 /* 0x70 */ WCVTF,
38243 /* 0x71 */ DELTAP123.bind(undefined, 2),
38244 /* 0x72 */ DELTAP123.bind(undefined, 3),
38245 /* 0x73 */ DELTAC123.bind(undefined, 1),
38246 /* 0x74 */ DELTAC123.bind(undefined, 2),
38247 /* 0x75 */ DELTAC123.bind(undefined, 3),
38248 /* 0x76 */ SROUND,
38249 /* 0x77 */ S45ROUND,
38250 /* 0x78 */ undefined, // TODO JROT[]
38251 /* 0x79 */ undefined, // TODO JROF[]
38252 /* 0x7A */ ROFF,
38253 /* 0x7B */ undefined,
38254 /* 0x7C */ RUTG,
38255 /* 0x7D */ RDTG,
38256 /* 0x7E */ POP, // actually SANGW, supposed to do only a pop though
38257 /* 0x7F */ POP, // actually AA, supposed to do only a pop though
38258 /* 0x80 */ undefined, // TODO FLIPPT
38259 /* 0x81 */ undefined, // TODO FLIPRGON
38260 /* 0x82 */ undefined, // TODO FLIPRGOFF
38261 /* 0x83 */ undefined,
38262 /* 0x84 */ undefined,
38263 /* 0x85 */ SCANCTRL,
38264 /* 0x86 */ SDPVTL.bind(undefined, 0),
38265 /* 0x87 */ SDPVTL.bind(undefined, 1),
38266 /* 0x88 */ GETINFO,
38267 /* 0x89 */ undefined, // TODO IDEF
38268 /* 0x8A */ ROLL,
38269 /* 0x8B */ MAX,
38270 /* 0x8C */ MIN,
38271 /* 0x8D */ SCANTYPE,
38272 /* 0x8E */ INSTCTRL,
38273 /* 0x8F */ undefined,
38274 /* 0x90 */ undefined,
38275 /* 0x91 */ undefined,
38276 /* 0x92 */ undefined,
38277 /* 0x93 */ undefined,
38278 /* 0x94 */ undefined,
38279 /* 0x95 */ undefined,
38280 /* 0x96 */ undefined,
38281 /* 0x97 */ undefined,
38282 /* 0x98 */ undefined,
38283 /* 0x99 */ undefined,
38284 /* 0x9A */ undefined,
38285 /* 0x9B */ undefined,
38286 /* 0x9C */ undefined,
38287 /* 0x9D */ undefined,
38288 /* 0x9E */ undefined,
38289 /* 0x9F */ undefined,
38290 /* 0xA0 */ undefined,
38291 /* 0xA1 */ undefined,
38292 /* 0xA2 */ undefined,
38293 /* 0xA3 */ undefined,
38294 /* 0xA4 */ undefined,
38295 /* 0xA5 */ undefined,
38296 /* 0xA6 */ undefined,
38297 /* 0xA7 */ undefined,
38298 /* 0xA8 */ undefined,
38299 /* 0xA9 */ undefined,
38300 /* 0xAA */ undefined,
38301 /* 0xAB */ undefined,
38302 /* 0xAC */ undefined,
38303 /* 0xAD */ undefined,
38304 /* 0xAE */ undefined,
38305 /* 0xAF */ undefined,
38306 /* 0xB0 */ PUSHB.bind(undefined, 1),
38307 /* 0xB1 */ PUSHB.bind(undefined, 2),
38308 /* 0xB2 */ PUSHB.bind(undefined, 3),
38309 /* 0xB3 */ PUSHB.bind(undefined, 4),
38310 /* 0xB4 */ PUSHB.bind(undefined, 5),
38311 /* 0xB5 */ PUSHB.bind(undefined, 6),
38312 /* 0xB6 */ PUSHB.bind(undefined, 7),
38313 /* 0xB7 */ PUSHB.bind(undefined, 8),
38314 /* 0xB8 */ PUSHW.bind(undefined, 1),
38315 /* 0xB9 */ PUSHW.bind(undefined, 2),
38316 /* 0xBA */ PUSHW.bind(undefined, 3),
38317 /* 0xBB */ PUSHW.bind(undefined, 4),
38318 /* 0xBC */ PUSHW.bind(undefined, 5),
38319 /* 0xBD */ PUSHW.bind(undefined, 6),
38320 /* 0xBE */ PUSHW.bind(undefined, 7),
38321 /* 0xBF */ PUSHW.bind(undefined, 8),
38322 /* 0xC0 */ MDRP_MIRP.bind(undefined, 0, 0, 0, 0, 0),
38323 /* 0xC1 */ MDRP_MIRP.bind(undefined, 0, 0, 0, 0, 1),
38324 /* 0xC2 */ MDRP_MIRP.bind(undefined, 0, 0, 0, 0, 2),
38325 /* 0xC3 */ MDRP_MIRP.bind(undefined, 0, 0, 0, 0, 3),
38326 /* 0xC4 */ MDRP_MIRP.bind(undefined, 0, 0, 0, 1, 0),
38327 /* 0xC5 */ MDRP_MIRP.bind(undefined, 0, 0, 0, 1, 1),
38328 /* 0xC6 */ MDRP_MIRP.bind(undefined, 0, 0, 0, 1, 2),
38329 /* 0xC7 */ MDRP_MIRP.bind(undefined, 0, 0, 0, 1, 3),
38330 /* 0xC8 */ MDRP_MIRP.bind(undefined, 0, 0, 1, 0, 0),
38331 /* 0xC9 */ MDRP_MIRP.bind(undefined, 0, 0, 1, 0, 1),
38332 /* 0xCA */ MDRP_MIRP.bind(undefined, 0, 0, 1, 0, 2),
38333 /* 0xCB */ MDRP_MIRP.bind(undefined, 0, 0, 1, 0, 3),
38334 /* 0xCC */ MDRP_MIRP.bind(undefined, 0, 0, 1, 1, 0),
38335 /* 0xCD */ MDRP_MIRP.bind(undefined, 0, 0, 1, 1, 1),
38336 /* 0xCE */ MDRP_MIRP.bind(undefined, 0, 0, 1, 1, 2),
38337 /* 0xCF */ MDRP_MIRP.bind(undefined, 0, 0, 1, 1, 3),
38338 /* 0xD0 */ MDRP_MIRP.bind(undefined, 0, 1, 0, 0, 0),
38339 /* 0xD1 */ MDRP_MIRP.bind(undefined, 0, 1, 0, 0, 1),
38340 /* 0xD2 */ MDRP_MIRP.bind(undefined, 0, 1, 0, 0, 2),
38341 /* 0xD3 */ MDRP_MIRP.bind(undefined, 0, 1, 0, 0, 3),
38342 /* 0xD4 */ MDRP_MIRP.bind(undefined, 0, 1, 0, 1, 0),
38343 /* 0xD5 */ MDRP_MIRP.bind(undefined, 0, 1, 0, 1, 1),
38344 /* 0xD6 */ MDRP_MIRP.bind(undefined, 0, 1, 0, 1, 2),
38345 /* 0xD7 */ MDRP_MIRP.bind(undefined, 0, 1, 0, 1, 3),
38346 /* 0xD8 */ MDRP_MIRP.bind(undefined, 0, 1, 1, 0, 0),
38347 /* 0xD9 */ MDRP_MIRP.bind(undefined, 0, 1, 1, 0, 1),
38348 /* 0xDA */ MDRP_MIRP.bind(undefined, 0, 1, 1, 0, 2),
38349 /* 0xDB */ MDRP_MIRP.bind(undefined, 0, 1, 1, 0, 3),
38350 /* 0xDC */ MDRP_MIRP.bind(undefined, 0, 1, 1, 1, 0),
38351 /* 0xDD */ MDRP_MIRP.bind(undefined, 0, 1, 1, 1, 1),
38352 /* 0xDE */ MDRP_MIRP.bind(undefined, 0, 1, 1, 1, 2),
38353 /* 0xDF */ MDRP_MIRP.bind(undefined, 0, 1, 1, 1, 3),
38354 /* 0xE0 */ MDRP_MIRP.bind(undefined, 1, 0, 0, 0, 0),
38355 /* 0xE1 */ MDRP_MIRP.bind(undefined, 1, 0, 0, 0, 1),
38356 /* 0xE2 */ MDRP_MIRP.bind(undefined, 1, 0, 0, 0, 2),
38357 /* 0xE3 */ MDRP_MIRP.bind(undefined, 1, 0, 0, 0, 3),
38358 /* 0xE4 */ MDRP_MIRP.bind(undefined, 1, 0, 0, 1, 0),
38359 /* 0xE5 */ MDRP_MIRP.bind(undefined, 1, 0, 0, 1, 1),
38360 /* 0xE6 */ MDRP_MIRP.bind(undefined, 1, 0, 0, 1, 2),
38361 /* 0xE7 */ MDRP_MIRP.bind(undefined, 1, 0, 0, 1, 3),
38362 /* 0xE8 */ MDRP_MIRP.bind(undefined, 1, 0, 1, 0, 0),
38363 /* 0xE9 */ MDRP_MIRP.bind(undefined, 1, 0, 1, 0, 1),
38364 /* 0xEA */ MDRP_MIRP.bind(undefined, 1, 0, 1, 0, 2),
38365 /* 0xEB */ MDRP_MIRP.bind(undefined, 1, 0, 1, 0, 3),
38366 /* 0xEC */ MDRP_MIRP.bind(undefined, 1, 0, 1, 1, 0),
38367 /* 0xED */ MDRP_MIRP.bind(undefined, 1, 0, 1, 1, 1),
38368 /* 0xEE */ MDRP_MIRP.bind(undefined, 1, 0, 1, 1, 2),
38369 /* 0xEF */ MDRP_MIRP.bind(undefined, 1, 0, 1, 1, 3),
38370 /* 0xF0 */ MDRP_MIRP.bind(undefined, 1, 1, 0, 0, 0),
38371 /* 0xF1 */ MDRP_MIRP.bind(undefined, 1, 1, 0, 0, 1),
38372 /* 0xF2 */ MDRP_MIRP.bind(undefined, 1, 1, 0, 0, 2),
38373 /* 0xF3 */ MDRP_MIRP.bind(undefined, 1, 1, 0, 0, 3),
38374 /* 0xF4 */ MDRP_MIRP.bind(undefined, 1, 1, 0, 1, 0),
38375 /* 0xF5 */ MDRP_MIRP.bind(undefined, 1, 1, 0, 1, 1),
38376 /* 0xF6 */ MDRP_MIRP.bind(undefined, 1, 1, 0, 1, 2),
38377 /* 0xF7 */ MDRP_MIRP.bind(undefined, 1, 1, 0, 1, 3),
38378 /* 0xF8 */ MDRP_MIRP.bind(undefined, 1, 1, 1, 0, 0),
38379 /* 0xF9 */ MDRP_MIRP.bind(undefined, 1, 1, 1, 0, 1),
38380 /* 0xFA */ MDRP_MIRP.bind(undefined, 1, 1, 1, 0, 2),
38381 /* 0xFB */ MDRP_MIRP.bind(undefined, 1, 1, 1, 0, 3),
38382 /* 0xFC */ MDRP_MIRP.bind(undefined, 1, 1, 1, 1, 0),
38383 /* 0xFD */ MDRP_MIRP.bind(undefined, 1, 1, 1, 1, 1),
38384 /* 0xFE */ MDRP_MIRP.bind(undefined, 1, 1, 1, 1, 2),
38385 /* 0xFF */ MDRP_MIRP.bind(undefined, 1, 1, 1, 1, 3)
38386 ];
38387
38388 /*****************************
38389 Mathematical Considerations
38390 ******************************
38391
38392 fv ... refers to freedom vector
38393 pv ... refers to projection vector
38394 rp ... refers to reference point
38395 p ... refers to to point being operated on
38396 d ... refers to distance
38397
38398 SETRELATIVE:
38399 ============
38400
38401 case freedom vector == x-axis:
38402 ------------------------------
38403
38404 (pv)
38405 .-'
38406 rpd .-'
38407 .-*
38408 d .-'90°'
38409 .-' '
38410 .-' '
38411 *-' ' b
38412 rp '
38413 '
38414 '
38415 p *----------*-------------- (fv)
38416 pm
38417
38418 rpdx = rpx + d * pv.x
38419 rpdy = rpy + d * pv.y
38420
38421 equation of line b
38422
38423 y - rpdy = pvns * (x- rpdx)
38424
38425 y = p.y
38426
38427 x = rpdx + ( p.y - rpdy ) / pvns
38428
38429
38430 case freedom vector == y-axis:
38431 ------------------------------
38432
38433 * pm
38434 |\
38435 | \
38436 | \
38437 | \
38438 | \
38439 | \
38440 | \
38441 | \
38442 | \
38443 | \ b
38444 | \
38445 | \
38446 | \ .-' (pv)
38447 | 90° \.-'
38448 | .-'* rpd
38449 | .-'
38450 * *-' d
38451 p rp
38452
38453 rpdx = rpx + d * pv.x
38454 rpdy = rpy + d * pv.y
38455
38456 equation of line b:
38457 pvns ... normal slope to pv
38458
38459 y - rpdy = pvns * (x - rpdx)
38460
38461 x = p.x
38462
38463 y = rpdy + pvns * (p.x - rpdx)
38464
38465
38466
38467 generic case:
38468 -------------
38469
38470
38471 .'(fv)
38472 .'
38473 .* pm
38474 .' !
38475 .' .
38476 .' !
38477 .' . b
38478 .' !
38479 * .
38480 p !
38481 90° . ... (pv)
38482 ...-*-'''
38483 ...---''' rpd
38484 ...---''' d
38485 *--'''
38486 rp
38487
38488 rpdx = rpx + d * pv.x
38489 rpdy = rpy + d * pv.y
38490
38491 equation of line b:
38492 pvns... normal slope to pv
38493
38494 y - rpdy = pvns * (x - rpdx)
38495
38496 equation of freedom vector line:
38497 fvs ... slope of freedom vector (=fy/fx)
38498
38499 y - py = fvs * (x - px)
38500
38501
38502 on pm both equations are true for same x/y
38503
38504 y - rpdy = pvns * (x - rpdx)
38505
38506 y - py = fvs * (x - px)
38507
38508 form to y and set equal:
38509
38510 pvns * (x - rpdx) + rpdy = fvs * (x - px) + py
38511
38512 expand:
38513
38514 pvns * x - pvns * rpdx + rpdy = fvs * x - fvs * px + py
38515
38516 switch:
38517
38518 fvs * x - fvs * px + py = pvns * x - pvns * rpdx + rpdy
38519
38520 solve for x:
38521
38522 fvs * x - pvns * x = fvs * px - pvns * rpdx - py + rpdy
38523
38524
38525
38526 fvs * px - pvns * rpdx + rpdy - py
38527 x = -----------------------------------
38528 fvs - pvns
38529
38530 and:
38531
38532 y = fvs * (x - px) + py
38533
38534
38535
38536 INTERPOLATE:
38537 ============
38538
38539 Examples of point interpolation.
38540
38541 The weight of the movement of the reference point gets bigger
38542 the further the other reference point is away, thus the safest
38543 option (that is avoiding 0/0 divisions) is to weight the
38544 original distance of the other point by the sum of both distances.
38545
38546 If the sum of both distances is 0, then move the point by the
38547 arithmetic average of the movement of both reference points.
38548
38549
38550
38551
38552 (+6)
38553 rp1o *---->*rp1
38554 . . (+12)
38555 . . rp2o *---------->* rp2
38556 . . . .
38557 . . . .
38558 . 10 20 . .
38559 |.........|...................| .
38560 . . .
38561 . . (+8) .
38562 po *------>*p .
38563 . . .
38564 . 12 . 24 .
38565 |...........|.......................|
38566 36
38567
38568
38569 -------
38570
38571
38572
38573 (+10)
38574 rp1o *-------->*rp1
38575 . . (-10)
38576 . . rp2 *<---------* rpo2
38577 . . . .
38578 . . . .
38579 . 10 . 30 . .
38580 |.........|.............................|
38581 . .
38582 . (+5) .
38583 po *--->* p .
38584 . . .
38585 . . 20 .
38586 |....|..............|
38587 5 15
38588
38589
38590 -------
38591
38592
38593 (+10)
38594 rp1o *-------->*rp1
38595 . .
38596 . .
38597 rp2o *-------->*rp2
38598
38599
38600 (+10)
38601 po *-------->* p
38602
38603 -------
38604
38605
38606 (+10)
38607 rp1o *-------->*rp1
38608 . .
38609 . .(+30)
38610 rp2o *---------------------------->*rp2
38611
38612
38613 (+25)
38614 po *----------------------->* p
38615
38616
38617
38618 vim: set ts=4 sw=4 expandtab:
38619 *****/
38620
38621 // The Font object
38622
38623 // This code is based on Array.from implementation for strings in https://github.com/mathiasbynens/Array.from
38624 var arrayFromString =
38625 Array.from ||
38626 function(s) {
38627 return (
38628 s.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]?|[^\uD800-\uDFFF]|./g) || []
38629 );
38630 };
38631
38632 /**
38633 * @typedef FontOptions
38634 * @type Object
38635 * @property {Boolean} empty - whether to create a new empty font
38636 * @property {string} familyName
38637 * @property {string} styleName
38638 * @property {string=} fullName
38639 * @property {string=} postScriptName
38640 * @property {string=} designer
38641 * @property {string=} designerURL
38642 * @property {string=} manufacturer
38643 * @property {string=} manufacturerURL
38644 * @property {string=} license
38645 * @property {string=} licenseURL
38646 * @property {string=} version
38647 * @property {string=} description
38648 * @property {string=} copyright
38649 * @property {string=} trademark
38650 * @property {Number} unitsPerEm
38651 * @property {Number} ascender
38652 * @property {Number} descender
38653 * @property {Number} createdTimestamp
38654 * @property {string=} weightClass
38655 * @property {string=} widthClass
38656 * @property {string=} fsSelection
38657 */
38658
38659 /**
38660 * A Font represents a loaded OpenType font file.
38661 * It contains a set of glyphs and methods to draw text on a drawing context,
38662 * or to get a path representing the text.
38663 * @exports opentype.Font
38664 * @class
38665 * @param {FontOptions}
38666 * @constructor
38667 */
38668 function Font(options) {
38669 options = options || {};
38670
38671 if (!options.empty) {
38672 // Check that we've provided the minimum set of names.
38673 checkArgument(
38674 options.familyName,
38675 'When creating a new Font object, familyName is required.'
38676 );
38677 checkArgument(
38678 options.styleName,
38679 'When creating a new Font object, styleName is required.'
38680 );
38681 checkArgument(
38682 options.unitsPerEm,
38683 'When creating a new Font object, unitsPerEm is required.'
38684 );
38685 checkArgument(
38686 options.ascender,
38687 'When creating a new Font object, ascender is required.'
38688 );
38689 checkArgument(
38690 options.descender,
38691 'When creating a new Font object, descender is required.'
38692 );
38693 checkArgument(
38694 options.descender < 0,
38695 'Descender should be negative (e.g. -512).'
38696 );
38697
38698 // OS X will complain if the names are empty, so we put a single space everywhere by default.
38699 this.names = {
38700 fontFamily: { en: options.familyName || ' ' },
38701 fontSubfamily: { en: options.styleName || ' ' },
38702 fullName: {
38703 en: options.fullName || options.familyName + ' ' + options.styleName
38704 },
38705 // postScriptName may not contain any whitespace
38706 postScriptName: {
38707 en:
38708 options.postScriptName ||
38709 (options.familyName + options.styleName).replace(/\s/g, '')
38710 },
38711 designer: { en: options.designer || ' ' },
38712 designerURL: { en: options.designerURL || ' ' },
38713 manufacturer: { en: options.manufacturer || ' ' },
38714 manufacturerURL: { en: options.manufacturerURL || ' ' },
38715 license: { en: options.license || ' ' },
38716 licenseURL: { en: options.licenseURL || ' ' },
38717 version: { en: options.version || 'Version 0.1' },
38718 description: { en: options.description || ' ' },
38719 copyright: { en: options.copyright || ' ' },
38720 trademark: { en: options.trademark || ' ' }
38721 };
38722 this.unitsPerEm = options.unitsPerEm || 1000;
38723 this.ascender = options.ascender;
38724 this.descender = options.descender;
38725 this.createdTimestamp = options.createdTimestamp;
38726 this.tables = {
38727 os2: {
38728 usWeightClass: options.weightClass || this.usWeightClasses.MEDIUM,
38729 usWidthClass: options.widthClass || this.usWidthClasses.MEDIUM,
38730 fsSelection: options.fsSelection || this.fsSelectionValues.REGULAR
38731 }
38732 };
38733 }
38734
38735 this.supported = true; // Deprecated: parseBuffer will throw an error if font is not supported.
38736 this.glyphs = new glyphset.GlyphSet(this, options.glyphs || []);
38737 this.encoding = new DefaultEncoding(this);
38738 this.position = new Position(this);
38739 this.substitution = new Substitution(this);
38740 this.tables = this.tables || {};
38741
38742 Object.defineProperty(this, 'hinting', {
38743 get: function() {
38744 if (this._hinting) {
38745 return this._hinting;
38746 }
38747 if (this.outlinesFormat === 'truetype') {
38748 return (this._hinting = new Hinting(this));
38749 }
38750 }
38751 });
38752 }
38753
38754 /**
38755 * Check if the font has a glyph for the given character.
38756 * @param {string}
38757 * @return {Boolean}
38758 */
38759 Font.prototype.hasChar = function(c) {
38760 return this.encoding.charToGlyphIndex(c) !== null;
38761 };
38762
38763 /**
38764 * Convert the given character to a single glyph index.
38765 * Note that this function assumes that there is a one-to-one mapping between
38766 * the given character and a glyph; for complex scripts this might not be the case.
38767 * @param {string}
38768 * @return {Number}
38769 */
38770 Font.prototype.charToGlyphIndex = function(s) {
38771 return this.encoding.charToGlyphIndex(s);
38772 };
38773
38774 /**
38775 * Convert the given character to a single Glyph object.
38776 * Note that this function assumes that there is a one-to-one mapping between
38777 * the given character and a glyph; for complex scripts this might not be the case.
38778 * @param {string}
38779 * @return {opentype.Glyph}
38780 */
38781 Font.prototype.charToGlyph = function(c) {
38782 var glyphIndex = this.charToGlyphIndex(c);
38783 var glyph = this.glyphs.get(glyphIndex);
38784 if (!glyph) {
38785 // .notdef
38786 glyph = this.glyphs.get(0);
38787 }
38788
38789 return glyph;
38790 };
38791
38792 /**
38793 * Convert the given text to a list of Glyph objects.
38794 * Note that there is no strict one-to-one mapping between characters and
38795 * glyphs, so the list of returned glyphs can be larger or smaller than the
38796 * length of the given string.
38797 * @param {string}
38798 * @param {GlyphRenderOptions} [options]
38799 * @return {opentype.Glyph[]}
38800 */
38801 Font.prototype.stringToGlyphs = function(s, options) {
38802 var this$1 = this;
38803
38804 options = options || this.defaultRenderOptions;
38805 // Get glyph indexes
38806 var chars = arrayFromString(s);
38807 var indexes = [];
38808 for (var i = 0; i < chars.length; i += 1) {
38809 var c = chars[i];
38810 indexes.push(this$1.charToGlyphIndex(c));
38811 }
38812 var length = indexes.length;
38813
38814 // Apply substitutions on glyph indexes
38815 if (options.features) {
38816 var script = options.script || this.substitution.getDefaultScriptName();
38817 var manyToOne = [];
38818 if (options.features.liga) {
38819 manyToOne = manyToOne.concat(
38820 this.substitution.getFeature('liga', script, options.language)
38821 );
38822 }
38823 if (options.features.rlig) {
38824 manyToOne = manyToOne.concat(
38825 this.substitution.getFeature('rlig', script, options.language)
38826 );
38827 }
38828 for (var i$1 = 0; i$1 < length; i$1 += 1) {
38829 for (var j = 0; j < manyToOne.length; j++) {
38830 var ligature = manyToOne[j];
38831 var components = ligature.sub;
38832 var compCount = components.length;
38833 var k = 0;
38834 while (k < compCount && components[k] === indexes[i$1 + k]) {
38835 k++;
38836 }
38837 if (k === compCount) {
38838 indexes.splice(i$1, compCount, ligature.by);
38839 length = length - compCount + 1;
38840 }
38841 }
38842 }
38843 }
38844
38845 // convert glyph indexes to glyph objects
38846 var glyphs = new Array(length);
38847 var notdef = this.glyphs.get(0);
38848 for (var i$2 = 0; i$2 < length; i$2 += 1) {
38849 glyphs[i$2] = this$1.glyphs.get(indexes[i$2]) || notdef;
38850 }
38851 return glyphs;
38852 };
38853
38854 /**
38855 * @param {string}
38856 * @return {Number}
38857 */
38858 Font.prototype.nameToGlyphIndex = function(name) {
38859 return this.glyphNames.nameToGlyphIndex(name);
38860 };
38861
38862 /**
38863 * @param {string}
38864 * @return {opentype.Glyph}
38865 */
38866 Font.prototype.nameToGlyph = function(name) {
38867 var glyphIndex = this.nameToGlyphIndex(name);
38868 var glyph = this.glyphs.get(glyphIndex);
38869 if (!glyph) {
38870 // .notdef
38871 glyph = this.glyphs.get(0);
38872 }
38873
38874 return glyph;
38875 };
38876
38877 /**
38878 * @param {Number}
38879 * @return {String}
38880 */
38881 Font.prototype.glyphIndexToName = function(gid) {
38882 if (!this.glyphNames.glyphIndexToName) {
38883 return '';
38884 }
38885
38886 return this.glyphNames.glyphIndexToName(gid);
38887 };
38888
38889 /**
38890 * Retrieve the value of the kerning pair between the left glyph (or its index)
38891 * and the right glyph (or its index). If no kerning pair is found, return 0.
38892 * The kerning value gets added to the advance width when calculating the spacing
38893 * between glyphs.
38894 * For GPOS kerning, this method uses the default script and language, which covers
38895 * most use cases. To have greater control, use font.position.getKerningValue .
38896 * @param {opentype.Glyph} leftGlyph
38897 * @param {opentype.Glyph} rightGlyph
38898 * @return {Number}
38899 */
38900 Font.prototype.getKerningValue = function(leftGlyph, rightGlyph) {
38901 leftGlyph = leftGlyph.index || leftGlyph;
38902 rightGlyph = rightGlyph.index || rightGlyph;
38903 var gposKerning = this.position.defaultKerningTables;
38904 if (gposKerning) {
38905 return this.position.getKerningValue(gposKerning, leftGlyph, rightGlyph);
38906 }
38907 // "kern" table
38908 return this.kerningPairs[leftGlyph + ',' + rightGlyph] || 0;
38909 };
38910
38911 /**
38912 * @typedef GlyphRenderOptions
38913 * @type Object
38914 * @property {string} [script] - script used to determine which features to apply. By default, 'DFLT' or 'latn' is used.
38915 * See https://www.microsoft.com/typography/otspec/scripttags.htm
38916 * @property {string} [language='dflt'] - language system used to determine which features to apply.
38917 * See https://www.microsoft.com/typography/developers/opentype/languagetags.aspx
38918 * @property {boolean} [kerning=true] - whether to include kerning values
38919 * @property {object} [features] - OpenType Layout feature tags. Used to enable or disable the features of the given script/language system.
38920 * See https://www.microsoft.com/typography/otspec/featuretags.htm
38921 */
38922 Font.prototype.defaultRenderOptions = {
38923 kerning: true,
38924 features: {
38925 liga: true,
38926 rlig: true
38927 }
38928 };
38929
38930 /**
38931 * Helper function that invokes the given callback for each glyph in the given text.
38932 * The callback gets `(glyph, x, y, fontSize, options)`.* @param {string} text
38933 * @param {string} text - The text to apply.
38934 * @param {number} [x=0] - Horizontal position of the beginning of the text.
38935 * @param {number} [y=0] - Vertical position of the *baseline* of the text.
38936 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`.
38937 * @param {GlyphRenderOptions=} options
38938 * @param {Function} callback
38939 */
38940 Font.prototype.forEachGlyph = function(
38941 text,
38942 x,
38943 y,
38944 fontSize,
38945 options,
38946 callback
38947 ) {
38948 var this$1 = this;
38949
38950 x = x !== undefined ? x : 0;
38951 y = y !== undefined ? y : 0;
38952 fontSize = fontSize !== undefined ? fontSize : 72;
38953 options = options || this.defaultRenderOptions;
38954 var fontScale = 1 / this.unitsPerEm * fontSize;
38955 var glyphs = this.stringToGlyphs(text, options);
38956 var kerningLookups;
38957 if (options.kerning) {
38958 var script = options.script || this.position.getDefaultScriptName();
38959 kerningLookups = this.position.getKerningTables(script, options.language);
38960 }
38961 for (var i = 0; i < glyphs.length; i += 1) {
38962 var glyph = glyphs[i];
38963 callback.call(this$1, glyph, x, y, fontSize, options);
38964 if (glyph.advanceWidth) {
38965 x += glyph.advanceWidth * fontScale;
38966 }
38967
38968 if (options.kerning && i < glyphs.length - 1) {
38969 // We should apply position adjustment lookups in a more generic way.
38970 // Here we only use the xAdvance value.
38971 var kerningValue = kerningLookups
38972 ? this$1.position.getKerningValue(
38973 kerningLookups,
38974 glyph.index,
38975 glyphs[i + 1].index
38976 )
38977 : this$1.getKerningValue(glyph, glyphs[i + 1]);
38978 x += kerningValue * fontScale;
38979 }
38980
38981 if (options.letterSpacing) {
38982 x += options.letterSpacing * fontSize;
38983 } else if (options.tracking) {
38984 x += options.tracking / 1000 * fontSize;
38985 }
38986 }
38987 return x;
38988 };
38989
38990 /**
38991 * Create a Path object that represents the given text.
38992 * @param {string} text - The text to create.
38993 * @param {number} [x=0] - Horizontal position of the beginning of the text.
38994 * @param {number} [y=0] - Vertical position of the *baseline* of the text.
38995 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`.
38996 * @param {GlyphRenderOptions=} options
38997 * @return {opentype.Path}
38998 */
38999 Font.prototype.getPath = function(text, x, y, fontSize, options) {
39000 var fullPath = new Path();
39001 this.forEachGlyph(text, x, y, fontSize, options, function(
39002 glyph,
39003 gX,
39004 gY,
39005 gFontSize
39006 ) {
39007 var glyphPath = glyph.getPath(gX, gY, gFontSize, options, this);
39008 fullPath.extend(glyphPath);
39009 });
39010 return fullPath;
39011 };
39012
39013 /**
39014 * Create an array of Path objects that represent the glyphs of a given text.
39015 * @param {string} text - The text to create.
39016 * @param {number} [x=0] - Horizontal position of the beginning of the text.
39017 * @param {number} [y=0] - Vertical position of the *baseline* of the text.
39018 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`.
39019 * @param {GlyphRenderOptions=} options
39020 * @return {opentype.Path[]}
39021 */
39022 Font.prototype.getPaths = function(text, x, y, fontSize, options) {
39023 var glyphPaths = [];
39024 this.forEachGlyph(text, x, y, fontSize, options, function(
39025 glyph,
39026 gX,
39027 gY,
39028 gFontSize
39029 ) {
39030 var glyphPath = glyph.getPath(gX, gY, gFontSize, options, this);
39031 glyphPaths.push(glyphPath);
39032 });
39033
39034 return glyphPaths;
39035 };
39036
39037 /**
39038 * Returns the advance width of a text.
39039 *
39040 * This is something different than Path.getBoundingBox() as for example a
39041 * suffixed whitespace increases the advanceWidth but not the bounding box
39042 * or an overhanging letter like a calligraphic 'f' might have a quite larger
39043 * bounding box than its advance width.
39044 *
39045 * This corresponds to canvas2dContext.measureText(text).width
39046 *
39047 * @param {string} text - The text to create.
39048 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`.
39049 * @param {GlyphRenderOptions=} options
39050 * @return advance width
39051 */
39052 Font.prototype.getAdvanceWidth = function(text, fontSize, options) {
39053 return this.forEachGlyph(text, 0, 0, fontSize, options, function() {});
39054 };
39055
39056 /**
39057 * Draw the text on the given drawing context.
39058 * @param {CanvasRenderingContext2D} ctx - A 2D drawing context, like Canvas.
39059 * @param {string} text - The text to create.
39060 * @param {number} [x=0] - Horizontal position of the beginning of the text.
39061 * @param {number} [y=0] - Vertical position of the *baseline* of the text.
39062 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`.
39063 * @param {GlyphRenderOptions=} options
39064 */
39065 Font.prototype.draw = function(ctx, text, x, y, fontSize, options) {
39066 this.getPath(text, x, y, fontSize, options).draw(ctx);
39067 };
39068
39069 /**
39070 * Draw the points of all glyphs in the text.
39071 * On-curve points will be drawn in blue, off-curve points will be drawn in red.
39072 * @param {CanvasRenderingContext2D} ctx - A 2D drawing context, like Canvas.
39073 * @param {string} text - The text to create.
39074 * @param {number} [x=0] - Horizontal position of the beginning of the text.
39075 * @param {number} [y=0] - Vertical position of the *baseline* of the text.
39076 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`.
39077 * @param {GlyphRenderOptions=} options
39078 */
39079 Font.prototype.drawPoints = function(ctx, text, x, y, fontSize, options) {
39080 this.forEachGlyph(text, x, y, fontSize, options, function(
39081 glyph,
39082 gX,
39083 gY,
39084 gFontSize
39085 ) {
39086 glyph.drawPoints(ctx, gX, gY, gFontSize);
39087 });
39088 };
39089
39090 /**
39091 * Draw lines indicating important font measurements for all glyphs in the text.
39092 * Black lines indicate the origin of the coordinate system (point 0,0).
39093 * Blue lines indicate the glyph bounding box.
39094 * Green line indicates the advance width of the glyph.
39095 * @param {CanvasRenderingContext2D} ctx - A 2D drawing context, like Canvas.
39096 * @param {string} text - The text to create.
39097 * @param {number} [x=0] - Horizontal position of the beginning of the text.
39098 * @param {number} [y=0] - Vertical position of the *baseline* of the text.
39099 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`.
39100 * @param {GlyphRenderOptions=} options
39101 */
39102 Font.prototype.drawMetrics = function(ctx, text, x, y, fontSize, options) {
39103 this.forEachGlyph(text, x, y, fontSize, options, function(
39104 glyph,
39105 gX,
39106 gY,
39107 gFontSize
39108 ) {
39109 glyph.drawMetrics(ctx, gX, gY, gFontSize);
39110 });
39111 };
39112
39113 /**
39114 * @param {string}
39115 * @return {string}
39116 */
39117 Font.prototype.getEnglishName = function(name) {
39118 var translations = this.names[name];
39119 if (translations) {
39120 return translations.en;
39121 }
39122 };
39123
39124 /**
39125 * Validate
39126 */
39127 Font.prototype.validate = function() {
39128 var _this = this;
39129
39130 function assert(predicate, message) {}
39131
39132 function assertNamePresent(name) {
39133 var englishName = _this.getEnglishName(name);
39134 assert(
39135 englishName && englishName.trim().length > 0,
39136 'No English ' + name + ' specified.'
39137 );
39138 }
39139
39140 // Identification information
39141 assertNamePresent('fontFamily');
39142 assertNamePresent('weightName');
39143 assertNamePresent('manufacturer');
39144 assertNamePresent('copyright');
39145 assertNamePresent('version');
39146
39147 // Dimension information
39148 assert(this.unitsPerEm > 0, 'No unitsPerEm specified.');
39149 };
39150
39151 /**
39152 * Convert the font object to a SFNT data structure.
39153 * This structure contains all the necessary tables and metadata to create a binary OTF file.
39154 * @return {opentype.Table}
39155 */
39156 Font.prototype.toTables = function() {
39157 return sfnt.fontToTable(this);
39158 };
39159 /**
39160 * @deprecated Font.toBuffer is deprecated. Use Font.toArrayBuffer instead.
39161 */
39162 Font.prototype.toBuffer = function() {
39163 console.warn(
39164 'Font.toBuffer is deprecated. Use Font.toArrayBuffer instead.'
39165 );
39166 return this.toArrayBuffer();
39167 };
39168 /**
39169 * Converts a `opentype.Font` into an `ArrayBuffer`
39170 * @return {ArrayBuffer}
39171 */
39172 Font.prototype.toArrayBuffer = function() {
39173 var sfntTable = this.toTables();
39174 var bytes = sfntTable.encode();
39175 var buffer = new ArrayBuffer(bytes.length);
39176 var intArray = new Uint8Array(buffer);
39177 for (var i = 0; i < bytes.length; i++) {
39178 intArray[i] = bytes[i];
39179 }
39180
39181 return buffer;
39182 };
39183
39184 /**
39185 * Initiate a download of the OpenType font.
39186 */
39187 Font.prototype.download = function(fileName) {
39188 var familyName = this.getEnglishName('fontFamily');
39189 var styleName = this.getEnglishName('fontSubfamily');
39190 fileName =
39191 fileName || familyName.replace(/\s/g, '') + '-' + styleName + '.otf';
39192 var arrayBuffer = this.toArrayBuffer();
39193
39194 if (isBrowser()) {
39195 window.requestFileSystem =
39196 window.requestFileSystem || window.webkitRequestFileSystem;
39197 window.requestFileSystem(
39198 window.TEMPORARY,
39199 arrayBuffer.byteLength,
39200 function(fs) {
39201 fs.root.getFile(fileName, { create: true }, function(fileEntry) {
39202 fileEntry.createWriter(function(writer) {
39203 var dataView = new DataView(arrayBuffer);
39204 var blob = new Blob([dataView], { type: 'font/opentype' });
39205 writer.write(blob);
39206
39207 writer.addEventListener(
39208 'writeend',
39209 function() {
39210 // Navigating to the file will download it.
39211 location.href = fileEntry.toURL();
39212 },
39213 false
39214 );
39215 });
39216 });
39217 },
39218 function(err) {
39219 throw new Error(err.name + ': ' + err.message);
39220 }
39221 );
39222 } else {
39223 var fs = _dereq_('fs');
39224 var buffer = arrayBufferToNodeBuffer(arrayBuffer);
39225 fs.writeFileSync(fileName, buffer);
39226 }
39227 };
39228 /**
39229 * @private
39230 */
39231 Font.prototype.fsSelectionValues = {
39232 ITALIC: 0x001, //1
39233 UNDERSCORE: 0x002, //2
39234 NEGATIVE: 0x004, //4
39235 OUTLINED: 0x008, //8
39236 STRIKEOUT: 0x010, //16
39237 BOLD: 0x020, //32
39238 REGULAR: 0x040, //64
39239 USER_TYPO_METRICS: 0x080, //128
39240 WWS: 0x100, //256
39241 OBLIQUE: 0x200 //512
39242 };
39243
39244 /**
39245 * @private
39246 */
39247 Font.prototype.usWidthClasses = {
39248 ULTRA_CONDENSED: 1,
39249 EXTRA_CONDENSED: 2,
39250 CONDENSED: 3,
39251 SEMI_CONDENSED: 4,
39252 MEDIUM: 5,
39253 SEMI_EXPANDED: 6,
39254 EXPANDED: 7,
39255 EXTRA_EXPANDED: 8,
39256 ULTRA_EXPANDED: 9
39257 };
39258
39259 /**
39260 * @private
39261 */
39262 Font.prototype.usWeightClasses = {
39263 THIN: 100,
39264 EXTRA_LIGHT: 200,
39265 LIGHT: 300,
39266 NORMAL: 400,
39267 MEDIUM: 500,
39268 SEMI_BOLD: 600,
39269 BOLD: 700,
39270 EXTRA_BOLD: 800,
39271 BLACK: 900
39272 };
39273
39274 // The `fvar` table stores font variation axes and instances.
39275
39276 function addName(name, names) {
39277 var nameString = JSON.stringify(name);
39278 var nameID = 256;
39279 for (var nameKey in names) {
39280 var n = parseInt(nameKey);
39281 if (!n || n < 256) {
39282 continue;
39283 }
39284
39285 if (JSON.stringify(names[nameKey]) === nameString) {
39286 return n;
39287 }
39288
39289 if (nameID <= n) {
39290 nameID = n + 1;
39291 }
39292 }
39293
39294 names[nameID] = name;
39295 return nameID;
39296 }
39297
39298 function makeFvarAxis(n, axis, names) {
39299 var nameID = addName(axis.name, names);
39300 return [
39301 { name: 'tag_' + n, type: 'TAG', value: axis.tag },
39302 { name: 'minValue_' + n, type: 'FIXED', value: axis.minValue << 16 },
39303 {
39304 name: 'defaultValue_' + n,
39305 type: 'FIXED',
39306 value: axis.defaultValue << 16
39307 },
39308 { name: 'maxValue_' + n, type: 'FIXED', value: axis.maxValue << 16 },
39309 { name: 'flags_' + n, type: 'USHORT', value: 0 },
39310 { name: 'nameID_' + n, type: 'USHORT', value: nameID }
39311 ];
39312 }
39313
39314 function parseFvarAxis(data, start, names) {
39315 var axis = {};
39316 var p = new parse.Parser(data, start);
39317 axis.tag = p.parseTag();
39318 axis.minValue = p.parseFixed();
39319 axis.defaultValue = p.parseFixed();
39320 axis.maxValue = p.parseFixed();
39321 p.skip('uShort', 1); // reserved for flags; no values defined
39322 axis.name = names[p.parseUShort()] || {};
39323 return axis;
39324 }
39325
39326 function makeFvarInstance(n, inst, axes, names) {
39327 var nameID = addName(inst.name, names);
39328 var fields = [
39329 { name: 'nameID_' + n, type: 'USHORT', value: nameID },
39330 { name: 'flags_' + n, type: 'USHORT', value: 0 }
39331 ];
39332
39333 for (var i = 0; i < axes.length; ++i) {
39334 var axisTag = axes[i].tag;
39335 fields.push({
39336 name: 'axis_' + n + ' ' + axisTag,
39337 type: 'FIXED',
39338 value: inst.coordinates[axisTag] << 16
39339 });
39340 }
39341
39342 return fields;
39343 }
39344
39345 function parseFvarInstance(data, start, axes, names) {
39346 var inst = {};
39347 var p = new parse.Parser(data, start);
39348 inst.name = names[p.parseUShort()] || {};
39349 p.skip('uShort', 1); // reserved for flags; no values defined
39350
39351 inst.coordinates = {};
39352 for (var i = 0; i < axes.length; ++i) {
39353 inst.coordinates[axes[i].tag] = p.parseFixed();
39354 }
39355
39356 return inst;
39357 }
39358
39359 function makeFvarTable(fvar, names) {
39360 var result = new table.Table('fvar', [
39361 { name: 'version', type: 'ULONG', value: 0x10000 },
39362 { name: 'offsetToData', type: 'USHORT', value: 0 },
39363 { name: 'countSizePairs', type: 'USHORT', value: 2 },
39364 { name: 'axisCount', type: 'USHORT', value: fvar.axes.length },
39365 { name: 'axisSize', type: 'USHORT', value: 20 },
39366 { name: 'instanceCount', type: 'USHORT', value: fvar.instances.length },
39367 { name: 'instanceSize', type: 'USHORT', value: 4 + fvar.axes.length * 4 }
39368 ]);
39369 result.offsetToData = result.sizeOf();
39370
39371 for (var i = 0; i < fvar.axes.length; i++) {
39372 result.fields = result.fields.concat(
39373 makeFvarAxis(i, fvar.axes[i], names)
39374 );
39375 }
39376
39377 for (var j = 0; j < fvar.instances.length; j++) {
39378 result.fields = result.fields.concat(
39379 makeFvarInstance(j, fvar.instances[j], fvar.axes, names)
39380 );
39381 }
39382
39383 return result;
39384 }
39385
39386 function parseFvarTable(data, start, names) {
39387 var p = new parse.Parser(data, start);
39388 var tableVersion = p.parseULong();
39389 check.argument(
39390 tableVersion === 0x00010000,
39391 'Unsupported fvar table version.'
39392 );
39393 var offsetToData = p.parseOffset16();
39394 // Skip countSizePairs.
39395 p.skip('uShort', 1);
39396 var axisCount = p.parseUShort();
39397 var axisSize = p.parseUShort();
39398 var instanceCount = p.parseUShort();
39399 var instanceSize = p.parseUShort();
39400
39401 var axes = [];
39402 for (var i = 0; i < axisCount; i++) {
39403 axes.push(
39404 parseFvarAxis(data, start + offsetToData + i * axisSize, names)
39405 );
39406 }
39407
39408 var instances = [];
39409 var instanceStart = start + offsetToData + axisCount * axisSize;
39410 for (var j = 0; j < instanceCount; j++) {
39411 instances.push(
39412 parseFvarInstance(data, instanceStart + j * instanceSize, axes, names)
39413 );
39414 }
39415
39416 return { axes: axes, instances: instances };
39417 }
39418
39419 var fvar = { make: makeFvarTable, parse: parseFvarTable };
39420
39421 // The `GPOS` table contains kerning pairs, among other things.
39422
39423 var subtableParsers$1 = new Array(10); // subtableParsers[0] is unused
39424
39425 // https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#lookup-type-1-single-adjustment-positioning-subtable
39426 // this = Parser instance
39427 subtableParsers$1[1] = function parseLookup1() {
39428 var start = this.offset + this.relativeOffset;
39429 var posformat = this.parseUShort();
39430 if (posformat === 1) {
39431 return {
39432 posFormat: 1,
39433 coverage: this.parsePointer(Parser.coverage),
39434 value: this.parseValueRecord()
39435 };
39436 } else if (posformat === 2) {
39437 return {
39438 posFormat: 2,
39439 coverage: this.parsePointer(Parser.coverage),
39440 values: this.parseValueRecordList()
39441 };
39442 }
39443 check.assert(
39444 false,
39445 '0x' + start.toString(16) + ': GPOS lookup type 1 format must be 1 or 2.'
39446 );
39447 };
39448
39449 // https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#lookup-type-2-pair-adjustment-positioning-subtable
39450 subtableParsers$1[2] = function parseLookup2() {
39451 var start = this.offset + this.relativeOffset;
39452 var posFormat = this.parseUShort();
39453 check.assert(
39454 posFormat === 1 || posFormat === 2,
39455 '0x' + start.toString(16) + ': GPOS lookup type 2 format must be 1 or 2.'
39456 );
39457 var coverage = this.parsePointer(Parser.coverage);
39458 var valueFormat1 = this.parseUShort();
39459 var valueFormat2 = this.parseUShort();
39460 if (posFormat === 1) {
39461 // Adjustments for Glyph Pairs
39462 return {
39463 posFormat: posFormat,
39464 coverage: coverage,
39465 valueFormat1: valueFormat1,
39466 valueFormat2: valueFormat2,
39467 pairSets: this.parseList(
39468 Parser.pointer(
39469 Parser.list(function() {
39470 return {
39471 // pairValueRecord
39472 secondGlyph: this.parseUShort(),
39473 value1: this.parseValueRecord(valueFormat1),
39474 value2: this.parseValueRecord(valueFormat2)
39475 };
39476 })
39477 )
39478 )
39479 };
39480 } else if (posFormat === 2) {
39481 var classDef1 = this.parsePointer(Parser.classDef);
39482 var classDef2 = this.parsePointer(Parser.classDef);
39483 var class1Count = this.parseUShort();
39484 var class2Count = this.parseUShort();
39485 return {
39486 // Class Pair Adjustment
39487 posFormat: posFormat,
39488 coverage: coverage,
39489 valueFormat1: valueFormat1,
39490 valueFormat2: valueFormat2,
39491 classDef1: classDef1,
39492 classDef2: classDef2,
39493 class1Count: class1Count,
39494 class2Count: class2Count,
39495 classRecords: this.parseList(
39496 class1Count,
39497 Parser.list(class2Count, function() {
39498 return {
39499 value1: this.parseValueRecord(valueFormat1),
39500 value2: this.parseValueRecord(valueFormat2)
39501 };
39502 })
39503 )
39504 };
39505 }
39506 };
39507
39508 subtableParsers$1[3] = function parseLookup3() {
39509 return { error: 'GPOS Lookup 3 not supported' };
39510 };
39511 subtableParsers$1[4] = function parseLookup4() {
39512 return { error: 'GPOS Lookup 4 not supported' };
39513 };
39514 subtableParsers$1[5] = function parseLookup5() {
39515 return { error: 'GPOS Lookup 5 not supported' };
39516 };
39517 subtableParsers$1[6] = function parseLookup6() {
39518 return { error: 'GPOS Lookup 6 not supported' };
39519 };
39520 subtableParsers$1[7] = function parseLookup7() {
39521 return { error: 'GPOS Lookup 7 not supported' };
39522 };
39523 subtableParsers$1[8] = function parseLookup8() {
39524 return { error: 'GPOS Lookup 8 not supported' };
39525 };
39526 subtableParsers$1[9] = function parseLookup9() {
39527 return { error: 'GPOS Lookup 9 not supported' };
39528 };
39529
39530 // https://docs.microsoft.com/en-us/typography/opentype/spec/gpos
39531 function parseGposTable(data, start) {
39532 start = start || 0;
39533 var p = new Parser(data, start);
39534 var tableVersion = p.parseVersion(1);
39535 check.argument(
39536 tableVersion === 1 || tableVersion === 1.1,
39537 'Unsupported GPOS table version ' + tableVersion
39538 );
39539
39540 if (tableVersion === 1) {
39541 return {
39542 version: tableVersion,
39543 scripts: p.parseScriptList(),
39544 features: p.parseFeatureList(),
39545 lookups: p.parseLookupList(subtableParsers$1)
39546 };
39547 } else {
39548 return {
39549 version: tableVersion,
39550 scripts: p.parseScriptList(),
39551 features: p.parseFeatureList(),
39552 lookups: p.parseLookupList(subtableParsers$1),
39553 variations: p.parseFeatureVariationsList()
39554 };
39555 }
39556 }
39557
39558 // GPOS Writing //////////////////////////////////////////////
39559 // NOT SUPPORTED
39560 var subtableMakers$1 = new Array(10);
39561
39562 function makeGposTable(gpos) {
39563 return new table.Table('GPOS', [
39564 { name: 'version', type: 'ULONG', value: 0x10000 },
39565 {
39566 name: 'scripts',
39567 type: 'TABLE',
39568 value: new table.ScriptList(gpos.scripts)
39569 },
39570 {
39571 name: 'features',
39572 type: 'TABLE',
39573 value: new table.FeatureList(gpos.features)
39574 },
39575 {
39576 name: 'lookups',
39577 type: 'TABLE',
39578 value: new table.LookupList(gpos.lookups, subtableMakers$1)
39579 }
39580 ]);
39581 }
39582
39583 var gpos = { parse: parseGposTable, make: makeGposTable };
39584
39585 // The `kern` table contains kerning pairs.
39586
39587 function parseWindowsKernTable(p) {
39588 var pairs = {};
39589 // Skip nTables.
39590 p.skip('uShort');
39591 var subtableVersion = p.parseUShort();
39592 check.argument(
39593 subtableVersion === 0,
39594 'Unsupported kern sub-table version.'
39595 );
39596 // Skip subtableLength, subtableCoverage
39597 p.skip('uShort', 2);
39598 var nPairs = p.parseUShort();
39599 // Skip searchRange, entrySelector, rangeShift.
39600 p.skip('uShort', 3);
39601 for (var i = 0; i < nPairs; i += 1) {
39602 var leftIndex = p.parseUShort();
39603 var rightIndex = p.parseUShort();
39604 var value = p.parseShort();
39605 pairs[leftIndex + ',' + rightIndex] = value;
39606 }
39607 return pairs;
39608 }
39609
39610 function parseMacKernTable(p) {
39611 var pairs = {};
39612 // The Mac kern table stores the version as a fixed (32 bits) but we only loaded the first 16 bits.
39613 // Skip the rest.
39614 p.skip('uShort');
39615 var nTables = p.parseULong();
39616 //check.argument(nTables === 1, 'Only 1 subtable is supported (got ' + nTables + ').');
39617 if (nTables > 1) {
39618 console.warn('Only the first kern subtable is supported.');
39619 }
39620 p.skip('uLong');
39621 var coverage = p.parseUShort();
39622 var subtableVersion = coverage & 0xff;
39623 p.skip('uShort');
39624 if (subtableVersion === 0) {
39625 var nPairs = p.parseUShort();
39626 // Skip searchRange, entrySelector, rangeShift.
39627 p.skip('uShort', 3);
39628 for (var i = 0; i < nPairs; i += 1) {
39629 var leftIndex = p.parseUShort();
39630 var rightIndex = p.parseUShort();
39631 var value = p.parseShort();
39632 pairs[leftIndex + ',' + rightIndex] = value;
39633 }
39634 }
39635 return pairs;
39636 }
39637
39638 // Parse the `kern` table which contains kerning pairs.
39639 function parseKernTable(data, start) {
39640 var p = new parse.Parser(data, start);
39641 var tableVersion = p.parseUShort();
39642 if (tableVersion === 0) {
39643 return parseWindowsKernTable(p);
39644 } else if (tableVersion === 1) {
39645 return parseMacKernTable(p);
39646 } else {
39647 throw new Error('Unsupported kern table version (' + tableVersion + ').');
39648 }
39649 }
39650
39651 var kern = { parse: parseKernTable };
39652
39653 // The `loca` table stores the offsets to the locations of the glyphs in the font.
39654
39655 // Parse the `loca` table. This table stores the offsets to the locations of the glyphs in the font,
39656 // relative to the beginning of the glyphData table.
39657 // The number of glyphs stored in the `loca` table is specified in the `maxp` table (under numGlyphs)
39658 // The loca table has two versions: a short version where offsets are stored as uShorts, and a long
39659 // version where offsets are stored as uLongs. The `head` table specifies which version to use
39660 // (under indexToLocFormat).
39661 function parseLocaTable(data, start, numGlyphs, shortVersion) {
39662 var p = new parse.Parser(data, start);
39663 var parseFn = shortVersion ? p.parseUShort : p.parseULong;
39664 // There is an extra entry after the last index element to compute the length of the last glyph.
39665 // That's why we use numGlyphs + 1.
39666 var glyphOffsets = [];
39667 for (var i = 0; i < numGlyphs + 1; i += 1) {
39668 var glyphOffset = parseFn.call(p);
39669 if (shortVersion) {
39670 // The short table version stores the actual offset divided by 2.
39671 glyphOffset *= 2;
39672 }
39673
39674 glyphOffsets.push(glyphOffset);
39675 }
39676
39677 return glyphOffsets;
39678 }
39679
39680 var loca = { parse: parseLocaTable };
39681
39682 // opentype.js
39683
39684 /**
39685 * The opentype library.
39686 * @namespace opentype
39687 */
39688
39689 // File loaders /////////////////////////////////////////////////////////
39690 /**
39691 * Loads a font from a file. The callback throws an error message as the first parameter if it fails
39692 * and the font as an ArrayBuffer in the second parameter if it succeeds.
39693 * @param {string} path - The path of the file
39694 * @param {Function} callback - The function to call when the font load completes
39695 */
39696 function loadFromFile(path, callback) {
39697 var fs = _dereq_('fs');
39698 fs.readFile(path, function(err, buffer) {
39699 if (err) {
39700 return callback(err.message);
39701 }
39702
39703 callback(null, nodeBufferToArrayBuffer(buffer));
39704 });
39705 }
39706 /**
39707 * Loads a font from a URL. The callback throws an error message as the first parameter if it fails
39708 * and the font as an ArrayBuffer in the second parameter if it succeeds.
39709 * @param {string} url - The URL of the font file.
39710 * @param {Function} callback - The function to call when the font load completes
39711 */
39712 function loadFromUrl(url, callback) {
39713 var request = new XMLHttpRequest();
39714 request.open('get', url, true);
39715 request.responseType = 'arraybuffer';
39716 request.onload = function() {
39717 if (request.response) {
39718 return callback(null, request.response);
39719 } else {
39720 return callback('Font could not be loaded: ' + request.statusText);
39721 }
39722 };
39723
39724 request.onerror = function() {
39725 callback('Font could not be loaded');
39726 };
39727
39728 request.send();
39729 }
39730
39731 // Table Directory Entries //////////////////////////////////////////////
39732 /**
39733 * Parses OpenType table entries.
39734 * @param {DataView}
39735 * @param {Number}
39736 * @return {Object[]}
39737 */
39738 function parseOpenTypeTableEntries(data, numTables) {
39739 var tableEntries = [];
39740 var p = 12;
39741 for (var i = 0; i < numTables; i += 1) {
39742 var tag = parse.getTag(data, p);
39743 var checksum = parse.getULong(data, p + 4);
39744 var offset = parse.getULong(data, p + 8);
39745 var length = parse.getULong(data, p + 12);
39746 tableEntries.push({
39747 tag: tag,
39748 checksum: checksum,
39749 offset: offset,
39750 length: length,
39751 compression: false
39752 });
39753 p += 16;
39754 }
39755
39756 return tableEntries;
39757 }
39758
39759 /**
39760 * Parses WOFF table entries.
39761 * @param {DataView}
39762 * @param {Number}
39763 * @return {Object[]}
39764 */
39765 function parseWOFFTableEntries(data, numTables) {
39766 var tableEntries = [];
39767 var p = 44; // offset to the first table directory entry.
39768 for (var i = 0; i < numTables; i += 1) {
39769 var tag = parse.getTag(data, p);
39770 var offset = parse.getULong(data, p + 4);
39771 var compLength = parse.getULong(data, p + 8);
39772 var origLength = parse.getULong(data, p + 12);
39773 var compression = void 0;
39774 if (compLength < origLength) {
39775 compression = 'WOFF';
39776 } else {
39777 compression = false;
39778 }
39779
39780 tableEntries.push({
39781 tag: tag,
39782 offset: offset,
39783 compression: compression,
39784 compressedLength: compLength,
39785 length: origLength
39786 });
39787 p += 20;
39788 }
39789
39790 return tableEntries;
39791 }
39792
39793 /**
39794 * @typedef TableData
39795 * @type Object
39796 * @property {DataView} data - The DataView
39797 * @property {number} offset - The data offset.
39798 */
39799
39800 /**
39801 * @param {DataView}
39802 * @param {Object}
39803 * @return {TableData}
39804 */
39805 function uncompressTable(data, tableEntry) {
39806 if (tableEntry.compression === 'WOFF') {
39807 var inBuffer = new Uint8Array(
39808 data.buffer,
39809 tableEntry.offset + 2,
39810 tableEntry.compressedLength - 2
39811 );
39812 var outBuffer = new Uint8Array(tableEntry.length);
39813 tinyInflate(inBuffer, outBuffer);
39814 if (outBuffer.byteLength !== tableEntry.length) {
39815 throw new Error(
39816 'Decompression error: ' +
39817 tableEntry.tag +
39818 " decompressed length doesn't match recorded length"
39819 );
39820 }
39821
39822 var view = new DataView(outBuffer.buffer, 0);
39823 return { data: view, offset: 0 };
39824 } else {
39825 return { data: data, offset: tableEntry.offset };
39826 }
39827 }
39828
39829 // Public API ///////////////////////////////////////////////////////////
39830
39831 /**
39832 * Parse the OpenType file data (as an ArrayBuffer) and return a Font object.
39833 * Throws an error if the font could not be parsed.
39834 * @param {ArrayBuffer}
39835 * @return {opentype.Font}
39836 */
39837 function parseBuffer(buffer) {
39838 var indexToLocFormat;
39839 var ltagTable;
39840
39841 // Since the constructor can also be called to create new fonts from scratch, we indicate this
39842 // should be an empty font that we'll fill with our own data.
39843 var font = new Font({ empty: true });
39844
39845 // OpenType fonts use big endian byte ordering.
39846 // We can't rely on typed array view types, because they operate with the endianness of the host computer.
39847 // Instead we use DataViews where we can specify endianness.
39848 var data = new DataView(buffer, 0);
39849 var numTables;
39850 var tableEntries = [];
39851 var signature = parse.getTag(data, 0);
39852 if (
39853 signature === String.fromCharCode(0, 1, 0, 0) ||
39854 signature === 'true' ||
39855 signature === 'typ1'
39856 ) {
39857 font.outlinesFormat = 'truetype';
39858 numTables = parse.getUShort(data, 4);
39859 tableEntries = parseOpenTypeTableEntries(data, numTables);
39860 } else if (signature === 'OTTO') {
39861 font.outlinesFormat = 'cff';
39862 numTables = parse.getUShort(data, 4);
39863 tableEntries = parseOpenTypeTableEntries(data, numTables);
39864 } else if (signature === 'wOFF') {
39865 var flavor = parse.getTag(data, 4);
39866 if (flavor === String.fromCharCode(0, 1, 0, 0)) {
39867 font.outlinesFormat = 'truetype';
39868 } else if (flavor === 'OTTO') {
39869 font.outlinesFormat = 'cff';
39870 } else {
39871 throw new Error('Unsupported OpenType flavor ' + signature);
39872 }
39873
39874 numTables = parse.getUShort(data, 12);
39875 tableEntries = parseWOFFTableEntries(data, numTables);
39876 } else {
39877 throw new Error('Unsupported OpenType signature ' + signature);
39878 }
39879
39880 var cffTableEntry;
39881 var fvarTableEntry;
39882 var glyfTableEntry;
39883 var gposTableEntry;
39884 var gsubTableEntry;
39885 var hmtxTableEntry;
39886 var kernTableEntry;
39887 var locaTableEntry;
39888 var nameTableEntry;
39889 var metaTableEntry;
39890 var p;
39891
39892 for (var i = 0; i < numTables; i += 1) {
39893 var tableEntry = tableEntries[i];
39894 var table = void 0;
39895 switch (tableEntry.tag) {
39896 case 'cmap':
39897 table = uncompressTable(data, tableEntry);
39898 font.tables.cmap = cmap.parse(table.data, table.offset);
39899 font.encoding = new CmapEncoding(font.tables.cmap);
39900 break;
39901 case 'cvt ':
39902 table = uncompressTable(data, tableEntry);
39903 p = new parse.Parser(table.data, table.offset);
39904 font.tables.cvt = p.parseShortList(tableEntry.length / 2);
39905 break;
39906 case 'fvar':
39907 fvarTableEntry = tableEntry;
39908 break;
39909 case 'fpgm':
39910 table = uncompressTable(data, tableEntry);
39911 p = new parse.Parser(table.data, table.offset);
39912 font.tables.fpgm = p.parseByteList(tableEntry.length);
39913 break;
39914 case 'head':
39915 table = uncompressTable(data, tableEntry);
39916 font.tables.head = head.parse(table.data, table.offset);
39917 font.unitsPerEm = font.tables.head.unitsPerEm;
39918 indexToLocFormat = font.tables.head.indexToLocFormat;
39919 break;
39920 case 'hhea':
39921 table = uncompressTable(data, tableEntry);
39922 font.tables.hhea = hhea.parse(table.data, table.offset);
39923 font.ascender = font.tables.hhea.ascender;
39924 font.descender = font.tables.hhea.descender;
39925 font.numberOfHMetrics = font.tables.hhea.numberOfHMetrics;
39926 break;
39927 case 'hmtx':
39928 hmtxTableEntry = tableEntry;
39929 break;
39930 case 'ltag':
39931 table = uncompressTable(data, tableEntry);
39932 ltagTable = ltag.parse(table.data, table.offset);
39933 break;
39934 case 'maxp':
39935 table = uncompressTable(data, tableEntry);
39936 font.tables.maxp = maxp.parse(table.data, table.offset);
39937 font.numGlyphs = font.tables.maxp.numGlyphs;
39938 break;
39939 case 'name':
39940 nameTableEntry = tableEntry;
39941 break;
39942 case 'OS/2':
39943 table = uncompressTable(data, tableEntry);
39944 font.tables.os2 = os2.parse(table.data, table.offset);
39945 break;
39946 case 'post':
39947 table = uncompressTable(data, tableEntry);
39948 font.tables.post = post.parse(table.data, table.offset);
39949 font.glyphNames = new GlyphNames(font.tables.post);
39950 break;
39951 case 'prep':
39952 table = uncompressTable(data, tableEntry);
39953 p = new parse.Parser(table.data, table.offset);
39954 font.tables.prep = p.parseByteList(tableEntry.length);
39955 break;
39956 case 'glyf':
39957 glyfTableEntry = tableEntry;
39958 break;
39959 case 'loca':
39960 locaTableEntry = tableEntry;
39961 break;
39962 case 'CFF ':
39963 cffTableEntry = tableEntry;
39964 break;
39965 case 'kern':
39966 kernTableEntry = tableEntry;
39967 break;
39968 case 'GPOS':
39969 gposTableEntry = tableEntry;
39970 break;
39971 case 'GSUB':
39972 gsubTableEntry = tableEntry;
39973 break;
39974 case 'meta':
39975 metaTableEntry = tableEntry;
39976 break;
39977 }
39978 }
39979
39980 var nameTable = uncompressTable(data, nameTableEntry);
39981 font.tables.name = _name.parse(nameTable.data, nameTable.offset, ltagTable);
39982 font.names = font.tables.name;
39983
39984 if (glyfTableEntry && locaTableEntry) {
39985 var shortVersion = indexToLocFormat === 0;
39986 var locaTable = uncompressTable(data, locaTableEntry);
39987 var locaOffsets = loca.parse(
39988 locaTable.data,
39989 locaTable.offset,
39990 font.numGlyphs,
39991 shortVersion
39992 );
39993 var glyfTable = uncompressTable(data, glyfTableEntry);
39994 font.glyphs = glyf.parse(
39995 glyfTable.data,
39996 glyfTable.offset,
39997 locaOffsets,
39998 font
39999 );
40000 } else if (cffTableEntry) {
40001 var cffTable = uncompressTable(data, cffTableEntry);
40002 cff.parse(cffTable.data, cffTable.offset, font);
40003 } else {
40004 throw new Error("Font doesn't contain TrueType or CFF outlines.");
40005 }
40006
40007 var hmtxTable = uncompressTable(data, hmtxTableEntry);
40008 hmtx.parse(
40009 hmtxTable.data,
40010 hmtxTable.offset,
40011 font.numberOfHMetrics,
40012 font.numGlyphs,
40013 font.glyphs
40014 );
40015 addGlyphNames(font);
40016
40017 if (kernTableEntry) {
40018 var kernTable = uncompressTable(data, kernTableEntry);
40019 font.kerningPairs = kern.parse(kernTable.data, kernTable.offset);
40020 } else {
40021 font.kerningPairs = {};
40022 }
40023
40024 if (gposTableEntry) {
40025 var gposTable = uncompressTable(data, gposTableEntry);
40026 font.tables.gpos = gpos.parse(gposTable.data, gposTable.offset);
40027 font.position.init();
40028 }
40029
40030 if (gsubTableEntry) {
40031 var gsubTable = uncompressTable(data, gsubTableEntry);
40032 font.tables.gsub = gsub.parse(gsubTable.data, gsubTable.offset);
40033 }
40034
40035 if (fvarTableEntry) {
40036 var fvarTable = uncompressTable(data, fvarTableEntry);
40037 font.tables.fvar = fvar.parse(
40038 fvarTable.data,
40039 fvarTable.offset,
40040 font.names
40041 );
40042 }
40043
40044 if (metaTableEntry) {
40045 var metaTable = uncompressTable(data, metaTableEntry);
40046 font.tables.meta = meta.parse(metaTable.data, metaTable.offset);
40047 font.metas = font.tables.meta;
40048 }
40049
40050 return font;
40051 }
40052
40053 /**
40054 * Asynchronously load the font from a URL or a filesystem. When done, call the callback
40055 * with two arguments `(err, font)`. The `err` will be null on success,
40056 * the `font` is a Font object.
40057 * We use the node.js callback convention so that
40058 * opentype.js can integrate with frameworks like async.js.
40059 * @alias opentype.load
40060 * @param {string} url - The URL of the font to load.
40061 * @param {Function} callback - The callback.
40062 */
40063 function load(url, callback) {
40064 var isNode$$1 = typeof window === 'undefined';
40065 var loadFn = isNode$$1 ? loadFromFile : loadFromUrl;
40066 loadFn(url, function(err, arrayBuffer) {
40067 if (err) {
40068 return callback(err);
40069 }
40070 var font;
40071 try {
40072 font = parseBuffer(arrayBuffer);
40073 } catch (e) {
40074 return callback(e, null);
40075 }
40076 return callback(null, font);
40077 });
40078 }
40079
40080 /**
40081 * Synchronously load the font from a URL or file.
40082 * When done, returns the font object or throws an error.
40083 * @alias opentype.loadSync
40084 * @param {string} url - The URL of the font to load.
40085 * @return {opentype.Font}
40086 */
40087 function loadSync(url) {
40088 var fs = _dereq_('fs');
40089 var buffer = fs.readFileSync(url);
40090 return parseBuffer(nodeBufferToArrayBuffer(buffer));
40091 }
40092
40093 exports.Font = Font;
40094 exports.Glyph = Glyph;
40095 exports.Path = Path;
40096 exports.BoundingBox = BoundingBox;
40097 exports._parse = parse;
40098 exports.parse = parseBuffer;
40099 exports.load = load;
40100 exports.loadSync = loadSync;
40101
40102 Object.defineProperty(exports, '__esModule', { value: true });
40103 });
40104 }.call(this, _dereq_('buffer').Buffer));
40105 },
40106 { buffer: 22, fs: 21 }
40107 ],
40108 35: [
40109 function(_dereq_, module, exports) {
40110 (function(process) {
40111 // .dirname, .basename, and .extname methods are extracted from Node.js v8.11.1,
40112 // backported and transplited with Babel, with backwards-compat fixes
40113
40114 // Copyright Joyent, Inc. and other Node contributors.
40115 //
40116 // Permission is hereby granted, free of charge, to any person obtaining a
40117 // copy of this software and associated documentation files (the
40118 // "Software"), to deal in the Software without restriction, including
40119 // without limitation the rights to use, copy, modify, merge, publish,
40120 // distribute, sublicense, and/or sell copies of the Software, and to permit
40121 // persons to whom the Software is furnished to do so, subject to the
40122 // following conditions:
40123 //
40124 // The above copyright notice and this permission notice shall be included
40125 // in all copies or substantial portions of the Software.
40126 //
40127 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
40128 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
40129 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
40130 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
40131 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
40132 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
40133 // USE OR OTHER DEALINGS IN THE SOFTWARE.
40134
40135 // resolves . and .. elements in a path array with directory names there
40136 // must be no slashes, empty elements, or device names (c:\) in the array
40137 // (so also no leading and trailing slashes - it does not distinguish
40138 // relative and absolute paths)
40139 function normalizeArray(parts, allowAboveRoot) {
40140 // if the path tries to go above the root, `up` ends up > 0
40141 var up = 0;
40142 for (var i = parts.length - 1; i >= 0; i--) {
40143 var last = parts[i];
40144 if (last === '.') {
40145 parts.splice(i, 1);
40146 } else if (last === '..') {
40147 parts.splice(i, 1);
40148 up++;
40149 } else if (up) {
40150 parts.splice(i, 1);
40151 up--;
40152 }
40153 }
40154
40155 // if the path is allowed to go above the root, restore leading ..s
40156 if (allowAboveRoot) {
40157 for (; up--; up) {
40158 parts.unshift('..');
40159 }
40160 }
40161
40162 return parts;
40163 }
40164
40165 // path.resolve([from ...], to)
40166 // posix version
40167 exports.resolve = function() {
40168 var resolvedPath = '',
40169 resolvedAbsolute = false;
40170
40171 for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
40172 var path = i >= 0 ? arguments[i] : process.cwd();
40173
40174 // Skip empty and invalid entries
40175 if (typeof path !== 'string') {
40176 throw new TypeError('Arguments to path.resolve must be strings');
40177 } else if (!path) {
40178 continue;
40179 }
40180
40181 resolvedPath = path + '/' + resolvedPath;
40182 resolvedAbsolute = path.charAt(0) === '/';
40183 }
40184
40185 // At this point the path should be resolved to a full absolute path, but
40186 // handle relative paths to be safe (might happen when process.cwd() fails)
40187
40188 // Normalize the path
40189 resolvedPath = normalizeArray(
40190 filter(resolvedPath.split('/'), function(p) {
40191 return !!p;
40192 }),
40193 !resolvedAbsolute
40194 ).join('/');
40195
40196 return (resolvedAbsolute ? '/' : '') + resolvedPath || '.';
40197 };
40198
40199 // path.normalize(path)
40200 // posix version
40201 exports.normalize = function(path) {
40202 var isAbsolute = exports.isAbsolute(path),
40203 trailingSlash = substr(path, -1) === '/';
40204
40205 // Normalize the path
40206 path = normalizeArray(
40207 filter(path.split('/'), function(p) {
40208 return !!p;
40209 }),
40210 !isAbsolute
40211 ).join('/');
40212
40213 if (!path && !isAbsolute) {
40214 path = '.';
40215 }
40216 if (path && trailingSlash) {
40217 path += '/';
40218 }
40219
40220 return (isAbsolute ? '/' : '') + path;
40221 };
40222
40223 // posix version
40224 exports.isAbsolute = function(path) {
40225 return path.charAt(0) === '/';
40226 };
40227
40228 // posix version
40229 exports.join = function() {
40230 var paths = Array.prototype.slice.call(arguments, 0);
40231 return exports.normalize(
40232 filter(paths, function(p, index) {
40233 if (typeof p !== 'string') {
40234 throw new TypeError('Arguments to path.join must be strings');
40235 }
40236 return p;
40237 }).join('/')
40238 );
40239 };
40240
40241 // path.relative(from, to)
40242 // posix version
40243 exports.relative = function(from, to) {
40244 from = exports.resolve(from).substr(1);
40245 to = exports.resolve(to).substr(1);
40246
40247 function trim(arr) {
40248 var start = 0;
40249 for (; start < arr.length; start++) {
40250 if (arr[start] !== '') break;
40251 }
40252
40253 var end = arr.length - 1;
40254 for (; end >= 0; end--) {
40255 if (arr[end] !== '') break;
40256 }
40257
40258 if (start > end) return [];
40259 return arr.slice(start, end - start + 1);
40260 }
40261
40262 var fromParts = trim(from.split('/'));
40263 var toParts = trim(to.split('/'));
40264
40265 var length = Math.min(fromParts.length, toParts.length);
40266 var samePartsLength = length;
40267 for (var i = 0; i < length; i++) {
40268 if (fromParts[i] !== toParts[i]) {
40269 samePartsLength = i;
40270 break;
40271 }
40272 }
40273
40274 var outputParts = [];
40275 for (var i = samePartsLength; i < fromParts.length; i++) {
40276 outputParts.push('..');
40277 }
40278
40279 outputParts = outputParts.concat(toParts.slice(samePartsLength));
40280
40281 return outputParts.join('/');
40282 };
40283
40284 exports.sep = '/';
40285 exports.delimiter = ':';
40286
40287 exports.dirname = function(path) {
40288 if (typeof path !== 'string') path = path + '';
40289 if (path.length === 0) return '.';
40290 var code = path.charCodeAt(0);
40291 var hasRoot = code === 47 /*/*/;
40292 var end = -1;
40293 var matchedSlash = true;
40294 for (var i = path.length - 1; i >= 1; --i) {
40295 code = path.charCodeAt(i);
40296 if (code === 47 /*/*/) {
40297 if (!matchedSlash) {
40298 end = i;
40299 break;
40300 }
40301 } else {
40302 // We saw the first non-path separator
40303 matchedSlash = false;
40304 }
40305 }
40306
40307 if (end === -1) return hasRoot ? '/' : '.';
40308 if (hasRoot && end === 1) {
40309 // return '//';
40310 // Backwards-compat fix:
40311 return '/';
40312 }
40313 return path.slice(0, end);
40314 };
40315
40316 function basename(path) {
40317 if (typeof path !== 'string') path = path + '';
40318
40319 var start = 0;
40320 var end = -1;
40321 var matchedSlash = true;
40322 var i;
40323
40324 for (i = path.length - 1; i >= 0; --i) {
40325 if (path.charCodeAt(i) === 47 /*/*/) {
40326 // If we reached a path separator that was not part of a set of path
40327 // separators at the end of the string, stop now
40328 if (!matchedSlash) {
40329 start = i + 1;
40330 break;
40331 }
40332 } else if (end === -1) {
40333 // We saw the first non-path separator, mark this as the end of our
40334 // path component
40335 matchedSlash = false;
40336 end = i + 1;
40337 }
40338 }
40339
40340 if (end === -1) return '';
40341 return path.slice(start, end);
40342 }
40343
40344 // Uses a mixed approach for backwards-compatibility, as ext behavior changed
40345 // in new Node.js versions, so only basename() above is backported here
40346 exports.basename = function(path, ext) {
40347 var f = basename(path);
40348 if (ext && f.substr(-1 * ext.length) === ext) {
40349 f = f.substr(0, f.length - ext.length);
40350 }
40351 return f;
40352 };
40353
40354 exports.extname = function(path) {
40355 if (typeof path !== 'string') path = path + '';
40356 var startDot = -1;
40357 var startPart = 0;
40358 var end = -1;
40359 var matchedSlash = true;
40360 // Track the state of characters (if any) we see before our first dot and
40361 // after any path separator we find
40362 var preDotState = 0;
40363 for (var i = path.length - 1; i >= 0; --i) {
40364 var code = path.charCodeAt(i);
40365 if (code === 47 /*/*/) {
40366 // If we reached a path separator that was not part of a set of path
40367 // separators at the end of the string, stop now
40368 if (!matchedSlash) {
40369 startPart = i + 1;
40370 break;
40371 }
40372 continue;
40373 }
40374 if (end === -1) {
40375 // We saw the first non-path separator, mark this as the end of our
40376 // extension
40377 matchedSlash = false;
40378 end = i + 1;
40379 }
40380 if (code === 46 /*.*/) {
40381 // If this is our first dot, mark it as the start of our extension
40382 if (startDot === -1) startDot = i;
40383 else if (preDotState !== 1) preDotState = 1;
40384 } else if (startDot !== -1) {
40385 // We saw a non-dot and non-path separator before our dot, so we should
40386 // have a good chance at having a non-empty extension
40387 preDotState = -1;
40388 }
40389 }
40390
40391 if (
40392 startDot === -1 ||
40393 end === -1 ||
40394 // We saw a non-dot character immediately before the dot
40395 preDotState === 0 ||
40396 // The (right-most) trimmed path component is exactly '..'
40397 (preDotState === 1 && startDot === end - 1 && startDot === startPart + 1)
40398 ) {
40399 return '';
40400 }
40401 return path.slice(startDot, end);
40402 };
40403
40404 function filter(xs, f) {
40405 if (xs.filter) return xs.filter(f);
40406 var res = [];
40407 for (var i = 0; i < xs.length; i++) {
40408 if (f(xs[i], i, xs)) res.push(xs[i]);
40409 }
40410 return res;
40411 }
40412
40413 // String.prototype.substr - negative index don't work in IE8
40414 var substr =
40415 'ab'.substr(-1) === 'b'
40416 ? function(str, start, len) {
40417 return str.substr(start, len);
40418 }
40419 : function(str, start, len) {
40420 if (start < 0) start = str.length + start;
40421 return str.substr(start, len);
40422 };
40423 }.call(this, _dereq_('_process')));
40424 },
40425 { _process: 36 }
40426 ],
40427 36: [
40428 function(_dereq_, module, exports) {
40429 // shim for using process in browser
40430 var process = (module.exports = {});
40431
40432 // cached from whatever global is present so that test runners that stub it
40433 // don't break things. But we need to wrap it in a try catch in case it is
40434 // wrapped in strict mode code which doesn't define any globals. It's inside a
40435 // function because try/catches deoptimize in certain engines.
40436
40437 var cachedSetTimeout;
40438 var cachedClearTimeout;
40439
40440 function defaultSetTimout() {
40441 throw new Error('setTimeout has not been defined');
40442 }
40443 function defaultClearTimeout() {
40444 throw new Error('clearTimeout has not been defined');
40445 }
40446 (function() {
40447 try {
40448 if (typeof setTimeout === 'function') {
40449 cachedSetTimeout = setTimeout;
40450 } else {
40451 cachedSetTimeout = defaultSetTimout;
40452 }
40453 } catch (e) {
40454 cachedSetTimeout = defaultSetTimout;
40455 }
40456 try {
40457 if (typeof clearTimeout === 'function') {
40458 cachedClearTimeout = clearTimeout;
40459 } else {
40460 cachedClearTimeout = defaultClearTimeout;
40461 }
40462 } catch (e) {
40463 cachedClearTimeout = defaultClearTimeout;
40464 }
40465 })();
40466 function runTimeout(fun) {
40467 if (cachedSetTimeout === setTimeout) {
40468 //normal enviroments in sane situations
40469 return setTimeout(fun, 0);
40470 }
40471 // if setTimeout wasn't available but was latter defined
40472 if (
40473 (cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) &&
40474 setTimeout
40475 ) {
40476 cachedSetTimeout = setTimeout;
40477 return setTimeout(fun, 0);
40478 }
40479 try {
40480 // when when somebody has screwed with setTimeout but no I.E. maddness
40481 return cachedSetTimeout(fun, 0);
40482 } catch (e) {
40483 try {
40484 // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
40485 return cachedSetTimeout.call(null, fun, 0);
40486 } catch (e) {
40487 // 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
40488 return cachedSetTimeout.call(this, fun, 0);
40489 }
40490 }
40491 }
40492 function runClearTimeout(marker) {
40493 if (cachedClearTimeout === clearTimeout) {
40494 //normal enviroments in sane situations
40495 return clearTimeout(marker);
40496 }
40497 // if clearTimeout wasn't available but was latter defined
40498 if (
40499 (cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) &&
40500 clearTimeout
40501 ) {
40502 cachedClearTimeout = clearTimeout;
40503 return clearTimeout(marker);
40504 }
40505 try {
40506 // when when somebody has screwed with setTimeout but no I.E. maddness
40507 return cachedClearTimeout(marker);
40508 } catch (e) {
40509 try {
40510 // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
40511 return cachedClearTimeout.call(null, marker);
40512 } catch (e) {
40513 // 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.
40514 // Some versions of I.E. have different rules for clearTimeout vs setTimeout
40515 return cachedClearTimeout.call(this, marker);
40516 }
40517 }
40518 }
40519 var queue = [];
40520 var draining = false;
40521 var currentQueue;
40522 var queueIndex = -1;
40523
40524 function cleanUpNextTick() {
40525 if (!draining || !currentQueue) {
40526 return;
40527 }
40528 draining = false;
40529 if (currentQueue.length) {
40530 queue = currentQueue.concat(queue);
40531 } else {
40532 queueIndex = -1;
40533 }
40534 if (queue.length) {
40535 drainQueue();
40536 }
40537 }
40538
40539 function drainQueue() {
40540 if (draining) {
40541 return;
40542 }
40543 var timeout = runTimeout(cleanUpNextTick);
40544 draining = true;
40545
40546 var len = queue.length;
40547 while (len) {
40548 currentQueue = queue;
40549 queue = [];
40550 while (++queueIndex < len) {
40551 if (currentQueue) {
40552 currentQueue[queueIndex].run();
40553 }
40554 }
40555 queueIndex = -1;
40556 len = queue.length;
40557 }
40558 currentQueue = null;
40559 draining = false;
40560 runClearTimeout(timeout);
40561 }
40562
40563 process.nextTick = function(fun) {
40564 var args = new Array(arguments.length - 1);
40565 if (arguments.length > 1) {
40566 for (var i = 1; i < arguments.length; i++) {
40567 args[i - 1] = arguments[i];
40568 }
40569 }
40570 queue.push(new Item(fun, args));
40571 if (queue.length === 1 && !draining) {
40572 runTimeout(drainQueue);
40573 }
40574 };
40575
40576 // v8 likes predictible objects
40577 function Item(fun, array) {
40578 this.fun = fun;
40579 this.array = array;
40580 }
40581 Item.prototype.run = function() {
40582 this.fun.apply(null, this.array);
40583 };
40584 process.title = 'browser';
40585 process.browser = true;
40586 process.env = {};
40587 process.argv = [];
40588 process.version = ''; // empty string to avoid regexp issues
40589 process.versions = {};
40590
40591 function noop() {}
40592
40593 process.on = noop;
40594 process.addListener = noop;
40595 process.once = noop;
40596 process.off = noop;
40597 process.removeListener = noop;
40598 process.removeAllListeners = noop;
40599 process.emit = noop;
40600 process.prependListener = noop;
40601 process.prependOnceListener = noop;
40602
40603 process.listeners = function(name) {
40604 return [];
40605 };
40606
40607 process.binding = function(name) {
40608 throw new Error('process.binding is not supported');
40609 };
40610
40611 process.cwd = function() {
40612 return '/';
40613 };
40614 process.chdir = function(dir) {
40615 throw new Error('process.chdir is not supported');
40616 };
40617 process.umask = function() {
40618 return 0;
40619 };
40620 },
40621 {}
40622 ],
40623 37: [
40624 function(_dereq_, module, exports) {
40625 (function(self) {
40626 'use strict';
40627
40628 if (self.fetch) {
40629 return;
40630 }
40631
40632 var support = {
40633 searchParams: 'URLSearchParams' in self,
40634 iterable: 'Symbol' in self && 'iterator' in Symbol,
40635 blob:
40636 'FileReader' in self &&
40637 'Blob' in self &&
40638 (function() {
40639 try {
40640 new Blob();
40641 return true;
40642 } catch (e) {
40643 return false;
40644 }
40645 })(),
40646 formData: 'FormData' in self,
40647 arrayBuffer: 'ArrayBuffer' in self
40648 };
40649
40650 if (support.arrayBuffer) {
40651 var viewClasses = [
40652 '[object Int8Array]',
40653 '[object Uint8Array]',
40654 '[object Uint8ClampedArray]',
40655 '[object Int16Array]',
40656 '[object Uint16Array]',
40657 '[object Int32Array]',
40658 '[object Uint32Array]',
40659 '[object Float32Array]',
40660 '[object Float64Array]'
40661 ];
40662
40663 var isDataView = function(obj) {
40664 return obj && DataView.prototype.isPrototypeOf(obj);
40665 };
40666
40667 var isArrayBufferView =
40668 ArrayBuffer.isView ||
40669 function(obj) {
40670 return (
40671 obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1
40672 );
40673 };
40674 }
40675
40676 function normalizeName(name) {
40677 if (typeof name !== 'string') {
40678 name = String(name);
40679 }
40680 if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) {
40681 throw new TypeError('Invalid character in header field name');
40682 }
40683 return name.toLowerCase();
40684 }
40685
40686 function normalizeValue(value) {
40687 if (typeof value !== 'string') {
40688 value = String(value);
40689 }
40690 return value;
40691 }
40692
40693 // Build a destructive iterator for the value list
40694 function iteratorFor(items) {
40695 var iterator = {
40696 next: function() {
40697 var value = items.shift();
40698 return { done: value === undefined, value: value };
40699 }
40700 };
40701
40702 if (support.iterable) {
40703 iterator[Symbol.iterator] = function() {
40704 return iterator;
40705 };
40706 }
40707
40708 return iterator;
40709 }
40710
40711 function Headers(headers) {
40712 this.map = {};
40713
40714 if (headers instanceof Headers) {
40715 headers.forEach(function(value, name) {
40716 this.append(name, value);
40717 }, this);
40718 } else if (Array.isArray(headers)) {
40719 headers.forEach(function(header) {
40720 this.append(header[0], header[1]);
40721 }, this);
40722 } else if (headers) {
40723 Object.getOwnPropertyNames(headers).forEach(function(name) {
40724 this.append(name, headers[name]);
40725 }, this);
40726 }
40727 }
40728
40729 Headers.prototype.append = function(name, value) {
40730 name = normalizeName(name);
40731 value = normalizeValue(value);
40732 var oldValue = this.map[name];
40733 this.map[name] = oldValue ? oldValue + ',' + value : value;
40734 };
40735
40736 Headers.prototype['delete'] = function(name) {
40737 delete this.map[normalizeName(name)];
40738 };
40739
40740 Headers.prototype.get = function(name) {
40741 name = normalizeName(name);
40742 return this.has(name) ? this.map[name] : null;
40743 };
40744
40745 Headers.prototype.has = function(name) {
40746 return this.map.hasOwnProperty(normalizeName(name));
40747 };
40748
40749 Headers.prototype.set = function(name, value) {
40750 this.map[normalizeName(name)] = normalizeValue(value);
40751 };
40752
40753 Headers.prototype.forEach = function(callback, thisArg) {
40754 for (var name in this.map) {
40755 if (this.map.hasOwnProperty(name)) {
40756 callback.call(thisArg, this.map[name], name, this);
40757 }
40758 }
40759 };
40760
40761 Headers.prototype.keys = function() {
40762 var items = [];
40763 this.forEach(function(value, name) {
40764 items.push(name);
40765 });
40766 return iteratorFor(items);
40767 };
40768
40769 Headers.prototype.values = function() {
40770 var items = [];
40771 this.forEach(function(value) {
40772 items.push(value);
40773 });
40774 return iteratorFor(items);
40775 };
40776
40777 Headers.prototype.entries = function() {
40778 var items = [];
40779 this.forEach(function(value, name) {
40780 items.push([name, value]);
40781 });
40782 return iteratorFor(items);
40783 };
40784
40785 if (support.iterable) {
40786 Headers.prototype[Symbol.iterator] = Headers.prototype.entries;
40787 }
40788
40789 function consumed(body) {
40790 if (body.bodyUsed) {
40791 return Promise.reject(new TypeError('Already read'));
40792 }
40793 body.bodyUsed = true;
40794 }
40795
40796 function fileReaderReady(reader) {
40797 return new Promise(function(resolve, reject) {
40798 reader.onload = function() {
40799 resolve(reader.result);
40800 };
40801 reader.onerror = function() {
40802 reject(reader.error);
40803 };
40804 });
40805 }
40806
40807 function readBlobAsArrayBuffer(blob) {
40808 var reader = new FileReader();
40809 var promise = fileReaderReady(reader);
40810 reader.readAsArrayBuffer(blob);
40811 return promise;
40812 }
40813
40814 function readBlobAsText(blob) {
40815 var reader = new FileReader();
40816 var promise = fileReaderReady(reader);
40817 reader.readAsText(blob);
40818 return promise;
40819 }
40820
40821 function readArrayBufferAsText(buf) {
40822 var view = new Uint8Array(buf);
40823 var chars = new Array(view.length);
40824
40825 for (var i = 0; i < view.length; i++) {
40826 chars[i] = String.fromCharCode(view[i]);
40827 }
40828 return chars.join('');
40829 }
40830
40831 function bufferClone(buf) {
40832 if (buf.slice) {
40833 return buf.slice(0);
40834 } else {
40835 var view = new Uint8Array(buf.byteLength);
40836 view.set(new Uint8Array(buf));
40837 return view.buffer;
40838 }
40839 }
40840
40841 function Body() {
40842 this.bodyUsed = false;
40843
40844 this._initBody = function(body) {
40845 this._bodyInit = body;
40846 if (!body) {
40847 this._bodyText = '';
40848 } else if (typeof body === 'string') {
40849 this._bodyText = body;
40850 } else if (support.blob && Blob.prototype.isPrototypeOf(body)) {
40851 this._bodyBlob = body;
40852 } else if (support.formData && FormData.prototype.isPrototypeOf(body)) {
40853 this._bodyFormData = body;
40854 } else if (
40855 support.searchParams &&
40856 URLSearchParams.prototype.isPrototypeOf(body)
40857 ) {
40858 this._bodyText = body.toString();
40859 } else if (support.arrayBuffer && support.blob && isDataView(body)) {
40860 this._bodyArrayBuffer = bufferClone(body.buffer);
40861 // IE 10-11 can't handle a DataView body.
40862 this._bodyInit = new Blob([this._bodyArrayBuffer]);
40863 } else if (
40864 support.arrayBuffer &&
40865 (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))
40866 ) {
40867 this._bodyArrayBuffer = bufferClone(body);
40868 } else {
40869 throw new Error('unsupported BodyInit type');
40870 }
40871
40872 if (!this.headers.get('content-type')) {
40873 if (typeof body === 'string') {
40874 this.headers.set('content-type', 'text/plain;charset=UTF-8');
40875 } else if (this._bodyBlob && this._bodyBlob.type) {
40876 this.headers.set('content-type', this._bodyBlob.type);
40877 } else if (
40878 support.searchParams &&
40879 URLSearchParams.prototype.isPrototypeOf(body)
40880 ) {
40881 this.headers.set(
40882 'content-type',
40883 'application/x-www-form-urlencoded;charset=UTF-8'
40884 );
40885 }
40886 }
40887 };
40888
40889 if (support.blob) {
40890 this.blob = function() {
40891 var rejected = consumed(this);
40892 if (rejected) {
40893 return rejected;
40894 }
40895
40896 if (this._bodyBlob) {
40897 return Promise.resolve(this._bodyBlob);
40898 } else if (this._bodyArrayBuffer) {
40899 return Promise.resolve(new Blob([this._bodyArrayBuffer]));
40900 } else if (this._bodyFormData) {
40901 throw new Error('could not read FormData body as blob');
40902 } else {
40903 return Promise.resolve(new Blob([this._bodyText]));
40904 }
40905 };
40906
40907 this.arrayBuffer = function() {
40908 if (this._bodyArrayBuffer) {
40909 return consumed(this) || Promise.resolve(this._bodyArrayBuffer);
40910 } else {
40911 return this.blob().then(readBlobAsArrayBuffer);
40912 }
40913 };
40914 }
40915
40916 this.text = function() {
40917 var rejected = consumed(this);
40918 if (rejected) {
40919 return rejected;
40920 }
40921
40922 if (this._bodyBlob) {
40923 return readBlobAsText(this._bodyBlob);
40924 } else if (this._bodyArrayBuffer) {
40925 return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer));
40926 } else if (this._bodyFormData) {
40927 throw new Error('could not read FormData body as text');
40928 } else {
40929 return Promise.resolve(this._bodyText);
40930 }
40931 };
40932
40933 if (support.formData) {
40934 this.formData = function() {
40935 return this.text().then(decode);
40936 };
40937 }
40938
40939 this.json = function() {
40940 return this.text().then(JSON.parse);
40941 };
40942
40943 return this;
40944 }
40945
40946 // HTTP methods whose capitalization should be normalized
40947 var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT'];
40948
40949 function normalizeMethod(method) {
40950 var upcased = method.toUpperCase();
40951 return methods.indexOf(upcased) > -1 ? upcased : method;
40952 }
40953
40954 function Request(input, options) {
40955 options = options || {};
40956 var body = options.body;
40957
40958 if (input instanceof Request) {
40959 if (input.bodyUsed) {
40960 throw new TypeError('Already read');
40961 }
40962 this.url = input.url;
40963 this.credentials = input.credentials;
40964 if (!options.headers) {
40965 this.headers = new Headers(input.headers);
40966 }
40967 this.method = input.method;
40968 this.mode = input.mode;
40969 if (!body && input._bodyInit != null) {
40970 body = input._bodyInit;
40971 input.bodyUsed = true;
40972 }
40973 } else {
40974 this.url = String(input);
40975 }
40976
40977 this.credentials = options.credentials || this.credentials || 'omit';
40978 if (options.headers || !this.headers) {
40979 this.headers = new Headers(options.headers);
40980 }
40981 this.method = normalizeMethod(options.method || this.method || 'GET');
40982 this.mode = options.mode || this.mode || null;
40983 this.referrer = null;
40984
40985 if ((this.method === 'GET' || this.method === 'HEAD') && body) {
40986 throw new TypeError('Body not allowed for GET or HEAD requests');
40987 }
40988 this._initBody(body);
40989 }
40990
40991 Request.prototype.clone = function() {
40992 return new Request(this, { body: this._bodyInit });
40993 };
40994
40995 function decode(body) {
40996 var form = new FormData();
40997 body
40998 .trim()
40999 .split('&')
41000 .forEach(function(bytes) {
41001 if (bytes) {
41002 var split = bytes.split('=');
41003 var name = split.shift().replace(/\+/g, ' ');
41004 var value = split.join('=').replace(/\+/g, ' ');
41005 form.append(decodeURIComponent(name), decodeURIComponent(value));
41006 }
41007 });
41008 return form;
41009 }
41010
41011 function parseHeaders(rawHeaders) {
41012 var headers = new Headers();
41013 // Replace instances of \r\n and \n followed by at least one space or horizontal tab with a space
41014 // https://tools.ietf.org/html/rfc7230#section-3.2
41015 var preProcessedHeaders = rawHeaders.replace(/\r?\n[\t ]+/g, ' ');
41016 preProcessedHeaders.split(/\r?\n/).forEach(function(line) {
41017 var parts = line.split(':');
41018 var key = parts.shift().trim();
41019 if (key) {
41020 var value = parts.join(':').trim();
41021 headers.append(key, value);
41022 }
41023 });
41024 return headers;
41025 }
41026
41027 Body.call(Request.prototype);
41028
41029 function Response(bodyInit, options) {
41030 if (!options) {
41031 options = {};
41032 }
41033
41034 this.type = 'default';
41035 this.status = options.status === undefined ? 200 : options.status;
41036 this.ok = this.status >= 200 && this.status < 300;
41037 this.statusText = 'statusText' in options ? options.statusText : 'OK';
41038 this.headers = new Headers(options.headers);
41039 this.url = options.url || '';
41040 this._initBody(bodyInit);
41041 }
41042
41043 Body.call(Response.prototype);
41044
41045 Response.prototype.clone = function() {
41046 return new Response(this._bodyInit, {
41047 status: this.status,
41048 statusText: this.statusText,
41049 headers: new Headers(this.headers),
41050 url: this.url
41051 });
41052 };
41053
41054 Response.error = function() {
41055 var response = new Response(null, { status: 0, statusText: '' });
41056 response.type = 'error';
41057 return response;
41058 };
41059
41060 var redirectStatuses = [301, 302, 303, 307, 308];
41061
41062 Response.redirect = function(url, status) {
41063 if (redirectStatuses.indexOf(status) === -1) {
41064 throw new RangeError('Invalid status code');
41065 }
41066
41067 return new Response(null, { status: status, headers: { location: url } });
41068 };
41069
41070 self.Headers = Headers;
41071 self.Request = Request;
41072 self.Response = Response;
41073
41074 self.fetch = function(input, init) {
41075 return new Promise(function(resolve, reject) {
41076 var request = new Request(input, init);
41077 var xhr = new XMLHttpRequest();
41078
41079 xhr.onload = function() {
41080 var options = {
41081 status: xhr.status,
41082 statusText: xhr.statusText,
41083 headers: parseHeaders(xhr.getAllResponseHeaders() || '')
41084 };
41085 options.url =
41086 'responseURL' in xhr
41087 ? xhr.responseURL
41088 : options.headers.get('X-Request-URL');
41089 var body = 'response' in xhr ? xhr.response : xhr.responseText;
41090 resolve(new Response(body, options));
41091 };
41092
41093 xhr.onerror = function() {
41094 reject(new TypeError('Network request failed'));
41095 };
41096
41097 xhr.ontimeout = function() {
41098 reject(new TypeError('Network request failed'));
41099 };
41100
41101 xhr.open(request.method, request.url, true);
41102
41103 if (request.credentials === 'include') {
41104 xhr.withCredentials = true;
41105 } else if (request.credentials === 'omit') {
41106 xhr.withCredentials = false;
41107 }
41108
41109 if ('responseType' in xhr && support.blob) {
41110 xhr.responseType = 'blob';
41111 }
41112
41113 request.headers.forEach(function(value, name) {
41114 xhr.setRequestHeader(name, value);
41115 });
41116
41117 xhr.send(
41118 typeof request._bodyInit === 'undefined' ? null : request._bodyInit
41119 );
41120 });
41121 };
41122 self.fetch.polyfill = true;
41123 })(typeof self !== 'undefined' ? self : this);
41124 },
41125 {}
41126 ],
41127 38: [
41128 function(_dereq_, module, exports) {
41129 'use strict';
41130 var _main = _interopRequireDefault(_dereq_('./core/main'));
41131 _dereq_('./core/constants');
41132 _dereq_('./core/environment');
41133 _dereq_('./core/friendly_errors/stacktrace');
41134 _dereq_('./core/friendly_errors/validate_params');
41135 _dereq_('./core/friendly_errors/file_errors');
41136 _dereq_('./core/friendly_errors/fes_core');
41137 _dereq_('./core/helpers');
41138 _dereq_('./core/legacy');
41139 _dereq_('./core/preload');
41140 _dereq_('./core/p5.Element');
41141 _dereq_('./core/p5.Graphics');
41142 _dereq_('./core/p5.Renderer');
41143 _dereq_('./core/p5.Renderer2D');
41144 _dereq_('./core/rendering');
41145 _dereq_('./core/shim');
41146 _dereq_('./core/structure');
41147 _dereq_('./core/transform');
41148 _dereq_('./core/shape/2d_primitives');
41149 _dereq_('./core/shape/attributes');
41150 _dereq_('./core/shape/curves');
41151 _dereq_('./core/shape/vertex');
41152
41153 _dereq_('./color/color_conversion');
41154 _dereq_('./color/creating_reading');
41155 _dereq_('./color/p5.Color');
41156 _dereq_('./color/setting');
41157
41158 _dereq_('./data/p5.TypedDict');
41159 _dereq_('./data/local_storage.js');
41160
41161 _dereq_('./dom/dom');
41162
41163 _dereq_('./events/acceleration');
41164 _dereq_('./events/keyboard');
41165 _dereq_('./events/mouse');
41166 _dereq_('./events/touch');
41167
41168 _dereq_('./image/filters');
41169 _dereq_('./image/image');
41170 _dereq_('./image/loading_displaying');
41171 _dereq_('./image/p5.Image');
41172 _dereq_('./image/pixels');
41173
41174 _dereq_('./io/files');
41175 _dereq_('./io/p5.Table');
41176 _dereq_('./io/p5.TableRow');
41177 _dereq_('./io/p5.XML');
41178
41179 _dereq_('./math/calculation');
41180 _dereq_('./math/math');
41181 _dereq_('./math/noise');
41182 _dereq_('./math/p5.Vector');
41183 _dereq_('./math/random');
41184 _dereq_('./math/trigonometry');
41185
41186 _dereq_('./typography/attributes');
41187 _dereq_('./typography/loading_displaying');
41188 _dereq_('./typography/p5.Font');
41189
41190 _dereq_('./utilities/array_functions');
41191 _dereq_('./utilities/conversion');
41192 _dereq_('./utilities/string_functions');
41193 _dereq_('./utilities/time_date');
41194
41195 _dereq_('./webgl/3d_primitives');
41196 _dereq_('./webgl/interaction');
41197 _dereq_('./webgl/light');
41198 _dereq_('./webgl/loading');
41199 _dereq_('./webgl/material');
41200 _dereq_('./webgl/p5.Camera');
41201 _dereq_('./webgl/p5.Geometry');
41202 _dereq_('./webgl/p5.Matrix');
41203 _dereq_('./webgl/p5.RendererGL.Immediate');
41204 _dereq_('./webgl/p5.RendererGL');
41205 _dereq_('./webgl/p5.RendererGL.Retained');
41206 _dereq_('./webgl/p5.Shader');
41207 _dereq_('./webgl/p5.RenderBuffer');
41208 _dereq_('./webgl/p5.Texture');
41209 _dereq_('./webgl/text');
41210
41211 _dereq_('./core/init');
41212 function _interopRequireDefault(obj) {
41213 return obj && obj.__esModule ? obj : { default: obj };
41214 } // core
41215 // color
41216 // data
41217 // DOM
41218 // events
41219 // image
41220 // io
41221 // math
41222 // typography
41223 // utilities
41224 // webgl
41225 module.exports = _main.default;
41226 },
41227 {
41228 './color/color_conversion': 39,
41229 './color/creating_reading': 40,
41230 './color/p5.Color': 41,
41231 './color/setting': 42,
41232 './core/constants': 43,
41233 './core/environment': 44,
41234 './core/friendly_errors/fes_core': 46,
41235 './core/friendly_errors/file_errors': 47,
41236 './core/friendly_errors/stacktrace': 48,
41237 './core/friendly_errors/validate_params': 49,
41238 './core/helpers': 50,
41239 './core/init': 51,
41240 './core/legacy': 53,
41241 './core/main': 54,
41242 './core/p5.Element': 55,
41243 './core/p5.Graphics': 56,
41244 './core/p5.Renderer': 57,
41245 './core/p5.Renderer2D': 58,
41246 './core/preload': 59,
41247 './core/rendering': 60,
41248 './core/shape/2d_primitives': 61,
41249 './core/shape/attributes': 62,
41250 './core/shape/curves': 63,
41251 './core/shape/vertex': 64,
41252 './core/shim': 65,
41253 './core/structure': 66,
41254 './core/transform': 67,
41255 './data/local_storage.js': 68,
41256 './data/p5.TypedDict': 69,
41257 './dom/dom': 70,
41258 './events/acceleration': 71,
41259 './events/keyboard': 72,
41260 './events/mouse': 73,
41261 './events/touch': 74,
41262 './image/filters': 75,
41263 './image/image': 76,
41264 './image/loading_displaying': 77,
41265 './image/p5.Image': 78,
41266 './image/pixels': 79,
41267 './io/files': 80,
41268 './io/p5.Table': 81,
41269 './io/p5.TableRow': 82,
41270 './io/p5.XML': 83,
41271 './math/calculation': 84,
41272 './math/math': 85,
41273 './math/noise': 86,
41274 './math/p5.Vector': 87,
41275 './math/random': 88,
41276 './math/trigonometry': 89,
41277 './typography/attributes': 90,
41278 './typography/loading_displaying': 91,
41279 './typography/p5.Font': 92,
41280 './utilities/array_functions': 93,
41281 './utilities/conversion': 94,
41282 './utilities/string_functions': 95,
41283 './utilities/time_date': 96,
41284 './webgl/3d_primitives': 97,
41285 './webgl/interaction': 98,
41286 './webgl/light': 99,
41287 './webgl/loading': 100,
41288 './webgl/material': 101,
41289 './webgl/p5.Camera': 102,
41290 './webgl/p5.Geometry': 103,
41291 './webgl/p5.Matrix': 104,
41292 './webgl/p5.RenderBuffer': 105,
41293 './webgl/p5.RendererGL': 108,
41294 './webgl/p5.RendererGL.Immediate': 106,
41295 './webgl/p5.RendererGL.Retained': 107,
41296 './webgl/p5.Shader': 109,
41297 './webgl/p5.Texture': 110,
41298 './webgl/text': 111
41299 }
41300 ],
41301 39: [
41302 function(_dereq_, module, exports) {
41303 'use strict';
41304 Object.defineProperty(exports, '__esModule', { value: true });
41305 exports.default = void 0;
41306
41307 var _main = _interopRequireDefault(_dereq_('../core/main'));
41308 function _interopRequireDefault(obj) {
41309 return obj && obj.__esModule ? obj : { default: obj };
41310 }
41311 /**
41312 * @module Color
41313 * @submodule Color Conversion
41314 * @for p5
41315 * @requires core
41316 */ /**
41317 * Conversions adapted from <http://www.easyrgb.com/en/math.php>.
41318 *
41319 * In these functions, hue is always in the range [0, 1], just like all other
41320 * components are in the range [0, 1]. 'Brightness' and 'value' are used
41321 * interchangeably.
41322 */ _main.default.ColorConversion = {};
41323 /**
41324 * Convert an HSBA array to HSLA.
41325 */ _main.default.ColorConversion._hsbaToHSLA = function(hsba) {
41326 var hue = hsba[0];
41327 var sat = hsba[1];
41328 var val = hsba[2]; // Calculate lightness.
41329 var li = (2 - sat) * val / 2; // Convert saturation.
41330 if (li !== 0) {
41331 if (li === 1) {
41332 sat = 0;
41333 } else if (li < 0.5) {
41334 sat = sat / (2 - sat);
41335 } else {
41336 sat = sat * val / (2 - li * 2);
41337 }
41338 }
41339
41340 // Hue and alpha stay the same.
41341 return [hue, sat, li, hsba[3]];
41342 };
41343
41344 /**
41345 * Convert an HSBA array to RGBA.
41346 */
41347 _main.default.ColorConversion._hsbaToRGBA = function(hsba) {
41348 var hue = hsba[0] * 6; // We will split hue into 6 sectors.
41349 var sat = hsba[1];
41350 var val = hsba[2];
41351
41352 var RGBA = [];
41353
41354 if (sat === 0) {
41355 RGBA = [val, val, val, hsba[3]]; // Return early if grayscale.
41356 } else {
41357 var sector = Math.floor(hue);
41358 var tint1 = val * (1 - sat);
41359 var tint2 = val * (1 - sat * (hue - sector));
41360 var tint3 = val * (1 - sat * (1 + sector - hue));
41361 var red, green, blue;
41362 if (sector === 1) {
41363 // Yellow to green.
41364 red = tint2;
41365 green = val;
41366 blue = tint1;
41367 } else if (sector === 2) {
41368 // Green to cyan.
41369 red = tint1;
41370 green = val;
41371 blue = tint3;
41372 } else if (sector === 3) {
41373 // Cyan to blue.
41374 red = tint1;
41375 green = tint2;
41376 blue = val;
41377 } else if (sector === 4) {
41378 // Blue to magenta.
41379 red = tint3;
41380 green = tint1;
41381 blue = val;
41382 } else if (sector === 5) {
41383 // Magenta to red.
41384 red = val;
41385 green = tint1;
41386 blue = tint2;
41387 } else {
41388 // Red to yellow (sector could be 0 or 6).
41389 red = val;
41390 green = tint3;
41391 blue = tint1;
41392 }
41393 RGBA = [red, green, blue, hsba[3]];
41394 }
41395
41396 return RGBA;
41397 };
41398
41399 /**
41400 * Convert an HSLA array to HSBA.
41401 */
41402 _main.default.ColorConversion._hslaToHSBA = function(hsla) {
41403 var hue = hsla[0];
41404 var sat = hsla[1];
41405 var li = hsla[2];
41406
41407 // Calculate brightness.
41408 var val;
41409 if (li < 0.5) {
41410 val = (1 + sat) * li;
41411 } else {
41412 val = li + sat - li * sat;
41413 }
41414
41415 // Convert saturation.
41416 sat = 2 * (val - li) / val;
41417
41418 // Hue and alpha stay the same.
41419 return [hue, sat, val, hsla[3]];
41420 };
41421
41422 /**
41423 * Convert an HSLA array to RGBA.
41424 *
41425 * We need to change basis from HSLA to something that can be more easily be
41426 * projected onto RGBA. We will choose hue and brightness as our first two
41427 * components, and pick a convenient third one ('zest') so that we don't need
41428 * to calculate formal HSBA saturation.
41429 */
41430 _main.default.ColorConversion._hslaToRGBA = function(hsla) {
41431 var hue = hsla[0] * 6; // We will split hue into 6 sectors.
41432 var sat = hsla[1];
41433 var li = hsla[2];
41434
41435 var RGBA = [];
41436
41437 if (sat === 0) {
41438 RGBA = [li, li, li, hsla[3]]; // Return early if grayscale.
41439 } else {
41440 // Calculate brightness.
41441 var val;
41442 if (li < 0.5) {
41443 val = (1 + sat) * li;
41444 } else {
41445 val = li + sat - li * sat;
41446 }
41447
41448 // Define zest.
41449 var zest = 2 * li - val;
41450
41451 // Implement projection (project onto green by default).
41452 var hzvToRGB = function hzvToRGB(hue, zest, val) {
41453 if (hue < 0) {
41454 // Hue must wrap to allow projection onto red and blue.
41455 hue += 6;
41456 } else if (hue >= 6) {
41457 hue -= 6;
41458 }
41459 if (hue < 1) {
41460 // Red to yellow (increasing green).
41461 return zest + (val - zest) * hue;
41462 } else if (hue < 3) {
41463 // Yellow to cyan (greatest green).
41464 return val;
41465 } else if (hue < 4) {
41466 // Cyan to blue (decreasing green).
41467 return zest + (val - zest) * (4 - hue);
41468 } else {
41469 // Blue to red (least green).
41470 return zest;
41471 }
41472 };
41473
41474 // Perform projections, offsetting hue as necessary.
41475 RGBA = [
41476 hzvToRGB(hue + 2, zest, val),
41477 hzvToRGB(hue, zest, val),
41478 hzvToRGB(hue - 2, zest, val),
41479 hsla[3]
41480 ];
41481 }
41482
41483 return RGBA;
41484 };
41485
41486 /**
41487 * Convert an RGBA array to HSBA.
41488 */
41489 _main.default.ColorConversion._rgbaToHSBA = function(rgba) {
41490 var red = rgba[0];
41491 var green = rgba[1];
41492 var blue = rgba[2];
41493
41494 var val = Math.max(red, green, blue);
41495 var chroma = val - Math.min(red, green, blue);
41496
41497 var hue, sat;
41498 if (chroma === 0) {
41499 // Return early if grayscale.
41500 hue = 0;
41501 sat = 0;
41502 } else {
41503 sat = chroma / val;
41504 if (red === val) {
41505 // Magenta to yellow.
41506 hue = (green - blue) / chroma;
41507 } else if (green === val) {
41508 // Yellow to cyan.
41509 hue = 2 + (blue - red) / chroma;
41510 } else if (blue === val) {
41511 // Cyan to magenta.
41512 hue = 4 + (red - green) / chroma;
41513 }
41514 if (hue < 0) {
41515 // Confine hue to the interval [0, 1).
41516 hue += 6;
41517 } else if (hue >= 6) {
41518 hue -= 6;
41519 }
41520 }
41521
41522 return [hue / 6, sat, val, rgba[3]];
41523 };
41524
41525 /**
41526 * Convert an RGBA array to HSLA.
41527 */
41528 _main.default.ColorConversion._rgbaToHSLA = function(rgba) {
41529 var red = rgba[0];
41530 var green = rgba[1];
41531 var blue = rgba[2];
41532
41533 var val = Math.max(red, green, blue);
41534 var min = Math.min(red, green, blue);
41535 var li = val + min; // We will halve this later.
41536 var chroma = val - min;
41537
41538 var hue, sat;
41539 if (chroma === 0) {
41540 // Return early if grayscale.
41541 hue = 0;
41542 sat = 0;
41543 } else {
41544 if (li < 1) {
41545 sat = chroma / li;
41546 } else {
41547 sat = chroma / (2 - li);
41548 }
41549 if (red === val) {
41550 // Magenta to yellow.
41551 hue = (green - blue) / chroma;
41552 } else if (green === val) {
41553 // Yellow to cyan.
41554 hue = 2 + (blue - red) / chroma;
41555 } else if (blue === val) {
41556 // Cyan to magenta.
41557 hue = 4 + (red - green) / chroma;
41558 }
41559 if (hue < 0) {
41560 // Confine hue to the interval [0, 1).
41561 hue += 6;
41562 } else if (hue >= 6) {
41563 hue -= 6;
41564 }
41565 }
41566
41567 return [hue / 6, sat, li / 2, rgba[3]];
41568 };
41569 var _default = _main.default.ColorConversion;
41570 exports.default = _default;
41571 },
41572 { '../core/main': 54 }
41573 ],
41574 40: [
41575 function(_dereq_, module, exports) {
41576 'use strict';
41577 function _typeof(obj) {
41578 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
41579 _typeof = function _typeof(obj) {
41580 return typeof obj;
41581 };
41582 } else {
41583 _typeof = function _typeof(obj) {
41584 return obj &&
41585 typeof Symbol === 'function' &&
41586 obj.constructor === Symbol &&
41587 obj !== Symbol.prototype
41588 ? 'symbol'
41589 : typeof obj;
41590 };
41591 }
41592 return _typeof(obj);
41593 }
41594 Object.defineProperty(exports, '__esModule', { value: true });
41595 exports.default = void 0;
41596
41597 var _main = _interopRequireDefault(_dereq_('../core/main'));
41598 var constants = _interopRequireWildcard(_dereq_('../core/constants'));
41599 _dereq_('./p5.Color');
41600 _dereq_('../core/friendly_errors/validate_params');
41601 _dereq_('../core/friendly_errors/file_errors');
41602 _dereq_('../core/friendly_errors/fes_core');
41603 function _getRequireWildcardCache() {
41604 if (typeof WeakMap !== 'function') return null;
41605 var cache = new WeakMap();
41606 _getRequireWildcardCache = function _getRequireWildcardCache() {
41607 return cache;
41608 };
41609 return cache;
41610 }
41611 function _interopRequireWildcard(obj) {
41612 if (obj && obj.__esModule) {
41613 return obj;
41614 }
41615 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) {
41616 return { default: obj };
41617 }
41618 var cache = _getRequireWildcardCache();
41619 if (cache && cache.has(obj)) {
41620 return cache.get(obj);
41621 }
41622 var newObj = {};
41623 var hasPropertyDescriptor =
41624 Object.defineProperty && Object.getOwnPropertyDescriptor;
41625 for (var key in obj) {
41626 if (Object.prototype.hasOwnProperty.call(obj, key)) {
41627 var desc = hasPropertyDescriptor
41628 ? Object.getOwnPropertyDescriptor(obj, key)
41629 : null;
41630 if (desc && (desc.get || desc.set)) {
41631 Object.defineProperty(newObj, key, desc);
41632 } else {
41633 newObj[key] = obj[key];
41634 }
41635 }
41636 }
41637 newObj.default = obj;
41638 if (cache) {
41639 cache.set(obj, newObj);
41640 }
41641 return newObj;
41642 }
41643 function _interopRequireDefault(obj) {
41644 return obj && obj.__esModule ? obj : { default: obj };
41645 }
41646 /**
41647 * @module Color
41648 * @submodule Creating & Reading
41649 * @for p5
41650 * @requires core
41651 * @requires constants
41652 */ /**
41653 * Extracts the alpha value from a color or pixel array.
41654 *
41655 * @method alpha
41656 * @param {p5.Color|Number[]|String} color <a href="#/p5.Color">p5.Color</a> object, color components,
41657 * or CSS color
41658 * @return {Number} the alpha value
41659 *
41660 * @example
41661 * <div>
41662 * <code>
41663 * noStroke();
41664 * let c = color(0, 126, 255, 102);
41665 * fill(c);
41666 * rect(15, 15, 35, 70);
41667 * let value = alpha(c); // Sets 'value' to 102
41668 * fill(value);
41669 * rect(50, 15, 35, 70);
41670 * </code>
41671 * </div>
41672 *
41673 * @alt
41674 * Left half of canvas light blue and right half light charcoal grey.
41675 */ _main.default.prototype.alpha = function(c) {
41676 _main.default._validateParameters('alpha', arguments);
41677 return this.color(c)._getAlpha();
41678 };
41679
41680 /**
41681 * Extracts the blue value from a color or pixel array.
41682 *
41683 * @method blue
41684 * @param {p5.Color|Number[]|String} color <a href="#/p5.Color">p5.Color</a> object, color components,
41685 * or CSS color
41686 * @return {Number} the blue value
41687 * @example
41688 * <div>
41689 * <code>
41690 * let c = color(175, 100, 220);
41691 * fill(c);
41692 * rect(15, 20, 35, 60); // Draw left rectangle
41693 * let blueValue = blue(c);
41694 * fill(0, 0, blueValue);
41695 * rect(50, 20, 35, 60); // Draw right rectangle
41696 * </code>
41697 * </div>
41698 *
41699 * @alt
41700 * Left half of canvas light purple and right half a royal blue.
41701 */
41702 _main.default.prototype.blue = function(c) {
41703 _main.default._validateParameters('blue', arguments);
41704 return this.color(c)._getBlue();
41705 };
41706
41707 /**
41708 * Extracts the HSB brightness value from a color or pixel array.
41709 *
41710 * @method brightness
41711 * @param {p5.Color|Number[]|String} color <a href="#/p5.Color">p5.Color</a> object, color components,
41712 * or CSS color
41713 * @return {Number} the brightness value
41714 *
41715 * @example
41716 * <div>
41717 * <code>
41718 * noStroke();
41719 * colorMode(HSB, 255);
41720 * let c = color(0, 126, 255);
41721 * fill(c);
41722 * rect(15, 20, 35, 60);
41723 * let value = brightness(c); // Sets 'value' to 255
41724 * fill(value);
41725 * rect(50, 20, 35, 60);
41726 * </code>
41727 * </div>
41728 *
41729 * <div>
41730 * <code>
41731 * noStroke();
41732 * colorMode(HSB, 255);
41733 * let c = color('hsb(60, 100%, 50%)');
41734 * fill(c);
41735 * rect(15, 20, 35, 60);
41736 * let value = brightness(c); // A 'value' of 50% is 127.5
41737 * fill(value);
41738 * rect(50, 20, 35, 60);
41739 * </code>
41740 * </div>
41741 *
41742 * @alt
41743 * Left half of canvas salmon pink and the right half with it's brightness colored white.
41744 * Left half of canvas olive colored and the right half with it's brightness color gray.
41745 */
41746 _main.default.prototype.brightness = function(c) {
41747 _main.default._validateParameters('brightness', arguments);
41748 return this.color(c)._getBrightness();
41749 };
41750
41751 /**
41752 * Creates colors for storing in variables of the color datatype. The
41753 * parameters are interpreted as RGB or HSB values depending on the
41754 * current <a href="#/p5/colorMode">colorMode()</a>. The default mode is RGB values from 0 to 255
41755 * and, therefore, the function call color(255, 204, 0) will return a
41756 * bright yellow color.
41757 *
41758 * Note that if only one value is provided to <a href="#/p5/color">color()</a>, it will be interpreted
41759 * as a grayscale value. Add a second value, and it will be used for alpha
41760 * transparency. When three values are specified, they are interpreted as
41761 * either RGB or HSB values. Adding a fourth value applies alpha
41762 * transparency.
41763 *
41764 * If a single string argument is provided, RGB, RGBA and Hex CSS color
41765 * strings and all named color strings are supported. In this case, an alpha
41766 * number value as a second argument is not supported, the RGBA form should be
41767 * used.
41768 *
41769 * @method color
41770 * @param {Number} gray number specifying value between white and black.
41771 * @param {Number} [alpha] alpha value relative to current color range
41772 * (default is 0-255)
41773 * @return {p5.Color} resulting color
41774 *
41775 * @example
41776 * <div>
41777 * <code>
41778 * let c = color(255, 204, 0);
41779 * fill(c);
41780 * noStroke();
41781 * rect(30, 20, 55, 55);
41782 * </code>
41783 * </div>
41784 *
41785 * <div>
41786 * <code>
41787 * let c = color(255, 204, 0);
41788 * fill(c);
41789 * noStroke();
41790 * ellipse(25, 25, 80, 80); // Draw left circle
41791 * // Using only one value generates a grayscale value.
41792 * c = color(65);
41793 * fill(c);
41794 * ellipse(75, 75, 80, 80);
41795 * </code>
41796 * </div>
41797 *
41798 * <div>
41799 * <code>
41800 * // You can use named SVG & CSS colors
41801 * let c = color('magenta');
41802 * fill(c);
41803 * noStroke();
41804 * rect(20, 20, 60, 60);
41805 * </code>
41806 * </div>
41807 *
41808 * <div>
41809 * <code>
41810 * // Example of hex color codes
41811 * noStroke();
41812 * let c = color('#0f0');
41813 * fill(c);
41814 * rect(0, 10, 45, 80);
41815 * c = color('#00ff00');
41816 * fill(c);
41817 * rect(55, 10, 45, 80);
41818 * </code>
41819 * </div>
41820 *
41821 * <div>
41822 * <code>
41823 * // RGB and RGBA color strings are also supported
41824 * // these all set to the same color (solid blue)
41825 * let c;
41826 * noStroke();
41827 * c = color('rgb(0,0,255)');
41828 * fill(c);
41829 * rect(10, 10, 35, 35); // Draw rectangle
41830 * c = color('rgb(0%, 0%, 100%)');
41831 * fill(c);
41832 * rect(55, 10, 35, 35); // Draw rectangle
41833 * c = color('rgba(0, 0, 255, 1)');
41834 * fill(c);
41835 * rect(10, 55, 35, 35); // Draw rectangle
41836 * c = color('rgba(0%, 0%, 100%, 1)');
41837 * fill(c);
41838 * rect(55, 55, 35, 35); // Draw rectangle
41839 * </code>
41840 * </div>
41841 *
41842 * <div>
41843 * <code>
41844 * // HSL color can also be specified by value
41845 * let c = color('hsl(160, 100%, 50%)');
41846 * noStroke();
41847 * fill(c);
41848 * rect(0, 10, 45, 80); // Draw rectangle
41849 * c = color('hsla(160, 100%, 50%, 0.5)');
41850 * fill(c);
41851 * rect(55, 10, 45, 80); // Draw rectangle
41852 * </code>
41853 * </div>
41854 *
41855 * <div>
41856 * <code>
41857 * // HSB color can also be specified
41858 * let c = color('hsb(160, 100%, 50%)');
41859 * noStroke();
41860 * fill(c);
41861 * rect(0, 10, 45, 80); // Draw rectangle
41862 * c = color('hsba(160, 100%, 50%, 0.5)');
41863 * fill(c);
41864 * rect(55, 10, 45, 80); // Draw rectangle
41865 * </code>
41866 * </div>
41867 *
41868 * <div>
41869 * <code>
41870 * noStroke();
41871 * let c = color(50, 55, 100);
41872 * fill(c);
41873 * rect(0, 10, 45, 80); // Draw left rect
41874 * colorMode(HSB, 100);
41875 * c = color(50, 55, 100);
41876 * fill(c);
41877 * rect(55, 10, 45, 80);
41878 * </code>
41879 * </div>
41880 *
41881 * @alt
41882 * Yellow rect in middle right of canvas, with 55 pixel width and height.
41883 * Yellow ellipse in top left of canvas, black ellipse in bottom right,both 80x80.
41884 * Bright fuchsia rect in middle of canvas, 60 pixel width and height.
41885 * Two bright green rects on opposite sides of the canvas, both 45x80.
41886 * Four blue rects in each corner of the canvas, each are 35x35.
41887 * Bright sea green rect on left and darker rect on right of canvas, both 45x80.
41888 * Dark green rect on left and lighter green rect on right of canvas, both 45x80.
41889 * Dark blue rect on left and light teal rect on right of canvas, both 45x80.
41890 */
41891
41892 /**
41893 * @method color
41894 * @param {Number} v1 red or hue value relative to
41895 * the current color range
41896 * @param {Number} v2 green or saturation value
41897 * relative to the current color range
41898 * @param {Number} v3 blue or brightness value
41899 * relative to the current color range
41900 * @param {Number} [alpha]
41901 * @return {p5.Color}
41902 */
41903
41904 /**
41905 * @method color
41906 * @param {String} value a color string
41907 * @return {p5.Color}
41908 */
41909
41910 /**
41911 * @method color
41912 * @param {Number[]} values an array containing the red,green,blue &
41913 * and alpha components of the color
41914 * @return {p5.Color}
41915 */
41916
41917 /**
41918 * @method color
41919 * @param {p5.Color} color
41920 * @return {p5.Color}
41921 */
41922 _main.default.prototype.color = function() {
41923 _main.default._validateParameters('color', arguments);
41924 if (arguments[0] instanceof _main.default.Color) {
41925 return arguments[0]; // Do nothing if argument is already a color object.
41926 }
41927
41928 var args = arguments[0] instanceof Array ? arguments[0] : arguments;
41929 return new _main.default.Color(this, args);
41930 };
41931
41932 /**
41933 * Extracts the green value from a color or pixel array.
41934 *
41935 * @method green
41936 * @param {p5.Color|Number[]|String} color <a href="#/p5.Color">p5.Color</a> object, color components,
41937 * or CSS color
41938 * @return {Number} the green value
41939 * @example
41940 * <div>
41941 * <code>
41942 * let c = color(20, 75, 200); // Define color 'c'
41943 * fill(c); // Use color variable 'c' as fill color
41944 * rect(15, 20, 35, 60); // Draw left rectangle
41945 *
41946 * let greenValue = green(c); // Get green in 'c'
41947 * print(greenValue); // Print "75.0"
41948 * fill(0, greenValue, 0); // Use 'greenValue' in new fill
41949 * rect(50, 20, 35, 60); // Draw right rectangle
41950 * </code>
41951 * </div>
41952 *
41953 * @alt
41954 * blue rect on left and green on right, both with black outlines & 35x60.
41955 */
41956 _main.default.prototype.green = function(c) {
41957 _main.default._validateParameters('green', arguments);
41958 return this.color(c)._getGreen();
41959 };
41960
41961 /**
41962 * Extracts the hue value from a color or pixel array.
41963 *
41964 * Hue exists in both HSB and HSL. This function will return the
41965 * HSB-normalized hue when supplied with an HSB color object (or when supplied
41966 * with a pixel array while the color mode is HSB), but will default to the
41967 * HSL-normalized hue otherwise. (The values will only be different if the
41968 * maximum hue setting for each system is different.)
41969 *
41970 * @method hue
41971 * @param {p5.Color|Number[]|String} color <a href="#/p5.Color">p5.Color</a> object, color components,
41972 * or CSS color
41973 * @return {Number} the hue
41974 * @example
41975 * <div>
41976 * <code>
41977 * noStroke();
41978 * colorMode(HSB, 255);
41979 * let c = color(0, 126, 255);
41980 * fill(c);
41981 * rect(15, 20, 35, 60);
41982 * let value = hue(c); // Sets 'value' to "0"
41983 * fill(value);
41984 * rect(50, 20, 35, 60);
41985 * </code>
41986 * </div>
41987 *
41988 * @alt
41989 * salmon pink rect on left and black on right, both 35x60.
41990 */
41991 _main.default.prototype.hue = function(c) {
41992 _main.default._validateParameters('hue', arguments);
41993 return this.color(c)._getHue();
41994 };
41995
41996 /**
41997 * Blends two colors to find a third color somewhere between them. The amt
41998 * parameter is the amount to interpolate between the two values where 0.0
41999 * equal to the first color, 0.1 is very near the first color, 0.5 is halfway
42000 * in between, etc. An amount below 0 will be treated as 0. Likewise, amounts
42001 * above 1 will be capped at 1. This is different from the behavior of <a href="#/p5/lerp">lerp()</a>,
42002 * but necessary because otherwise numbers outside the range will produce
42003 * strange and unexpected colors.
42004 *
42005 * The way that colors are interpolated depends on the current color mode.
42006 *
42007 * @method lerpColor
42008 * @param {p5.Color} c1 interpolate from this color
42009 * @param {p5.Color} c2 interpolate to this color
42010 * @param {Number} amt number between 0 and 1
42011 * @return {p5.Color} interpolated color
42012 *
42013 * @example
42014 * <div>
42015 * <code>
42016 * colorMode(RGB);
42017 * stroke(255);
42018 * background(51);
42019 * let from = color(218, 165, 32);
42020 * let to = color(72, 61, 139);
42021 * colorMode(RGB); // Try changing to HSB.
42022 * let interA = lerpColor(from, to, 0.33);
42023 * let interB = lerpColor(from, to, 0.66);
42024 * fill(from);
42025 * rect(10, 20, 20, 60);
42026 * fill(interA);
42027 * rect(30, 20, 20, 60);
42028 * fill(interB);
42029 * rect(50, 20, 20, 60);
42030 * fill(to);
42031 * rect(70, 20, 20, 60);
42032 * </code>
42033 * </div>
42034 *
42035 * @alt
42036 * 4 rects one tan, brown, brownish purple, purple, with white outlines & 20x60
42037 */
42038
42039 _main.default.prototype.lerpColor = function(c1, c2, amt) {
42040 _main.default._validateParameters('lerpColor', arguments);
42041 var mode = this._colorMode;
42042 var maxes = this._colorMaxes;
42043 var l0, l1, l2, l3;
42044 var fromArray, toArray;
42045
42046 if (mode === constants.RGB) {
42047 fromArray = c1.levels.map(function(level) {
42048 return level / 255;
42049 });
42050 toArray = c2.levels.map(function(level) {
42051 return level / 255;
42052 });
42053 } else if (mode === constants.HSB) {
42054 c1._getBrightness(); // Cache hsba so it definitely exists.
42055 c2._getBrightness();
42056 fromArray = c1.hsba;
42057 toArray = c2.hsba;
42058 } else if (mode === constants.HSL) {
42059 c1._getLightness(); // Cache hsla so it definitely exists.
42060 c2._getLightness();
42061 fromArray = c1.hsla;
42062 toArray = c2.hsla;
42063 } else {
42064 throw new Error(''.concat(mode, 'cannot be used for interpolation.'));
42065 }
42066
42067 // Prevent extrapolation.
42068 amt = Math.max(Math.min(amt, 1), 0);
42069
42070 // Define lerp here itself if user isn't using math module.
42071 // Maintains the definition as found in math/calculation.js
42072 if (typeof this.lerp === 'undefined') {
42073 this.lerp = function(start, stop, amt) {
42074 return amt * (stop - start) + start;
42075 };
42076 }
42077
42078 // Perform interpolation.
42079 l0 = this.lerp(fromArray[0], toArray[0], amt);
42080 l1 = this.lerp(fromArray[1], toArray[1], amt);
42081 l2 = this.lerp(fromArray[2], toArray[2], amt);
42082 l3 = this.lerp(fromArray[3], toArray[3], amt);
42083
42084 // Scale components.
42085 l0 *= maxes[mode][0];
42086 l1 *= maxes[mode][1];
42087 l2 *= maxes[mode][2];
42088 l3 *= maxes[mode][3];
42089
42090 return this.color(l0, l1, l2, l3);
42091 };
42092
42093 /**
42094 * Extracts the HSL lightness value from a color or pixel array.
42095 *
42096 * @method lightness
42097 * @param {p5.Color|Number[]|String} color <a href="#/p5.Color">p5.Color</a> object, color components,
42098 * or CSS color
42099 * @return {Number} the lightness
42100 *
42101 * @example
42102 * <div>
42103 * <code>
42104 * noStroke();
42105 * colorMode(HSL);
42106 * let c = color(156, 100, 50, 1);
42107 * fill(c);
42108 * rect(15, 20, 35, 60);
42109 * let value = lightness(c); // Sets 'value' to 50
42110 * fill(value);
42111 * rect(50, 20, 35, 60);
42112 * </code>
42113 * </div>
42114 *
42115 * @alt
42116 * light pastel green rect on left and dark grey rect on right, both 35x60.
42117 */
42118 _main.default.prototype.lightness = function(c) {
42119 _main.default._validateParameters('lightness', arguments);
42120 return this.color(c)._getLightness();
42121 };
42122
42123 /**
42124 * Extracts the red value from a color or pixel array.
42125 *
42126 * @method red
42127 * @param {p5.Color|Number[]|String} color <a href="#/p5.Color">p5.Color</a> object, color components,
42128 * or CSS color
42129 * @return {Number} the red value
42130 * @example
42131 * <div>
42132 * <code>
42133 * let c = color(255, 204, 0); // Define color 'c'
42134 * fill(c); // Use color variable 'c' as fill color
42135 * rect(15, 20, 35, 60); // Draw left rectangle
42136 *
42137 * let redValue = red(c); // Get red in 'c'
42138 * print(redValue); // Print "255.0"
42139 * fill(redValue, 0, 0); // Use 'redValue' in new fill
42140 * rect(50, 20, 35, 60); // Draw right rectangle
42141 * </code>
42142 * </div>
42143 *
42144 * <div class="norender">
42145 * <code>
42146 * colorMode(RGB, 255); // Sets the range for red, green, and blue to 255
42147 * let c = color(127, 255, 0);
42148 * colorMode(RGB, 1); // Sets the range for red, green, and blue to 1
42149 * let myColor = red(c);
42150 * print(myColor); // 0.4980392156862745
42151 * </code>
42152 * </div>
42153 *
42154 * @alt
42155 * yellow rect on left and red rect on right, both with black outlines and 35x60.
42156 * grey canvas
42157 */
42158 _main.default.prototype.red = function(c) {
42159 _main.default._validateParameters('red', arguments);
42160 return this.color(c)._getRed();
42161 };
42162
42163 /**
42164 * Extracts the saturation value from a color or pixel array.
42165 *
42166 * Saturation is scaled differently in HSB and HSL. This function will return
42167 * the HSB saturation when supplied with an HSB color object (or when supplied
42168 * with a pixel array while the color mode is HSB), but will default to the
42169 * HSL saturation otherwise.
42170 *
42171 * @method saturation
42172 * @param {p5.Color|Number[]|String} color <a href="#/p5.Color">p5.Color</a> object, color components,
42173 * or CSS color
42174 * @return {Number} the saturation value
42175 * @example
42176 * <div>
42177 * <code>
42178 * noStroke();
42179 * colorMode(HSB, 255);
42180 * let c = color(0, 126, 255);
42181 * fill(c);
42182 * rect(15, 20, 35, 60);
42183 * let value = saturation(c); // Sets 'value' to 126
42184 * fill(value);
42185 * rect(50, 20, 35, 60);
42186 * </code>
42187 * </div>
42188 *
42189 * @alt
42190 *deep pink rect on left and grey rect on right, both 35x60.
42191 */
42192 _main.default.prototype.saturation = function(c) {
42193 _main.default._validateParameters('saturation', arguments);
42194 return this.color(c)._getSaturation();
42195 };
42196 var _default = _main.default;
42197 exports.default = _default;
42198 },
42199 {
42200 '../core/constants': 43,
42201 '../core/friendly_errors/fes_core': 46,
42202 '../core/friendly_errors/file_errors': 47,
42203 '../core/friendly_errors/validate_params': 49,
42204 '../core/main': 54,
42205 './p5.Color': 41
42206 }
42207 ],
42208 41: [
42209 function(_dereq_, module, exports) {
42210 'use strict';
42211 function _typeof(obj) {
42212 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
42213 _typeof = function _typeof(obj) {
42214 return typeof obj;
42215 };
42216 } else {
42217 _typeof = function _typeof(obj) {
42218 return obj &&
42219 typeof Symbol === 'function' &&
42220 obj.constructor === Symbol &&
42221 obj !== Symbol.prototype
42222 ? 'symbol'
42223 : typeof obj;
42224 };
42225 }
42226 return _typeof(obj);
42227 }
42228 Object.defineProperty(exports, '__esModule', { value: true });
42229 exports.default = void 0;
42230
42231 var _main = _interopRequireDefault(_dereq_('../core/main'));
42232 var constants = _interopRequireWildcard(_dereq_('../core/constants'));
42233 var _color_conversion = _interopRequireDefault(_dereq_('./color_conversion'));
42234 function _getRequireWildcardCache() {
42235 if (typeof WeakMap !== 'function') return null;
42236 var cache = new WeakMap();
42237 _getRequireWildcardCache = function _getRequireWildcardCache() {
42238 return cache;
42239 };
42240 return cache;
42241 }
42242 function _interopRequireWildcard(obj) {
42243 if (obj && obj.__esModule) {
42244 return obj;
42245 }
42246 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) {
42247 return { default: obj };
42248 }
42249 var cache = _getRequireWildcardCache();
42250 if (cache && cache.has(obj)) {
42251 return cache.get(obj);
42252 }
42253 var newObj = {};
42254 var hasPropertyDescriptor =
42255 Object.defineProperty && Object.getOwnPropertyDescriptor;
42256 for (var key in obj) {
42257 if (Object.prototype.hasOwnProperty.call(obj, key)) {
42258 var desc = hasPropertyDescriptor
42259 ? Object.getOwnPropertyDescriptor(obj, key)
42260 : null;
42261 if (desc && (desc.get || desc.set)) {
42262 Object.defineProperty(newObj, key, desc);
42263 } else {
42264 newObj[key] = obj[key];
42265 }
42266 }
42267 }
42268 newObj.default = obj;
42269 if (cache) {
42270 cache.set(obj, newObj);
42271 }
42272 return newObj;
42273 }
42274 function _interopRequireDefault(obj) {
42275 return obj && obj.__esModule ? obj : { default: obj };
42276 }
42277 /**
42278 * @module Color
42279 * @submodule Creating & Reading
42280 * @for p5
42281 * @requires core
42282 * @requires constants
42283 * @requires color_conversion
42284 */ /**
42285 * Each color stores the color mode and level maxes that was applied at the
42286 * time of its construction. These are used to interpret the input arguments
42287 * (at construction and later for that instance of color) and to format the
42288 * output e.g. when <a href="#/p5/saturation">saturation()</a> is requested.
42289 *
42290 * Internally, we store an array representing the ideal RGBA values in floating
42291 * point form, normalized from 0 to 1. From this we calculate the closest
42292 * screen color (RGBA levels from 0 to 255) and expose this to the renderer.
42293 *
42294 * We also cache normalized, floating point components of the color in various
42295 * representations as they are calculated. This is done to prevent repeating a
42296 * conversion that has already been performed.
42297 *
42298 * @class p5.Color
42299 * @constructor
42300 */ _main.default.Color = function(pInst, vals) {
42301 // Record color mode and maxes at time of construction.
42302 this._storeModeAndMaxes(pInst._colorMode, pInst._colorMaxes); // Calculate normalized RGBA values.
42303 if (
42304 this.mode !== constants.RGB &&
42305 this.mode !== constants.HSL &&
42306 this.mode !== constants.HSB
42307 ) {
42308 throw new Error(''.concat(this.mode, ' is an invalid colorMode.'));
42309 } else {
42310 this._array = _main.default.Color._parseInputs.apply(this, vals);
42311 }
42312
42313 // Expose closest screen color.
42314 this._calculateLevels();
42315 return this;
42316 };
42317
42318 /**
42319 * This function returns the color formatted as a string. This can be useful
42320 * for debugging, or for using p5.js with other libraries.
42321 *
42322 * @method toString
42323 * @param {String} [format] How the color string will be formatted.
42324 * Leaving this empty formats the string as rgba(r, g, b, a).
42325 * '#rgb' '#rgba' '#rrggbb' and '#rrggbbaa' format as hexadecimal color codes.
42326 * 'rgb' 'hsb' and 'hsl' return the color formatted in the specified color mode.
42327 * 'rgba' 'hsba' and 'hsla' are the same as above but with alpha channels.
42328 * 'rgb%' 'hsb%' 'hsl%' 'rgba%' 'hsba%' and 'hsla%' format as percentages.
42329 * @return {String} the formatted string
42330 *
42331 * @example
42332 * <div>
42333 * <code>
42334 * createCanvas(200, 100);
42335 * let myColor;
42336 * stroke(255);
42337 * myColor = color(100, 100, 250);
42338 * fill(myColor);
42339 * rotate(HALF_PI);
42340 * text(myColor.toString(), 0, -5);
42341 * text(myColor.toString('#rrggbb'), 0, -30);
42342 * text(myColor.toString('rgba%'), 0, -55);
42343 * </code>
42344 * </div>
42345 *
42346 * @alt
42347 * A canvas with 3 text representation of thier color.
42348 */
42349 _main.default.Color.prototype.toString = function(format) {
42350 var a = this.levels;
42351 var f = this._array;
42352 var alpha = f[3]; // String representation uses normalized alpha
42353
42354 switch (format) {
42355 case '#rrggbb':
42356 return '#'.concat(
42357 a[0] < 16 ? '0'.concat(a[0].toString(16)) : a[0].toString(16),
42358 a[1] < 16 ? '0'.concat(a[1].toString(16)) : a[1].toString(16),
42359 a[2] < 16 ? '0'.concat(a[2].toString(16)) : a[2].toString(16)
42360 );
42361
42362 case '#rrggbbaa':
42363 return '#'.concat(
42364 a[0] < 16 ? '0'.concat(a[0].toString(16)) : a[0].toString(16),
42365 a[1] < 16 ? '0'.concat(a[1].toString(16)) : a[1].toString(16),
42366 a[2] < 16 ? '0'.concat(a[2].toString(16)) : a[2].toString(16),
42367 a[3] < 16 ? '0'.concat(a[2].toString(16)) : a[3].toString(16)
42368 );
42369
42370 case '#rgb':
42371 return '#'.concat(
42372 Math.round(f[0] * 15).toString(16),
42373 Math.round(f[1] * 15).toString(16),
42374 Math.round(f[2] * 15).toString(16)
42375 );
42376
42377 case '#rgba':
42378 return '#'.concat(
42379 Math.round(f[0] * 15).toString(16),
42380 Math.round(f[1] * 15).toString(16),
42381 Math.round(f[2] * 15).toString(16),
42382 Math.round(f[3] * 15).toString(16)
42383 );
42384
42385 case 'rgb':
42386 return 'rgb('.concat(a[0], ', ', a[1], ', ', a[2], ')');
42387
42388 case 'rgb%':
42389 return 'rgb('.concat(
42390 (100 * f[0]).toPrecision(3),
42391 '%, ',
42392 (100 * f[1]).toPrecision(3),
42393 '%, ',
42394 (100 * f[2]).toPrecision(3),
42395 '%)'
42396 );
42397
42398 case 'rgba%':
42399 return 'rgba('.concat(
42400 (100 * f[0]).toPrecision(3),
42401 '%, ',
42402 (100 * f[1]).toPrecision(3),
42403 '%, ',
42404 (100 * f[2]).toPrecision(3),
42405 '%, ',
42406 (100 * f[3]).toPrecision(3),
42407 '%)'
42408 );
42409
42410 case 'hsb':
42411 case 'hsv':
42412 if (!this.hsba)
42413 this.hsba = _color_conversion.default._rgbaToHSBA(this._array);
42414 return 'hsb('.concat(
42415 this.hsba[0] * this.maxes[constants.HSB][0],
42416 ', ',
42417 this.hsba[1] * this.maxes[constants.HSB][1],
42418 ', ',
42419 this.hsba[2] * this.maxes[constants.HSB][2],
42420 ')'
42421 );
42422
42423 case 'hsb%':
42424 case 'hsv%':
42425 if (!this.hsba)
42426 this.hsba = _color_conversion.default._rgbaToHSBA(this._array);
42427 return 'hsb('.concat(
42428 (100 * this.hsba[0]).toPrecision(3),
42429 '%, ',
42430 (100 * this.hsba[1]).toPrecision(3),
42431 '%, ',
42432 (100 * this.hsba[2]).toPrecision(3),
42433 '%)'
42434 );
42435
42436 case 'hsba':
42437 case 'hsva':
42438 if (!this.hsba)
42439 this.hsba = _color_conversion.default._rgbaToHSBA(this._array);
42440 return 'hsba('.concat(
42441 this.hsba[0] * this.maxes[constants.HSB][0],
42442 ', ',
42443 this.hsba[1] * this.maxes[constants.HSB][1],
42444 ', ',
42445 this.hsba[2] * this.maxes[constants.HSB][2],
42446 ', ',
42447 alpha,
42448 ')'
42449 );
42450
42451 case 'hsba%':
42452 case 'hsva%':
42453 if (!this.hsba)
42454 this.hsba = _color_conversion.default._rgbaToHSBA(this._array);
42455 return 'hsba('.concat(
42456 (100 * this.hsba[0]).toPrecision(3),
42457 '%, ',
42458 (100 * this.hsba[1]).toPrecision(3),
42459 '%, ',
42460 (100 * this.hsba[2]).toPrecision(3),
42461 '%, ',
42462 (100 * alpha).toPrecision(3),
42463 '%)'
42464 );
42465
42466 case 'hsl':
42467 if (!this.hsla)
42468 this.hsla = _color_conversion.default._rgbaToHSLA(this._array);
42469 return 'hsl('.concat(
42470 this.hsla[0] * this.maxes[constants.HSL][0],
42471 ', ',
42472 this.hsla[1] * this.maxes[constants.HSL][1],
42473 ', ',
42474 this.hsla[2] * this.maxes[constants.HSL][2],
42475 ')'
42476 );
42477
42478 case 'hsl%':
42479 if (!this.hsla)
42480 this.hsla = _color_conversion.default._rgbaToHSLA(this._array);
42481 return 'hsl('.concat(
42482 (100 * this.hsla[0]).toPrecision(3),
42483 '%, ',
42484 (100 * this.hsla[1]).toPrecision(3),
42485 '%, ',
42486 (100 * this.hsla[2]).toPrecision(3),
42487 '%)'
42488 );
42489
42490 case 'hsla':
42491 if (!this.hsla)
42492 this.hsla = _color_conversion.default._rgbaToHSLA(this._array);
42493 return 'hsla('.concat(
42494 this.hsla[0] * this.maxes[constants.HSL][0],
42495 ', ',
42496 this.hsla[1] * this.maxes[constants.HSL][1],
42497 ', ',
42498 this.hsla[2] * this.maxes[constants.HSL][2],
42499 ', ',
42500 alpha,
42501 ')'
42502 );
42503
42504 case 'hsla%':
42505 if (!this.hsla)
42506 this.hsla = _color_conversion.default._rgbaToHSLA(this._array);
42507 return 'hsl('.concat(
42508 (100 * this.hsla[0]).toPrecision(3),
42509 '%, ',
42510 (100 * this.hsla[1]).toPrecision(3),
42511 '%, ',
42512 (100 * this.hsla[2]).toPrecision(3),
42513 '%, ',
42514 (100 * alpha).toPrecision(3),
42515 '%)'
42516 );
42517
42518 case 'rgba':
42519 default:
42520 return 'rgba('.concat(a[0], ',', a[1], ',', a[2], ',', alpha, ')');
42521 }
42522 };
42523
42524 /**
42525 * The setRed function sets the red component of a color.
42526 * The range depends on your color mode, in the default RGB mode it's between 0 and 255.
42527 * @method setRed
42528 * @param {Number} red the new red value
42529 * @example
42530 * <div>
42531 * <code>
42532 * let backgroundColor;
42533 *
42534 * function setup() {
42535 * backgroundColor = color(100, 50, 150);
42536 * }
42537 *
42538 * function draw() {
42539 * backgroundColor.setRed(128 + 128 * sin(millis() / 1000));
42540 * background(backgroundColor);
42541 * }
42542 * </code>
42543 * </div>
42544 *
42545 * @alt
42546 * canvas with gradually changing background color
42547 */
42548 _main.default.Color.prototype.setRed = function(new_red) {
42549 this._array[0] = new_red / this.maxes[constants.RGB][0];
42550 this._calculateLevels();
42551 };
42552
42553 /**
42554 * The setGreen function sets the green component of a color.
42555 * The range depends on your color mode, in the default RGB mode it's between 0 and 255.
42556 * @method setGreen
42557 * @param {Number} green the new green value
42558 * @example
42559 * <div>
42560 * <code>
42561 * let backgroundColor = color(100, 50, 150);
42562 * function draw() {
42563 * backgroundColor.setGreen(128 + 128 * sin(millis() / 1000));
42564 * background(backgroundColor);
42565 * }
42566 * </code>
42567 * </div>
42568 *
42569 * @alt
42570 * canvas with gradually changing background color
42571 **/
42572 _main.default.Color.prototype.setGreen = function(new_green) {
42573 this._array[1] = new_green / this.maxes[constants.RGB][1];
42574 this._calculateLevels();
42575 };
42576
42577 /**
42578 * The setBlue function sets the blue component of a color.
42579 * The range depends on your color mode, in the default RGB mode it's between 0 and 255.
42580 * @method setBlue
42581 * @param {Number} blue the new blue value
42582 * @example
42583 * <div>
42584 * <code>
42585 * let backgroundColor = color(100, 50, 150);
42586 * function draw() {
42587 * backgroundColor.setBlue(128 + 128 * sin(millis() / 1000));
42588 * background(backgroundColor);
42589 * }
42590 * </code>
42591 * </div>
42592 *
42593 * @alt
42594 * canvas with gradually changing background color
42595 **/
42596 _main.default.Color.prototype.setBlue = function(new_blue) {
42597 this._array[2] = new_blue / this.maxes[constants.RGB][2];
42598 this._calculateLevels();
42599 };
42600
42601 /**
42602 * The setAlpha function sets the transparency (alpha) value of a color.
42603 * The range depends on your color mode, in the default RGB mode it's between 0 and 255.
42604 * @method setAlpha
42605 * @param {Number} alpha the new alpha value
42606 * @example
42607 * <div>
42608 * <code>
42609 * function draw() {
42610 * clear();
42611 * background(200);
42612 * squareColor = color(100, 50, 100);
42613 * squareColor.setAlpha(128 + 128 * sin(millis() / 1000));
42614 * fill(squareColor);
42615 * rect(13, 13, width - 26, height - 26);
42616 * }
42617 * </code>
42618 * </div>
42619 *
42620 * @alt
42621 * a square with gradually changing opacity on a gray background
42622 **/
42623 _main.default.Color.prototype.setAlpha = function(new_alpha) {
42624 this._array[3] = new_alpha / this.maxes[this.mode][3];
42625 this._calculateLevels();
42626 };
42627
42628 // calculates and stores the closest screen levels
42629 _main.default.Color.prototype._calculateLevels = function() {
42630 var array = this._array;
42631 // (loop backwards for performance)
42632 var levels = (this.levels = new Array(array.length));
42633 for (var i = array.length - 1; i >= 0; --i) {
42634 levels[i] = Math.round(array[i] * 255);
42635 }
42636 };
42637
42638 _main.default.Color.prototype._getAlpha = function() {
42639 return this._array[3] * this.maxes[this.mode][3];
42640 };
42641
42642 // stores the color mode and maxes in this instance of Color
42643 // for later use (by _parseInputs())
42644 _main.default.Color.prototype._storeModeAndMaxes = function(new_mode, new_maxes) {
42645 this.mode = new_mode;
42646 this.maxes = new_maxes;
42647 };
42648
42649 _main.default.Color.prototype._getMode = function() {
42650 return this.mode;
42651 };
42652
42653 _main.default.Color.prototype._getMaxes = function() {
42654 return this.maxes;
42655 };
42656
42657 _main.default.Color.prototype._getBlue = function() {
42658 return this._array[2] * this.maxes[constants.RGB][2];
42659 };
42660
42661 _main.default.Color.prototype._getBrightness = function() {
42662 if (!this.hsba) {
42663 this.hsba = _color_conversion.default._rgbaToHSBA(this._array);
42664 }
42665 return this.hsba[2] * this.maxes[constants.HSB][2];
42666 };
42667
42668 _main.default.Color.prototype._getGreen = function() {
42669 return this._array[1] * this.maxes[constants.RGB][1];
42670 };
42671
42672 /**
42673 * Hue is the same in HSB and HSL, but the maximum value may be different.
42674 * This function will return the HSB-normalized saturation when supplied with
42675 * an HSB color object, but will default to the HSL-normalized saturation
42676 * otherwise.
42677 */
42678 _main.default.Color.prototype._getHue = function() {
42679 if (this.mode === constants.HSB) {
42680 if (!this.hsba) {
42681 this.hsba = _color_conversion.default._rgbaToHSBA(this._array);
42682 }
42683 return this.hsba[0] * this.maxes[constants.HSB][0];
42684 } else {
42685 if (!this.hsla) {
42686 this.hsla = _color_conversion.default._rgbaToHSLA(this._array);
42687 }
42688 return this.hsla[0] * this.maxes[constants.HSL][0];
42689 }
42690 };
42691
42692 _main.default.Color.prototype._getLightness = function() {
42693 if (!this.hsla) {
42694 this.hsla = _color_conversion.default._rgbaToHSLA(this._array);
42695 }
42696 return this.hsla[2] * this.maxes[constants.HSL][2];
42697 };
42698
42699 _main.default.Color.prototype._getRed = function() {
42700 return this._array[0] * this.maxes[constants.RGB][0];
42701 };
42702
42703 /**
42704 * Saturation is scaled differently in HSB and HSL. This function will return
42705 * the HSB saturation when supplied with an HSB color object, but will default
42706 * to the HSL saturation otherwise.
42707 */
42708 _main.default.Color.prototype._getSaturation = function() {
42709 if (this.mode === constants.HSB) {
42710 if (!this.hsba) {
42711 this.hsba = _color_conversion.default._rgbaToHSBA(this._array);
42712 }
42713 return this.hsba[1] * this.maxes[constants.HSB][1];
42714 } else {
42715 if (!this.hsla) {
42716 this.hsla = _color_conversion.default._rgbaToHSLA(this._array);
42717 }
42718 return this.hsla[1] * this.maxes[constants.HSL][1];
42719 }
42720 };
42721
42722 /**
42723 * CSS named colors.
42724 */
42725 var namedColors = {
42726 aliceblue: '#f0f8ff',
42727 antiquewhite: '#faebd7',
42728 aqua: '#00ffff',
42729 aquamarine: '#7fffd4',
42730 azure: '#f0ffff',
42731 beige: '#f5f5dc',
42732 bisque: '#ffe4c4',
42733 black: '#000000',
42734 blanchedalmond: '#ffebcd',
42735 blue: '#0000ff',
42736 blueviolet: '#8a2be2',
42737 brown: '#a52a2a',
42738 burlywood: '#deb887',
42739 cadetblue: '#5f9ea0',
42740 chartreuse: '#7fff00',
42741 chocolate: '#d2691e',
42742 coral: '#ff7f50',
42743 cornflowerblue: '#6495ed',
42744 cornsilk: '#fff8dc',
42745 crimson: '#dc143c',
42746 cyan: '#00ffff',
42747 darkblue: '#00008b',
42748 darkcyan: '#008b8b',
42749 darkgoldenrod: '#b8860b',
42750 darkgray: '#a9a9a9',
42751 darkgreen: '#006400',
42752 darkgrey: '#a9a9a9',
42753 darkkhaki: '#bdb76b',
42754 darkmagenta: '#8b008b',
42755 darkolivegreen: '#556b2f',
42756 darkorange: '#ff8c00',
42757 darkorchid: '#9932cc',
42758 darkred: '#8b0000',
42759 darksalmon: '#e9967a',
42760 darkseagreen: '#8fbc8f',
42761 darkslateblue: '#483d8b',
42762 darkslategray: '#2f4f4f',
42763 darkslategrey: '#2f4f4f',
42764 darkturquoise: '#00ced1',
42765 darkviolet: '#9400d3',
42766 deeppink: '#ff1493',
42767 deepskyblue: '#00bfff',
42768 dimgray: '#696969',
42769 dimgrey: '#696969',
42770 dodgerblue: '#1e90ff',
42771 firebrick: '#b22222',
42772 floralwhite: '#fffaf0',
42773 forestgreen: '#228b22',
42774 fuchsia: '#ff00ff',
42775 gainsboro: '#dcdcdc',
42776 ghostwhite: '#f8f8ff',
42777 gold: '#ffd700',
42778 goldenrod: '#daa520',
42779 gray: '#808080',
42780 green: '#008000',
42781 greenyellow: '#adff2f',
42782 grey: '#808080',
42783 honeydew: '#f0fff0',
42784 hotpink: '#ff69b4',
42785 indianred: '#cd5c5c',
42786 indigo: '#4b0082',
42787 ivory: '#fffff0',
42788 khaki: '#f0e68c',
42789 lavender: '#e6e6fa',
42790 lavenderblush: '#fff0f5',
42791 lawngreen: '#7cfc00',
42792 lemonchiffon: '#fffacd',
42793 lightblue: '#add8e6',
42794 lightcoral: '#f08080',
42795 lightcyan: '#e0ffff',
42796 lightgoldenrodyellow: '#fafad2',
42797 lightgray: '#d3d3d3',
42798 lightgreen: '#90ee90',
42799 lightgrey: '#d3d3d3',
42800 lightpink: '#ffb6c1',
42801 lightsalmon: '#ffa07a',
42802 lightseagreen: '#20b2aa',
42803 lightskyblue: '#87cefa',
42804 lightslategray: '#778899',
42805 lightslategrey: '#778899',
42806 lightsteelblue: '#b0c4de',
42807 lightyellow: '#ffffe0',
42808 lime: '#00ff00',
42809 limegreen: '#32cd32',
42810 linen: '#faf0e6',
42811 magenta: '#ff00ff',
42812 maroon: '#800000',
42813 mediumaquamarine: '#66cdaa',
42814 mediumblue: '#0000cd',
42815 mediumorchid: '#ba55d3',
42816 mediumpurple: '#9370db',
42817 mediumseagreen: '#3cb371',
42818 mediumslateblue: '#7b68ee',
42819 mediumspringgreen: '#00fa9a',
42820 mediumturquoise: '#48d1cc',
42821 mediumvioletred: '#c71585',
42822 midnightblue: '#191970',
42823 mintcream: '#f5fffa',
42824 mistyrose: '#ffe4e1',
42825 moccasin: '#ffe4b5',
42826 navajowhite: '#ffdead',
42827 navy: '#000080',
42828 oldlace: '#fdf5e6',
42829 olive: '#808000',
42830 olivedrab: '#6b8e23',
42831 orange: '#ffa500',
42832 orangered: '#ff4500',
42833 orchid: '#da70d6',
42834 palegoldenrod: '#eee8aa',
42835 palegreen: '#98fb98',
42836 paleturquoise: '#afeeee',
42837 palevioletred: '#db7093',
42838 papayawhip: '#ffefd5',
42839 peachpuff: '#ffdab9',
42840 peru: '#cd853f',
42841 pink: '#ffc0cb',
42842 plum: '#dda0dd',
42843 powderblue: '#b0e0e6',
42844 purple: '#800080',
42845 rebeccapurple: '#663399',
42846 red: '#ff0000',
42847 rosybrown: '#bc8f8f',
42848 royalblue: '#4169e1',
42849 saddlebrown: '#8b4513',
42850 salmon: '#fa8072',
42851 sandybrown: '#f4a460',
42852 seagreen: '#2e8b57',
42853 seashell: '#fff5ee',
42854 sienna: '#a0522d',
42855 silver: '#c0c0c0',
42856 skyblue: '#87ceeb',
42857 slateblue: '#6a5acd',
42858 slategray: '#708090',
42859 slategrey: '#708090',
42860 snow: '#fffafa',
42861 springgreen: '#00ff7f',
42862 steelblue: '#4682b4',
42863 tan: '#d2b48c',
42864 teal: '#008080',
42865 thistle: '#d8bfd8',
42866 tomato: '#ff6347',
42867 turquoise: '#40e0d0',
42868 violet: '#ee82ee',
42869 wheat: '#f5deb3',
42870 white: '#ffffff',
42871 whitesmoke: '#f5f5f5',
42872 yellow: '#ffff00',
42873 yellowgreen: '#9acd32'
42874 };
42875
42876 /**
42877 * These regular expressions are used to build up the patterns for matching
42878 * viable CSS color strings: fragmenting the regexes in this way increases the
42879 * legibility and comprehensibility of the code.
42880 *
42881 * Note that RGB values of .9 are not parsed by IE, but are supported here for
42882 * color string consistency.
42883 */
42884 var WHITESPACE = /\s*/; // Match zero or more whitespace characters.
42885 var INTEGER = /(\d{1,3})/; // Match integers: 79, 255, etc.
42886 var DECIMAL = /((?:\d+(?:\.\d+)?)|(?:\.\d+))/; // Match 129.6, 79, .9, etc.
42887 var PERCENT = new RegExp(''.concat(DECIMAL.source, '%')); // Match 12.9%, 79%, .9%, etc.
42888
42889 /**
42890 * Full color string patterns. The capture groups are necessary.
42891 */
42892 var colorPatterns = {
42893 // Match colors in format #XXX, e.g. #416.
42894 HEX3: /^#([a-f0-9])([a-f0-9])([a-f0-9])$/i,
42895
42896 // Match colors in format #XXXX, e.g. #5123.
42897 HEX4: /^#([a-f0-9])([a-f0-9])([a-f0-9])([a-f0-9])$/i,
42898
42899 // Match colors in format #XXXXXX, e.g. #b4d455.
42900 HEX6: /^#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})$/i,
42901
42902 // Match colors in format #XXXXXXXX, e.g. #b4d45535.
42903 HEX8: /^#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})$/i,
42904
42905 // Match colors in format rgb(R, G, B), e.g. rgb(255, 0, 128).
42906 RGB: new RegExp(
42907 [
42908 '^rgb\\(',
42909 INTEGER.source,
42910 ',',
42911 INTEGER.source,
42912 ',',
42913 INTEGER.source,
42914 '\\)$'
42915 ].join(WHITESPACE.source),
42916 'i'
42917 ),
42918
42919 // Match colors in format rgb(R%, G%, B%), e.g. rgb(100%, 0%, 28.9%).
42920 RGB_PERCENT: new RegExp(
42921 [
42922 '^rgb\\(',
42923 PERCENT.source,
42924 ',',
42925 PERCENT.source,
42926 ',',
42927 PERCENT.source,
42928 '\\)$'
42929 ].join(WHITESPACE.source),
42930 'i'
42931 ),
42932
42933 // Match colors in format rgb(R, G, B, A), e.g. rgb(255, 0, 128, 0.25).
42934 RGBA: new RegExp(
42935 [
42936 '^rgba\\(',
42937 INTEGER.source,
42938 ',',
42939 INTEGER.source,
42940 ',',
42941 INTEGER.source,
42942 ',',
42943 DECIMAL.source,
42944 '\\)$'
42945 ].join(WHITESPACE.source),
42946 'i'
42947 ),
42948
42949 // Match colors in format rgb(R%, G%, B%, A), e.g. rgb(100%, 0%, 28.9%, 0.5).
42950 RGBA_PERCENT: new RegExp(
42951 [
42952 '^rgba\\(',
42953 PERCENT.source,
42954 ',',
42955 PERCENT.source,
42956 ',',
42957 PERCENT.source,
42958 ',',
42959 DECIMAL.source,
42960 '\\)$'
42961 ].join(WHITESPACE.source),
42962 'i'
42963 ),
42964
42965 // Match colors in format hsla(H, S%, L%), e.g. hsl(100, 40%, 28.9%).
42966 HSL: new RegExp(
42967 [
42968 '^hsl\\(',
42969 INTEGER.source,
42970 ',',
42971 PERCENT.source,
42972 ',',
42973 PERCENT.source,
42974 '\\)$'
42975 ].join(WHITESPACE.source),
42976 'i'
42977 ),
42978
42979 // Match colors in format hsla(H, S%, L%, A), e.g. hsla(100, 40%, 28.9%, 0.5).
42980 HSLA: new RegExp(
42981 [
42982 '^hsla\\(',
42983 INTEGER.source,
42984 ',',
42985 PERCENT.source,
42986 ',',
42987 PERCENT.source,
42988 ',',
42989 DECIMAL.source,
42990 '\\)$'
42991 ].join(WHITESPACE.source),
42992 'i'
42993 ),
42994
42995 // Match colors in format hsb(H, S%, B%), e.g. hsb(100, 40%, 28.9%).
42996 HSB: new RegExp(
42997 [
42998 '^hsb\\(',
42999 INTEGER.source,
43000 ',',
43001 PERCENT.source,
43002 ',',
43003 PERCENT.source,
43004 '\\)$'
43005 ].join(WHITESPACE.source),
43006 'i'
43007 ),
43008
43009 // Match colors in format hsba(H, S%, B%, A), e.g. hsba(100, 40%, 28.9%, 0.5).
43010 HSBA: new RegExp(
43011 [
43012 '^hsba\\(',
43013 INTEGER.source,
43014 ',',
43015 PERCENT.source,
43016 ',',
43017 PERCENT.source,
43018 ',',
43019 DECIMAL.source,
43020 '\\)$'
43021 ].join(WHITESPACE.source),
43022 'i'
43023 )
43024 };
43025
43026 /**
43027 * For a number of different inputs, returns a color formatted as [r, g, b, a]
43028 * arrays, with each component normalized between 0 and 1.
43029 *
43030 * @private
43031 * @param {Array} [...args] An 'array-like' object that represents a list of
43032 * arguments
43033 * @return {Number[]} a color formatted as [r, g, b, a]
43034 * Example:
43035 * input ==> output
43036 * g ==> [g, g, g, 255]
43037 * g,a ==> [g, g, g, a]
43038 * r, g, b ==> [r, g, b, 255]
43039 * r, g, b, a ==> [r, g, b, a]
43040 * [g] ==> [g, g, g, 255]
43041 * [g, a] ==> [g, g, g, a]
43042 * [r, g, b] ==> [r, g, b, 255]
43043 * [r, g, b, a] ==> [r, g, b, a]
43044 * @example
43045 * <div>
43046 * <code>
43047 * // todo
43048 * </code>
43049 * </div>
43050 *
43051 * @alt
43052 * //todo
43053 */
43054 _main.default.Color._parseInputs = function(r, g, b, a) {
43055 var numArgs = arguments.length;
43056 var mode = this.mode;
43057 var maxes = this.maxes[mode];
43058 var results = [];
43059 var i;
43060
43061 if (numArgs >= 3) {
43062 // Argument is a list of component values.
43063
43064 results[0] = r / maxes[0];
43065 results[1] = g / maxes[1];
43066 results[2] = b / maxes[2];
43067
43068 // Alpha may be undefined, so default it to 100%.
43069 if (typeof a === 'number') {
43070 results[3] = a / maxes[3];
43071 } else {
43072 results[3] = 1;
43073 }
43074
43075 // Constrain components to the range [0,1].
43076 // (loop backwards for performance)
43077 for (i = results.length - 1; i >= 0; --i) {
43078 var result = results[i];
43079 if (result < 0) {
43080 results[i] = 0;
43081 } else if (result > 1) {
43082 results[i] = 1;
43083 }
43084 }
43085
43086 // Convert to RGBA and return.
43087 if (mode === constants.HSL) {
43088 return _color_conversion.default._hslaToRGBA(results);
43089 } else if (mode === constants.HSB) {
43090 return _color_conversion.default._hsbaToRGBA(results);
43091 } else {
43092 return results;
43093 }
43094 } else if (numArgs === 1 && typeof r === 'string') {
43095 var str = r.trim().toLowerCase();
43096
43097 // Return if string is a named colour.
43098 if (namedColors[str]) {
43099 return _main.default.Color._parseInputs.call(this, namedColors[str]);
43100 }
43101
43102 // Try RGBA pattern matching.
43103 if (colorPatterns.HEX3.test(str)) {
43104 // #rgb
43105 results = colorPatterns.HEX3.exec(str)
43106 .slice(1)
43107 .map(function(color) {
43108 return parseInt(color + color, 16) / 255;
43109 });
43110 results[3] = 1;
43111 return results;
43112 } else if (colorPatterns.HEX6.test(str)) {
43113 // #rrggbb
43114 results = colorPatterns.HEX6.exec(str)
43115 .slice(1)
43116 .map(function(color) {
43117 return parseInt(color, 16) / 255;
43118 });
43119 results[3] = 1;
43120 return results;
43121 } else if (colorPatterns.HEX4.test(str)) {
43122 // #rgba
43123 results = colorPatterns.HEX4.exec(str)
43124 .slice(1)
43125 .map(function(color) {
43126 return parseInt(color + color, 16) / 255;
43127 });
43128 return results;
43129 } else if (colorPatterns.HEX8.test(str)) {
43130 // #rrggbbaa
43131 results = colorPatterns.HEX8.exec(str)
43132 .slice(1)
43133 .map(function(color) {
43134 return parseInt(color, 16) / 255;
43135 });
43136 return results;
43137 } else if (colorPatterns.RGB.test(str)) {
43138 // rgb(R,G,B)
43139 results = colorPatterns.RGB.exec(str)
43140 .slice(1)
43141 .map(function(color) {
43142 return color / 255;
43143 });
43144 results[3] = 1;
43145 return results;
43146 } else if (colorPatterns.RGB_PERCENT.test(str)) {
43147 // rgb(R%,G%,B%)
43148 results = colorPatterns.RGB_PERCENT.exec(str)
43149 .slice(1)
43150 .map(function(color) {
43151 return parseFloat(color) / 100;
43152 });
43153 results[3] = 1;
43154 return results;
43155 } else if (colorPatterns.RGBA.test(str)) {
43156 // rgba(R,G,B,A)
43157 results = colorPatterns.RGBA.exec(str)
43158 .slice(1)
43159 .map(function(color, idx) {
43160 if (idx === 3) {
43161 return parseFloat(color);
43162 }
43163 return color / 255;
43164 });
43165 return results;
43166 } else if (colorPatterns.RGBA_PERCENT.test(str)) {
43167 // rgba(R%,G%,B%,A%)
43168 results = colorPatterns.RGBA_PERCENT.exec(str)
43169 .slice(1)
43170 .map(function(color, idx) {
43171 if (idx === 3) {
43172 return parseFloat(color);
43173 }
43174 return parseFloat(color) / 100;
43175 });
43176 return results;
43177 }
43178
43179 // Try HSLA pattern matching.
43180 if (colorPatterns.HSL.test(str)) {
43181 // hsl(H,S,L)
43182 results = colorPatterns.HSL.exec(str)
43183 .slice(1)
43184 .map(function(color, idx) {
43185 if (idx === 0) {
43186 return parseInt(color, 10) / 360;
43187 }
43188 return parseInt(color, 10) / 100;
43189 });
43190 results[3] = 1;
43191 } else if (colorPatterns.HSLA.test(str)) {
43192 // hsla(H,S,L,A)
43193 results = colorPatterns.HSLA.exec(str)
43194 .slice(1)
43195 .map(function(color, idx) {
43196 if (idx === 0) {
43197 return parseInt(color, 10) / 360;
43198 } else if (idx === 3) {
43199 return parseFloat(color);
43200 }
43201 return parseInt(color, 10) / 100;
43202 });
43203 }
43204 results = results.map(function(value) {
43205 return Math.max(Math.min(value, 1), 0);
43206 });
43207 if (results.length) {
43208 return _color_conversion.default._hslaToRGBA(results);
43209 }
43210
43211 // Try HSBA pattern matching.
43212 if (colorPatterns.HSB.test(str)) {
43213 // hsb(H,S,B)
43214 results = colorPatterns.HSB.exec(str)
43215 .slice(1)
43216 .map(function(color, idx) {
43217 if (idx === 0) {
43218 return parseInt(color, 10) / 360;
43219 }
43220 return parseInt(color, 10) / 100;
43221 });
43222 results[3] = 1;
43223 } else if (colorPatterns.HSBA.test(str)) {
43224 // hsba(H,S,B,A)
43225 results = colorPatterns.HSBA.exec(str)
43226 .slice(1)
43227 .map(function(color, idx) {
43228 if (idx === 0) {
43229 return parseInt(color, 10) / 360;
43230 } else if (idx === 3) {
43231 return parseFloat(color);
43232 }
43233 return parseInt(color, 10) / 100;
43234 });
43235 }
43236
43237 if (results.length) {
43238 // (loop backwards for performance)
43239 for (i = results.length - 1; i >= 0; --i) {
43240 results[i] = Math.max(Math.min(results[i], 1), 0);
43241 }
43242
43243 return _color_conversion.default._hsbaToRGBA(results);
43244 }
43245
43246 // Input did not match any CSS color pattern: default to white.
43247 results = [1, 1, 1, 1];
43248 } else if ((numArgs === 1 || numArgs === 2) && typeof r === 'number') {
43249 // 'Grayscale' mode.
43250
43251 /**
43252 * For HSB and HSL, interpret the gray level as a brightness/lightness
43253 * value (they are equivalent when chroma is zero). For RGB, normalize the
43254 * gray level according to the blue maximum.
43255 */
43256 results[0] = r / maxes[2];
43257 results[1] = r / maxes[2];
43258 results[2] = r / maxes[2];
43259
43260 // Alpha may be undefined, so default it to 100%.
43261 if (typeof g === 'number') {
43262 results[3] = g / maxes[3];
43263 } else {
43264 results[3] = 1;
43265 }
43266
43267 // Constrain components to the range [0,1].
43268 results = results.map(function(value) {
43269 return Math.max(Math.min(value, 1), 0);
43270 });
43271 } else {
43272 throw new Error(''.concat(arguments, 'is not a valid color representation.'));
43273 }
43274
43275 return results;
43276 };
43277 var _default = _main.default.Color;
43278 exports.default = _default;
43279 },
43280 { '../core/constants': 43, '../core/main': 54, './color_conversion': 39 }
43281 ],
43282 42: [
43283 function(_dereq_, module, exports) {
43284 'use strict';
43285 function _typeof(obj) {
43286 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
43287 _typeof = function _typeof(obj) {
43288 return typeof obj;
43289 };
43290 } else {
43291 _typeof = function _typeof(obj) {
43292 return obj &&
43293 typeof Symbol === 'function' &&
43294 obj.constructor === Symbol &&
43295 obj !== Symbol.prototype
43296 ? 'symbol'
43297 : typeof obj;
43298 };
43299 }
43300 return _typeof(obj);
43301 }
43302 Object.defineProperty(exports, '__esModule', { value: true });
43303 exports.default = void 0;
43304
43305 var _main = _interopRequireDefault(_dereq_('../core/main'));
43306 var constants = _interopRequireWildcard(_dereq_('../core/constants'));
43307 _dereq_('./p5.Color');
43308 function _getRequireWildcardCache() {
43309 if (typeof WeakMap !== 'function') return null;
43310 var cache = new WeakMap();
43311 _getRequireWildcardCache = function _getRequireWildcardCache() {
43312 return cache;
43313 };
43314 return cache;
43315 }
43316 function _interopRequireWildcard(obj) {
43317 if (obj && obj.__esModule) {
43318 return obj;
43319 }
43320 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) {
43321 return { default: obj };
43322 }
43323 var cache = _getRequireWildcardCache();
43324 if (cache && cache.has(obj)) {
43325 return cache.get(obj);
43326 }
43327 var newObj = {};
43328 var hasPropertyDescriptor =
43329 Object.defineProperty && Object.getOwnPropertyDescriptor;
43330 for (var key in obj) {
43331 if (Object.prototype.hasOwnProperty.call(obj, key)) {
43332 var desc = hasPropertyDescriptor
43333 ? Object.getOwnPropertyDescriptor(obj, key)
43334 : null;
43335 if (desc && (desc.get || desc.set)) {
43336 Object.defineProperty(newObj, key, desc);
43337 } else {
43338 newObj[key] = obj[key];
43339 }
43340 }
43341 }
43342 newObj.default = obj;
43343 if (cache) {
43344 cache.set(obj, newObj);
43345 }
43346 return newObj;
43347 }
43348 function _interopRequireDefault(obj) {
43349 return obj && obj.__esModule ? obj : { default: obj };
43350 } /**
43351 * @method background
43352 * @param {Number} gray specifies a value between white and black
43353 * @param {Number} [a]
43354 * @chainable
43355 */ /**
43356 * @module Color
43357 * @submodule Setting
43358 * @for p5
43359 * @requires core
43360 * @requires constants
43361 */ /**
43362 * The <a href="#/p5/background">background()</a> function sets the color used
43363 * for the background of the p5.js canvas. The default background is transparent.
43364 * This function is typically used within <a href="#/p5/draw">draw()</a> to clear
43365 * the display window at the beginning of each frame, but it can be used inside
43366 * <a href="#/p5/setup">setup()</a> to set the background on the first frame of
43367 * animation or if the background need only be set once.
43368 *
43369 * The color is either specified in terms of the RGB, HSB, or HSL color depending
43370 * on the current <a href="#/p5/colorMode">colorMode</a>. (The default color space
43371 * is RGB, with each value in the range from 0 to 255). The alpha range by default
43372 * is also 0 to 255.<br><br>
43373 *
43374 * If a single string argument is provided, RGB, RGBA and Hex CSS color strings
43375 * and all named color strings are supported. In this case, an alpha number
43376 * value as a second argument is not supported, the RGBA form should be used.
43377 *
43378 * A <a href="#/p5.Color">p5.Color</a> object can also be provided to set the background color.
43379 *
43380 * A <a href="#/p5.Image">p5.Image</a> can also be provided to set the background image.
43381 *
43382 * @method background
43383 * @param {p5.Color} color any value created by the <a href="#/p5/color">color()</a> function
43384 * @chainable
43385 *
43386 * @example
43387 * <div>
43388 * <code>
43389 * // Grayscale integer value
43390 * background(51);
43391 * </code>
43392 * </div>
43393 *
43394 * <div>
43395 * <code>
43396 * // R, G & B integer values
43397 * background(255, 204, 0);
43398 * </code>
43399 * </div>
43400 *
43401 * <div>
43402 * <code>
43403 * // H, S & B integer values
43404 * colorMode(HSB);
43405 * background(255, 204, 100);
43406 * </code>
43407 * </div>
43408 *
43409 * <div>
43410 * <code>
43411 * // Named SVG/CSS color string
43412 * background('red');
43413 * </code>
43414 * </div>
43415 *
43416 * <div>
43417 * <code>
43418 * // three-digit hexadecimal RGB notation
43419 * background('#fae');
43420 * </code>
43421 * </div>
43422 *
43423 * <div>
43424 * <code>
43425 * // six-digit hexadecimal RGB notation
43426 * background('#222222');
43427 * </code>
43428 * </div>
43429 *
43430 * <div>
43431 * <code>
43432 * // integer RGB notation
43433 * background('rgb(0,255,0)');
43434 * </code>
43435 * </div>
43436 *
43437 * <div>
43438 * <code>
43439 * // integer RGBA notation
43440 * background('rgba(0,255,0, 0.25)');
43441 * </code>
43442 * </div>
43443 *
43444 * <div>
43445 * <code>
43446 * // percentage RGB notation
43447 * background('rgb(100%,0%,10%)');
43448 * </code>
43449 * </div>
43450 *
43451 * <div>
43452 * <code>
43453 * // percentage RGBA notation
43454 * background('rgba(100%,0%,100%,0.5)');
43455 * </code>
43456 * </div>
43457 *
43458 * <div>
43459 * <code>
43460 * // p5 Color object
43461 * background(color(0, 0, 255));
43462 * </code>
43463 * </div>
43464 *
43465 * @alt
43466 * canvas with darkest charcoal grey background.
43467 * canvas with yellow background.
43468 * canvas with royal blue background.
43469 * canvas with red background.
43470 * canvas with pink background.
43471 * canvas with black background.
43472 * canvas with bright green background.
43473 * canvas with soft green background.
43474 * canvas with red background.
43475 * canvas with light purple background.
43476 * canvas with blue background.
43477 */ /**
43478 * @method background
43479 * @param {String} colorstring color string, possible formats include: integer
43480 * rgb() or rgba(), percentage rgb() or rgba(),
43481 * 3-digit hex, 6-digit hex
43482 * @param {Number} [a] opacity of the background relative to current
43483 * color range (default is 0-255)
43484 * @chainable
43485 */
43486
43487 /**
43488 * @method background
43489 * @param {Number} v1 red or hue value (depending on the current color
43490 * mode)
43491 * @param {Number} v2 green or saturation value (depending on the current
43492 * color mode)
43493 * @param {Number} v3 blue or brightness value (depending on the current
43494 * color mode)
43495 * @param {Number} [a]
43496 * @chainable
43497 */
43498
43499 /**
43500 * @method background
43501 * @param {Number[]} values an array containing the red, green, blue
43502 * and alpha components of the color
43503 * @chainable
43504 */
43505
43506 /**
43507 * @method background
43508 * @param {p5.Image} image image created with <a href="#/p5/loadImage">loadImage()</a> or <a href="#/p5/createImage">createImage()</a>,
43509 * to set as background
43510 * (must be same size as the sketch window)
43511 * @param {Number} [a]
43512 * @chainable
43513 */
43514 _main.default.prototype.background = function() {
43515 var _this$_renderer;
43516 (_this$_renderer = this._renderer).background.apply(_this$_renderer, arguments);
43517 return this;
43518 };
43519
43520 /**
43521 * Clears the pixels within a buffer. This function only clears the canvas.
43522 * It will not clear objects created by createX() methods such as
43523 * <a href="#/p5/createVideo">createVideo()</a> or <a href="#/p5/createDiv">createDiv()</a>.
43524 * Unlike the main graphics context, pixels in additional graphics areas created
43525 * with <a href="#/p5/createGraphics">createGraphics()</a> can be entirely
43526 * or partially transparent. This function clears everything to make all of
43527 * the pixels 100% transparent.
43528 *
43529 * @method clear
43530 * @chainable
43531 * @example
43532 * <div>
43533 * <code>
43534 * // Clear the screen on mouse press.
43535 * function draw() {
43536 * ellipse(mouseX, mouseY, 20, 20);
43537 * }
43538 * function mousePressed() {
43539 * clear();
43540 * background(128);
43541 * }
43542 * </code>
43543 * </div>
43544 *
43545 * @alt
43546 * small white ellipses are continually drawn at mouse's x and y coordinates.
43547 */
43548
43549 _main.default.prototype.clear = function() {
43550 this._renderer.clear();
43551 return this;
43552 };
43553
43554 /**
43555 * <a href="#/p5/colorMode">colorMode()</a> changes the way p5.js interprets
43556 * color data. By default, the parameters for <a href="#/p5/fill">fill()</a>,
43557 * <a href="#/p5/stroke">stroke()</a>, <a href="#/p5/background">background()</a>,
43558 * and <a href="#/p5/color">color()</a> are defined by values between 0 and 255
43559 * using the RGB color model. This is equivalent to setting colorMode(RGB, 255).
43560 * Setting colorMode(HSB) lets you use the HSB system instead. By default, this
43561 * is colorMode(HSB, 360, 100, 100, 1). You can also use HSL.
43562 *
43563 * Note: existing color objects remember the mode that they were created in,
43564 * so you can change modes as you like without affecting their appearance.
43565 *
43566 * @method colorMode
43567 * @param {Constant} mode either RGB, HSB or HSL, corresponding to
43568 * Red/Green/Blue and Hue/Saturation/Brightness
43569 * (or Lightness)
43570 * @param {Number} [max] range for all values
43571 * @chainable
43572 *
43573 * @example
43574 * <div>
43575 * <code>
43576 * noStroke();
43577 * colorMode(RGB, 100);
43578 * for (let i = 0; i < 100; i++) {
43579 * for (let j = 0; j < 100; j++) {
43580 * stroke(i, j, 0);
43581 * point(i, j);
43582 * }
43583 * }
43584 * </code>
43585 * </div>
43586 *
43587 * <div>
43588 * <code>
43589 * noStroke();
43590 * colorMode(HSB, 100);
43591 * for (let i = 0; i < 100; i++) {
43592 * for (let j = 0; j < 100; j++) {
43593 * stroke(i, j, 100);
43594 * point(i, j);
43595 * }
43596 * }
43597 * </code>
43598 * </div>
43599 *
43600 * <div>
43601 * <code>
43602 * colorMode(RGB, 255);
43603 * let c = color(127, 255, 0);
43604 * colorMode(RGB, 1);
43605 * let myColor = c._getRed();
43606 * text(myColor, 10, 10, 80, 80);
43607 * </code>
43608 * </div>
43609 *
43610 * <div>
43611 * <code>
43612 * noFill();
43613 * colorMode(RGB, 255, 255, 255, 1);
43614 * background(255);
43615 * strokeWeight(4);
43616 * stroke(255, 0, 10, 0.3);
43617 * ellipse(40, 40, 50, 50);
43618 * ellipse(50, 50, 40, 40);
43619 * </code>
43620 * </div>
43621 *
43622 * @alt
43623 *Green to red gradient from bottom L to top R. shading originates from top left.
43624 *Rainbow gradient from left to right. Brightness increasing to white at top.
43625 *unknown image.
43626 *50x50 ellipse at middle L & 40x40 ellipse at center. Translucent pink outlines.
43627 */
43628
43629 /**
43630 * @method colorMode
43631 * @param {Constant} mode
43632 * @param {Number} max1 range for the red or hue depending on the
43633 * current color mode
43634 * @param {Number} max2 range for the green or saturation depending
43635 * on the current color mode
43636 * @param {Number} max3 range for the blue or brightness/lightness
43637 * depending on the current color mode
43638 * @param {Number} [maxA] range for the alpha
43639 * @chainable
43640 */
43641 _main.default.prototype.colorMode = function(mode, max1, max2, max3, maxA) {
43642 _main.default._validateParameters('colorMode', arguments);
43643 if (
43644 mode === constants.RGB ||
43645 mode === constants.HSB ||
43646 mode === constants.HSL
43647 ) {
43648 // Set color mode.
43649 this._colorMode = mode;
43650
43651 // Set color maxes.
43652 var maxes = this._colorMaxes[mode];
43653 if (arguments.length === 2) {
43654 maxes[0] = max1; // Red
43655 maxes[1] = max1; // Green
43656 maxes[2] = max1; // Blue
43657 maxes[3] = max1; // Alpha
43658 } else if (arguments.length === 4) {
43659 maxes[0] = max1; // Red
43660 maxes[1] = max2; // Green
43661 maxes[2] = max3; // Blue
43662 } else if (arguments.length === 5) {
43663 maxes[0] = max1; // Red
43664 maxes[1] = max2; // Green
43665 maxes[2] = max3; // Blue
43666 maxes[3] = maxA; // Alpha
43667 }
43668 }
43669
43670 return this;
43671 };
43672
43673 /**
43674 * Sets the color used to fill shapes. For example, if you run fill(204, 102, 0),
43675 * all shapes drawn after the fill command will be filled with the color orange.
43676 * This color is either specified in terms of the RGB or HSB color depending on
43677 * the current <a href="#/p5/colorMode">colorMode()</a>. (The default color space
43678 * is RGB, with each value in the range from 0 to 255). The alpha range by default
43679 * is also 0 to 255.
43680 *
43681 * If a single string argument is provided, RGB, RGBA and Hex CSS color strings
43682 * and all named color strings are supported. In this case, an alpha number
43683 * value as a second argument is not supported, the RGBA form should be used.
43684 *
43685 * A p5 <a href="#/p5.Color">Color</a> object can also be provided to set the fill color.
43686 *
43687 * @method fill
43688 * @param {Number} v1 red or hue value relative to
43689 * the current color range
43690 * @param {Number} v2 green or saturation value
43691 * relative to the current color range
43692 * @param {Number} v3 blue or brightness value
43693 * relative to the current color range
43694 * @param {Number} [alpha]
43695 * @chainable
43696 * @example
43697 * <div>
43698 * <code>
43699 * // Grayscale integer value
43700 * fill(51);
43701 * rect(20, 20, 60, 60);
43702 * </code>
43703 * </div>
43704 *
43705 * <div>
43706 * <code>
43707 * // R, G & B integer values
43708 * fill(255, 204, 0);
43709 * rect(20, 20, 60, 60);
43710 * </code>
43711 * </div>
43712 *
43713 * <div>
43714 * <code>
43715 * // H, S & B integer values
43716 * colorMode(HSB);
43717 * fill(255, 204, 100);
43718 * rect(20, 20, 60, 60);
43719 * </code>
43720 * </div>
43721 *
43722 * <div>
43723 * <code>
43724 * // Named SVG/CSS color string
43725 * fill('red');
43726 * rect(20, 20, 60, 60);
43727 * </code>
43728 * </div>
43729 *
43730 * <div>
43731 * <code>
43732 * // three-digit hexadecimal RGB notation
43733 * fill('#fae');
43734 * rect(20, 20, 60, 60);
43735 * </code>
43736 * </div>
43737 *
43738 * <div>
43739 * <code>
43740 * // six-digit hexadecimal RGB notation
43741 * fill('#222222');
43742 * rect(20, 20, 60, 60);
43743 * </code>
43744 * </div>
43745 *
43746 * <div>
43747 * <code>
43748 * // integer RGB notation
43749 * fill('rgb(0,255,0)');
43750 * rect(20, 20, 60, 60);
43751 * </code>
43752 * </div>
43753 *
43754 * <div>
43755 * <code>
43756 * // integer RGBA notation
43757 * fill('rgba(0,255,0, 0.25)');
43758 * rect(20, 20, 60, 60);
43759 * </code>
43760 * </div>
43761 *
43762 * <div>
43763 * <code>
43764 * // percentage RGB notation
43765 * fill('rgb(100%,0%,10%)');
43766 * rect(20, 20, 60, 60);
43767 * </code>
43768 * </div>
43769 *
43770 * <div>
43771 * <code>
43772 * // percentage RGBA notation
43773 * fill('rgba(100%,0%,100%,0.5)');
43774 * rect(20, 20, 60, 60);
43775 * </code>
43776 * </div>
43777 *
43778 * <div>
43779 * <code>
43780 * // p5 Color object
43781 * fill(color(0, 0, 255));
43782 * rect(20, 20, 60, 60);
43783 * </code>
43784 * </div>
43785 *
43786 * @alt
43787 * 60x60 dark charcoal grey rect with black outline in center of canvas.
43788 * 60x60 yellow rect with black outline in center of canvas.
43789 * 60x60 royal blue rect with black outline in center of canvas.
43790 * 60x60 red rect with black outline in center of canvas.
43791 * 60x60 pink rect with black outline in center of canvas.
43792 * 60x60 black rect with black outline in center of canvas.
43793 * 60x60 light green rect with black outline in center of canvas.
43794 * 60x60 soft green rect with black outline in center of canvas.
43795 * 60x60 red rect with black outline in center of canvas.
43796 * 60x60 dark fuchsia rect with black outline in center of canvas.
43797 * 60x60 blue rect with black outline in center of canvas.
43798 */
43799
43800 /**
43801 * @method fill
43802 * @param {String} value a color string
43803 * @chainable
43804 */
43805
43806 /**
43807 * @method fill
43808 * @param {Number} gray a gray value
43809 * @param {Number} [alpha]
43810 * @chainable
43811 */
43812
43813 /**
43814 * @method fill
43815 * @param {Number[]} values an array containing the red,green,blue &
43816 * and alpha components of the color
43817 * @chainable
43818 */
43819
43820 /**
43821 * @method fill
43822 * @param {p5.Color} color the fill color
43823 * @chainable
43824 */
43825 _main.default.prototype.fill = function() {
43826 var _this$_renderer2;
43827 this._renderer._setProperty('_fillSet', true);
43828 this._renderer._setProperty('_doFill', true);
43829 (_this$_renderer2 = this._renderer).fill.apply(_this$_renderer2, arguments);
43830 return this;
43831 };
43832
43833 /**
43834 * Disables filling geometry. If both <a href="#/p5/noStroke">noStroke()</a> and <a href="#/p5/noFill">noFill()</a> are called,
43835 * nothing will be drawn to the screen.
43836 *
43837 * @method noFill
43838 * @chainable
43839 * @example
43840 * <div>
43841 * <code>
43842 * rect(15, 10, 55, 55);
43843 * noFill();
43844 * rect(20, 20, 60, 60);
43845 * </code>
43846 * </div>
43847 *
43848 * <div modernizr='webgl'>
43849 * <code>
43850 * function setup() {
43851 * createCanvas(100, 100, WEBGL);
43852 * }
43853 *
43854 * function draw() {
43855 * background(0);
43856 * noFill();
43857 * stroke(100, 100, 240);
43858 * rotateX(frameCount * 0.01);
43859 * rotateY(frameCount * 0.01);
43860 * box(45, 45, 45);
43861 * }
43862 * </code>
43863 * </div>
43864 *
43865 * @alt
43866 * white rect top middle and noFill rect center. Both 60x60 with black outlines.
43867 * black canvas with purple cube wireframe spinning
43868 */
43869 _main.default.prototype.noFill = function() {
43870 this._renderer._setProperty('_doFill', false);
43871 return this;
43872 };
43873
43874 /**
43875 * Disables drawing the stroke (outline). If both <a href="#/p5/noStroke">noStroke()</a> and <a href="#/p5/noFill">noFill()</a>
43876 * are called, nothing will be drawn to the screen.
43877 *
43878 * @method noStroke
43879 * @chainable
43880 * @example
43881 * <div>
43882 * <code>
43883 * noStroke();
43884 * rect(20, 20, 60, 60);
43885 * </code>
43886 * </div>
43887 *
43888 * <div modernizr='webgl'>
43889 * <code>
43890 * function setup() {
43891 * createCanvas(100, 100, WEBGL);
43892 * }
43893 *
43894 * function draw() {
43895 * background(0);
43896 * noStroke();
43897 * fill(240, 150, 150);
43898 * rotateX(frameCount * 0.01);
43899 * rotateY(frameCount * 0.01);
43900 * box(45, 45, 45);
43901 * }
43902 * </code>
43903 * </div>
43904 *
43905 * @alt
43906 * 60x60 white rect at center. no outline.
43907 * black canvas with pink cube spinning
43908 */
43909 _main.default.prototype.noStroke = function() {
43910 this._renderer._setProperty('_doStroke', false);
43911 return this;
43912 };
43913
43914 /**
43915 * Sets the color used to draw lines and borders around shapes. This color
43916 * is either specified in terms of the RGB or HSB color depending on the
43917 * current <a href="#/p5/colorMode">colorMode()</a> (the default color space
43918 * is RGB, with each value in the range from 0 to 255). The alpha range by
43919 * default is also 0 to 255.
43920 *
43921 * If a single string argument is provided, RGB, RGBA and Hex CSS color
43922 * strings and all named color strings are supported. In this case, an alpha
43923 * number value as a second argument is not supported, the RGBA form should be
43924 * used.
43925 *
43926 * A p5 <a href="#/p5.Color">Color</a> object can also be provided to set the stroke color.
43927 *
43928 * @method stroke
43929 * @param {Number} v1 red or hue value relative to
43930 * the current color range
43931 * @param {Number} v2 green or saturation value
43932 * relative to the current color range
43933 * @param {Number} v3 blue or brightness value
43934 * relative to the current color range
43935 * @param {Number} [alpha]
43936 * @chainable
43937 *
43938 * @example
43939 * <div>
43940 * <code>
43941 * // Grayscale integer value
43942 * strokeWeight(4);
43943 * stroke(51);
43944 * rect(20, 20, 60, 60);
43945 * </code>
43946 * </div>
43947 *
43948 * <div>
43949 * <code>
43950 * // R, G & B integer values
43951 * stroke(255, 204, 0);
43952 * strokeWeight(4);
43953 * rect(20, 20, 60, 60);
43954 * </code>
43955 * </div>
43956 *
43957 * <div>
43958 * <code>
43959 * // H, S & B integer values
43960 * colorMode(HSB);
43961 * strokeWeight(4);
43962 * stroke(255, 204, 100);
43963 * rect(20, 20, 60, 60);
43964 * </code>
43965 * </div>
43966 *
43967 * <div>
43968 * <code>
43969 * // Named SVG/CSS color string
43970 * stroke('red');
43971 * strokeWeight(4);
43972 * rect(20, 20, 60, 60);
43973 * </code>
43974 * </div>
43975 *
43976 * <div>
43977 * <code>
43978 * // three-digit hexadecimal RGB notation
43979 * stroke('#fae');
43980 * strokeWeight(4);
43981 * rect(20, 20, 60, 60);
43982 * </code>
43983 * </div>
43984 *
43985 * <div>
43986 * <code>
43987 * // six-digit hexadecimal RGB notation
43988 * stroke('#222222');
43989 * strokeWeight(4);
43990 * rect(20, 20, 60, 60);
43991 * </code>
43992 * </div>
43993 *
43994 * <div>
43995 * <code>
43996 * // integer RGB notation
43997 * stroke('rgb(0,255,0)');
43998 * strokeWeight(4);
43999 * rect(20, 20, 60, 60);
44000 * </code>
44001 * </div>
44002 *
44003 * <div>
44004 * <code>
44005 * // integer RGBA notation
44006 * stroke('rgba(0,255,0,0.25)');
44007 * strokeWeight(4);
44008 * rect(20, 20, 60, 60);
44009 * </code>
44010 * </div>
44011 *
44012 * <div>
44013 * <code>
44014 * // percentage RGB notation
44015 * stroke('rgb(100%,0%,10%)');
44016 * strokeWeight(4);
44017 * rect(20, 20, 60, 60);
44018 * </code>
44019 * </div>
44020 *
44021 * <div>
44022 * <code>
44023 * // percentage RGBA notation
44024 * stroke('rgba(100%,0%,100%,0.5)');
44025 * strokeWeight(4);
44026 * rect(20, 20, 60, 60);
44027 * </code>
44028 * </div>
44029 *
44030 * <div>
44031 * <code>
44032 * // p5 Color object
44033 * stroke(color(0, 0, 255));
44034 * strokeWeight(4);
44035 * rect(20, 20, 60, 60);
44036 * </code>
44037 * </div>
44038 *
44039 * @alt
44040 * 60x60 white rect at center. Dark charcoal grey outline.
44041 * 60x60 white rect at center. Yellow outline.
44042 * 60x60 white rect at center. Royal blue outline.
44043 * 60x60 white rect at center. Red outline.
44044 * 60x60 white rect at center. Pink outline.
44045 * 60x60 white rect at center. Black outline.
44046 * 60x60 white rect at center. Bright green outline.
44047 * 60x60 white rect at center. Soft green outline.
44048 * 60x60 white rect at center. Red outline.
44049 * 60x60 white rect at center. Dark fuchsia outline.
44050 * 60x60 white rect at center. Blue outline.
44051 */
44052
44053 /**
44054 * @method stroke
44055 * @param {String} value a color string
44056 * @chainable
44057 */
44058
44059 /**
44060 * @method stroke
44061 * @param {Number} gray a gray value
44062 * @param {Number} [alpha]
44063 * @chainable
44064 */
44065
44066 /**
44067 * @method stroke
44068 * @param {Number[]} values an array containing the red,green,blue &
44069 * and alpha components of the color
44070 * @chainable
44071 */
44072
44073 /**
44074 * @method stroke
44075 * @param {p5.Color} color the stroke color
44076 * @chainable
44077 */
44078
44079 _main.default.prototype.stroke = function() {
44080 var _this$_renderer3;
44081 this._renderer._setProperty('_strokeSet', true);
44082 this._renderer._setProperty('_doStroke', true);
44083 (_this$_renderer3 = this._renderer).stroke.apply(_this$_renderer3, arguments);
44084 return this;
44085 };
44086
44087 /**
44088 * All drawing that follows <a href="#/p5/erase">erase()</a> will subtract from
44089 * the canvas.Erased areas will reveal the web page underneath the canvas.Erasing
44090 * can be canceled with <a href="#/p5/noErase">noErase()</a>.
44091 *
44092 * Drawing done with <a href="#/p5/image">image()</a> and <a href="#/p5/background">
44093 * background()</a> in between <a href="#/p5/erase">erase()</a> and
44094 * <a href="#/p5/noErase">noErase()</a> will not erase the canvas but works as usual.
44095 *
44096 * @method erase
44097 * @param {Number} [strengthFill] A number (0-255) for the strength of erasing for a shape's fill.
44098 * This will default to 255 when no argument is given, which
44099 * is full strength.
44100 * @param {Number} [strengthStroke] A number (0-255) for the strength of erasing for a shape's stroke.
44101 * This will default to 255 when no argument is given, which
44102 * is full strength.
44103 *
44104 * @chainable
44105 * @example
44106 * <div>
44107 * <code>
44108 * background(100, 100, 250);
44109 * fill(250, 100, 100);
44110 * rect(20, 20, 60, 60);
44111 * erase();
44112 * ellipse(25, 30, 30);
44113 * noErase();
44114 * </code>
44115 * </div>
44116 *
44117 * <div>
44118 * <code>
44119 * background(150, 250, 150);
44120 * fill(100, 100, 250);
44121 * rect(20, 20, 60, 60);
44122 * strokeWeight(5);
44123 * erase(150, 255);
44124 * triangle(50, 10, 70, 50, 90, 10);
44125 * noErase();
44126 * </code>
44127 * </div>
44128 *
44129 * <div>
44130 * <code>
44131 * function setup() {
44132 * smooth();
44133 * createCanvas(100, 100, WEBGL);
44134 * // Make a &lt;p&gt; element and put it behind the canvas
44135 * let p = createP('I am a dom element');
44136 * p.center();
44137 * p.style('font-size', '20px');
44138 * p.style('text-align', 'center');
44139 * p.style('z-index', '-9999');
44140 * }
44141 *
44142 * function draw() {
44143 * background(250, 250, 150);
44144 * fill(15, 195, 185);
44145 * noStroke();
44146 * sphere(30);
44147 * erase();
44148 * rotateY(frameCount * 0.02);
44149 * translate(0, 0, 40);
44150 * torus(15, 5);
44151 * noErase();
44152 * }
44153 * </code>
44154 * </div>
44155 *
44156 * @alt
44157 * 60x60 centered pink rect, purple background. Elliptical area in top-left of rect is erased white.
44158 * 60x60 centered purple rect, mint green background. Triangle in top-right is partially erased with fully erased outline.
44159 * 60x60 centered teal sphere, yellow background. Torus rotating around sphere erases to reveal black text underneath.
44160 */
44161 _main.default.prototype.erase = function() {
44162 var opacityFill =
44163 arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 255;
44164 var opacityStroke =
44165 arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 255;
44166 this._renderer.erase(opacityFill, opacityStroke);
44167
44168 return this;
44169 };
44170
44171 /**
44172 * Ends erasing that was started with <a href="#/p5/erase">erase()</a>.
44173 * The <a href="#/p5/fill">fill()</a>, <a href="#/p5/stroke">stroke()</a>, and
44174 * <a href="#/p5/blendMode">blendMode()</a> settings will return to what they were
44175 * prior to calling <a href="#/p5/erase">erase()</a>.
44176 *
44177 * @method noErase
44178 * @chainable
44179 * @example
44180 * <div>
44181 * <code>
44182 * background(235, 145, 15);
44183 * noStroke();
44184 * fill(30, 45, 220);
44185 * rect(30, 10, 10, 80);
44186 * erase();
44187 * ellipse(50, 50, 60);
44188 * noErase();
44189 * rect(70, 10, 10, 80);
44190 * </code>
44191 * </div>
44192 *
44193 * @alt
44194 * Orange background, with two tall blue rectangles. A centered ellipse erased the first blue rect but not the second.
44195 */
44196
44197 _main.default.prototype.noErase = function() {
44198 this._renderer.noErase();
44199 return this;
44200 };
44201 var _default = _main.default;
44202 exports.default = _default;
44203 },
44204 { '../core/constants': 43, '../core/main': 54, './p5.Color': 41 }
44205 ],
44206 43: [
44207 function(_dereq_, module, exports) {
44208 'use strict';
44209 Object.defineProperty(exports, '__esModule', { value: true });
44210 exports.FILL = exports.STROKE = exports.CURVE = exports.BEZIER = exports.QUADRATIC = exports.LINEAR = exports._CTX_MIDDLE = exports._DEFAULT_LEADMULT = exports._DEFAULT_TEXT_FILL = exports.BOLDITALIC = exports.BOLD = exports.ITALIC = exports.NORMAL = exports.BLUR = exports.ERODE = exports.DILATE = exports.POSTERIZE = exports.INVERT = exports.OPAQUE = exports.GRAY = exports.THRESHOLD = exports.BURN = exports.DODGE = exports.SOFT_LIGHT = exports.HARD_LIGHT = exports.OVERLAY = exports.REPLACE = exports.SCREEN = exports.MULTIPLY = exports.EXCLUSION = exports.SUBTRACT = exports.DIFFERENCE = exports.LIGHTEST = exports.DARKEST = exports.ADD = exports.REMOVE = exports.BLEND = exports.UP_ARROW = exports.TAB = exports.SHIFT = exports.RIGHT_ARROW = exports.RETURN = exports.OPTION = exports.LEFT_ARROW = exports.ESCAPE = exports.ENTER = exports.DOWN_ARROW = exports.DELETE = exports.CONTROL = exports.BACKSPACE = exports.ALT = exports.AUTO = exports.HSL = exports.HSB = exports.RGB = exports.MITER = exports.BEVEL = exports.ROUND = exports.SQUARE = exports.PROJECT = exports.PIE = exports.CHORD = exports.OPEN = exports.CLOSE = exports.TESS = exports.QUAD_STRIP = exports.QUADS = exports.TRIANGLE_STRIP = exports.TRIANGLE_FAN = exports.TRIANGLES = exports.LINE_LOOP = exports.LINE_STRIP = exports.LINES = exports.POINTS = exports.BASELINE = exports.BOTTOM = exports.TOP = exports.CENTER = exports.LEFT = exports.RIGHT = exports.RADIUS = exports.CORNERS = exports.CORNER = exports.RAD_TO_DEG = exports.DEG_TO_RAD = exports.RADIANS = exports.DEGREES = exports.TWO_PI = exports.TAU = exports.QUARTER_PI = exports.PI = exports.HALF_PI = exports.WAIT = exports.TEXT = exports.MOVE = exports.HAND = exports.CROSS = exports.ARROW = exports.WEBGL = exports.P2D = void 0;
44211 exports.AXES = exports.GRID = exports._DEFAULT_FILL = exports._DEFAULT_STROKE = exports.PORTRAIT = exports.LANDSCAPE = exports.MIRROR = exports.CLAMP = exports.REPEAT = exports.NEAREST = exports.IMAGE = exports.IMMEDIATE = exports.TEXTURE = void 0; /**
44212 * @module Constants
44213 * @submodule Constants
44214 * @for p5
44215 */
44216
44217 var _PI = Math.PI;
44218
44219 // GRAPHICS RENDERER
44220 /**
44221 * The default, two-dimensional renderer.
44222 * @property {String} P2D
44223 * @final
44224 */
44225 var P2D = 'p2d';
44226 /**
44227 * One of the two render modes in p5.js: P2D (default renderer) and WEBGL
44228 * Enables 3D render by introducing the third dimension: Z
44229 * @property {String} WEBGL
44230 * @final
44231 */ exports.P2D = P2D;
44232 var WEBGL = 'webgl';
44233
44234 // ENVIRONMENT
44235 /**
44236 * @property {String} ARROW
44237 * @final
44238 */ exports.WEBGL = WEBGL;
44239 var ARROW = 'default';
44240 /**
44241 * @property {String} CROSS
44242 * @final
44243 */ exports.ARROW = ARROW;
44244 var CROSS = 'crosshair';
44245 /**
44246 * @property {String} HAND
44247 * @final
44248 */ exports.CROSS = CROSS;
44249 var HAND = 'pointer';
44250 /**
44251 * @property {String} MOVE
44252 * @final
44253 */ exports.HAND = HAND;
44254 var MOVE = 'move';
44255 /**
44256 * @property {String} TEXT
44257 * @final
44258 */ exports.MOVE = MOVE;
44259 var TEXT = 'text';
44260 /**
44261 * @property {String} WAIT
44262 * @final
44263 */ exports.TEXT = TEXT;
44264 var WAIT = 'wait';
44265
44266 // TRIGONOMETRY
44267
44268 /**
44269 * HALF_PI is a mathematical constant with the value
44270 * 1.57079632679489661923. It is half the ratio of the
44271 * circumference of a circle to its diameter. It is useful in
44272 * combination with the trigonometric functions <a href="#/p5/sin">sin()</a> and <a href="#/p5/cos">cos()</a>.
44273 *
44274 * @property {Number} HALF_PI
44275 * @final
44276 *
44277 * @example
44278 * <div><code>
44279 * arc(50, 50, 80, 80, 0, HALF_PI);
44280 * </code></div>
44281 *
44282 * @alt
44283 * 80x80 white quarter-circle with curve toward bottom right of canvas.
44284 */ exports.WAIT = WAIT;
44285 var HALF_PI = _PI / 2;
44286 /**
44287 * PI is a mathematical constant with the value
44288 * 3.14159265358979323846. It is the ratio of the circumference
44289 * of a circle to its diameter. It is useful in combination with
44290 * the trigonometric functions <a href="#/p5/sin">sin()</a> and <a href="#/p5/cos">cos()</a>.
44291 *
44292 * @property {Number} PI
44293 * @final
44294 *
44295 * @example
44296 * <div><code>
44297 * arc(50, 50, 80, 80, 0, PI);
44298 * </code></div>
44299 *
44300 * @alt
44301 * white half-circle with curve toward bottom of canvas.
44302 */ exports.HALF_PI = HALF_PI;
44303 var PI = _PI;
44304 /**
44305 * QUARTER_PI is a mathematical constant with the value 0.7853982.
44306 * It is one quarter the ratio of the circumference of a circle to
44307 * its diameter. It is useful in combination with the trigonometric
44308 * functions <a href="#/p5/sin">sin()</a> and <a href="#/p5/cos">cos()</a>.
44309 *
44310 * @property {Number} QUARTER_PI
44311 * @final
44312 *
44313 * @example
44314 * <div><code>
44315 * arc(50, 50, 80, 80, 0, QUARTER_PI);
44316 * </code></div>
44317 *
44318 * @alt
44319 * white eighth-circle rotated about 40 degrees with curve bottom right canvas.
44320 */ exports.PI = PI;
44321 var QUARTER_PI = _PI / 4;
44322 /**
44323 * TAU is an alias for TWO_PI, a mathematical constant with the
44324 * value 6.28318530717958647693. It is twice the ratio of the
44325 * circumference of a circle to its diameter. It is useful in
44326 * combination with the trigonometric functions <a href="#/p5/sin">sin()</a> and <a href="#/p5/cos">cos()</a>.
44327 *
44328 * @property {Number} TAU
44329 * @final
44330 *
44331 * @example
44332 * <div><code>
44333 * arc(50, 50, 80, 80, 0, TAU);
44334 * </code></div>
44335 *
44336 * @alt
44337 * 80x80 white ellipse shape in center of canvas.
44338 */ exports.QUARTER_PI = QUARTER_PI;
44339 var TAU = _PI * 2;
44340 /**
44341 * TWO_PI is a mathematical constant with the value
44342 * 6.28318530717958647693. It is twice the ratio of the
44343 * circumference of a circle to its diameter. It is useful in
44344 * combination with the trigonometric functions <a href="#/p5/sin">sin()</a> and <a href="#/p5/cos">cos()</a>.
44345 *
44346 * @property {Number} TWO_PI
44347 * @final
44348 *
44349 * @example
44350 * <div><code>
44351 * arc(50, 50, 80, 80, 0, TWO_PI);
44352 * </code></div>
44353 *
44354 * @alt
44355 * 80x80 white ellipse shape in center of canvas.
44356 */ exports.TAU = TAU;
44357 var TWO_PI = _PI * 2;
44358 /**
44359 * Constant to be used with <a href="#/p5/angleMode">angleMode()</a> function, to set the mode which
44360 * p5.js interprates and calculates angles (either DEGREES or RADIANS).
44361 * @property {String} DEGREES
44362 * @final
44363 *
44364 * @example
44365 * <div class='norender'><code>
44366 * function setup() {
44367 * angleMode(DEGREES);
44368 * }
44369 * </code></div>
44370 */ exports.TWO_PI = TWO_PI;
44371 var DEGREES = 'degrees';
44372 /**
44373 * Constant to be used with <a href="#/p5/angleMode">angleMode()</a> function, to set the mode which
44374 * p5.js interprates and calculates angles (either RADIANS or DEGREES).
44375 * @property {String} RADIANS
44376 * @final
44377 *
44378 * @example
44379 * <div class='norender'><code>
44380 * function setup() {
44381 * angleMode(RADIANS);
44382 * }
44383 * </code></div>
44384 */ exports.DEGREES = DEGREES;
44385 var RADIANS = 'radians';
44386 exports.RADIANS = RADIANS;
44387 var DEG_TO_RAD = _PI / 180.0;
44388 exports.DEG_TO_RAD = DEG_TO_RAD;
44389 var RAD_TO_DEG = 180.0 / _PI;
44390
44391 // SHAPE
44392 /**
44393 * @property {String} CORNER
44394 * @final
44395 */ exports.RAD_TO_DEG = RAD_TO_DEG;
44396 var CORNER = 'corner';
44397 /**
44398 * @property {String} CORNERS
44399 * @final
44400 */ exports.CORNER = CORNER;
44401 var CORNERS = 'corners';
44402 /**
44403 * @property {String} RADIUS
44404 * @final
44405 */ exports.CORNERS = CORNERS;
44406 var RADIUS = 'radius';
44407 /**
44408 * @property {String} RIGHT
44409 * @final
44410 */ exports.RADIUS = RADIUS;
44411 var RIGHT = 'right';
44412 /**
44413 * @property {String} LEFT
44414 * @final
44415 */ exports.RIGHT = RIGHT;
44416 var LEFT = 'left';
44417 /**
44418 * @property {String} CENTER
44419 * @final
44420 */ exports.LEFT = LEFT;
44421 var CENTER = 'center';
44422 /**
44423 * @property {String} TOP
44424 * @final
44425 */ exports.CENTER = CENTER;
44426 var TOP = 'top';
44427 /**
44428 * @property {String} BOTTOM
44429 * @final
44430 */ exports.TOP = TOP;
44431 var BOTTOM = 'bottom';
44432 /**
44433 * @property {String} BASELINE
44434 * @final
44435 * @default alphabetic
44436 */ exports.BOTTOM = BOTTOM;
44437 var BASELINE = 'alphabetic';
44438 /**
44439 * @property {Number} POINTS
44440 * @final
44441 * @default 0x0000
44442 */ exports.BASELINE = BASELINE;
44443 var POINTS = 0x0000;
44444 /**
44445 * @property {Number} LINES
44446 * @final
44447 * @default 0x0001
44448 */ exports.POINTS = POINTS;
44449 var LINES = 0x0001;
44450 /**
44451 * @property {Number} LINE_STRIP
44452 * @final
44453 * @default 0x0003
44454 */ exports.LINES = LINES;
44455 var LINE_STRIP = 0x0003;
44456 /**
44457 * @property {Number} LINE_LOOP
44458 * @final
44459 * @default 0x0002
44460 */ exports.LINE_STRIP = LINE_STRIP;
44461 var LINE_LOOP = 0x0002;
44462 /**
44463 * @property {Number} TRIANGLES
44464 * @final
44465 * @default 0x0004
44466 */ exports.LINE_LOOP = LINE_LOOP;
44467 var TRIANGLES = 0x0004;
44468 /**
44469 * @property {Number} TRIANGLE_FAN
44470 * @final
44471 * @default 0x0006
44472 */ exports.TRIANGLES = TRIANGLES;
44473 var TRIANGLE_FAN = 0x0006;
44474 /**
44475 * @property {Number} TRIANGLE_STRIP
44476 * @final
44477 * @default 0x0005
44478 */ exports.TRIANGLE_FAN = TRIANGLE_FAN;
44479 var TRIANGLE_STRIP = 0x0005;
44480 /**
44481 * @property {String} QUADS
44482 * @final
44483 */ exports.TRIANGLE_STRIP = TRIANGLE_STRIP;
44484 var QUADS = 'quads';
44485 /**
44486 * @property {String} QUAD_STRIP
44487 * @final
44488 * @default quad_strip
44489 */ exports.QUADS = QUADS;
44490 var QUAD_STRIP = 'quad_strip';
44491 /**
44492 * @property {String} TESS
44493 * @final
44494 * @default tess
44495 */ exports.QUAD_STRIP = QUAD_STRIP;
44496 var TESS = 'tess';
44497 /**
44498 * @property {String} CLOSE
44499 * @final
44500 */ exports.TESS = TESS;
44501 var CLOSE = 'close';
44502 /**
44503 * @property {String} OPEN
44504 * @final
44505 */ exports.CLOSE = CLOSE;
44506 var OPEN = 'open';
44507 /**
44508 * @property {String} CHORD
44509 * @final
44510 */ exports.OPEN = OPEN;
44511 var CHORD = 'chord';
44512 /**
44513 * @property {String} PIE
44514 * @final
44515 */ exports.CHORD = CHORD;
44516 var PIE = 'pie';
44517 /**
44518 * @property {String} PROJECT
44519 * @final
44520 * @default square
44521 */ exports.PIE = PIE;
44522 var PROJECT = 'square'; // PEND: careful this is counterintuitive
44523 /**
44524 * @property {String} SQUARE
44525 * @final
44526 * @default butt
44527 */ exports.PROJECT = PROJECT;
44528 var SQUARE = 'butt';
44529 /**
44530 * @property {String} ROUND
44531 * @final
44532 */ exports.SQUARE = SQUARE;
44533 var ROUND = 'round';
44534 /**
44535 * @property {String} BEVEL
44536 * @final
44537 */ exports.ROUND = ROUND;
44538 var BEVEL = 'bevel';
44539 /**
44540 * @property {String} MITER
44541 * @final
44542 */ exports.BEVEL = BEVEL;
44543 var MITER = 'miter';
44544
44545 // COLOR
44546 /**
44547 * @property {String} RGB
44548 * @final
44549 */ exports.MITER = MITER;
44550 var RGB = 'rgb';
44551 /**
44552 * HSB (hue, saturation, brightness) is a type of color model.
44553 * You can learn more about it at
44554 * <a href="https://learnui.design/blog/the-hsb-color-system-practicioners-primer.html">HSB</a>.
44555 *
44556 * @property {String} HSB
44557 * @final
44558 */ exports.RGB = RGB;
44559 var HSB = 'hsb';
44560 /**
44561 * @property {String} HSL
44562 * @final
44563 */ exports.HSB = HSB;
44564 var HSL = 'hsl';
44565
44566 // DOM EXTENSION
44567 /**
44568 * AUTO allows us to automatically set the width or height of an element (but not both),
44569 * based on the current height and width of the element. Only one parameter can
44570 * be passed to the <a href="/#/p5.Element/size">size</a> function as AUTO, at a time.
44571 *
44572 * @property {String} AUTO
44573 * @final
44574 */ exports.HSL = HSL;
44575 var AUTO = 'auto';
44576
44577 /**
44578 * @property {Number} ALT
44579 * @final
44580 */
44581 // INPUT
44582 exports.AUTO = AUTO;
44583 var ALT = 18;
44584 /**
44585 * @property {Number} BACKSPACE
44586 * @final
44587 */ exports.ALT = ALT;
44588 var BACKSPACE = 8;
44589 /**
44590 * @property {Number} CONTROL
44591 * @final
44592 */ exports.BACKSPACE = BACKSPACE;
44593 var CONTROL = 17;
44594 /**
44595 * @property {Number} DELETE
44596 * @final
44597 */ exports.CONTROL = CONTROL;
44598 var DELETE = 46;
44599 /**
44600 * @property {Number} DOWN_ARROW
44601 * @final
44602 */ exports.DELETE = DELETE;
44603 var DOWN_ARROW = 40;
44604 /**
44605 * @property {Number} ENTER
44606 * @final
44607 */ exports.DOWN_ARROW = DOWN_ARROW;
44608 var ENTER = 13;
44609 /**
44610 * @property {Number} ESCAPE
44611 * @final
44612 */ exports.ENTER = ENTER;
44613 var ESCAPE = 27;
44614 /**
44615 * @property {Number} LEFT_ARROW
44616 * @final
44617 */ exports.ESCAPE = ESCAPE;
44618 var LEFT_ARROW = 37;
44619 /**
44620 * @property {Number} OPTION
44621 * @final
44622 */ exports.LEFT_ARROW = LEFT_ARROW;
44623 var OPTION = 18;
44624 /**
44625 * @property {Number} RETURN
44626 * @final
44627 */ exports.OPTION = OPTION;
44628 var RETURN = 13;
44629 /**
44630 * @property {Number} RIGHT_ARROW
44631 * @final
44632 */ exports.RETURN = RETURN;
44633 var RIGHT_ARROW = 39;
44634 /**
44635 * @property {Number} SHIFT
44636 * @final
44637 */ exports.RIGHT_ARROW = RIGHT_ARROW;
44638 var SHIFT = 16;
44639 /**
44640 * @property {Number} TAB
44641 * @final
44642 */ exports.SHIFT = SHIFT;
44643 var TAB = 9;
44644 /**
44645 * @property {Number} UP_ARROW
44646 * @final
44647 */ exports.TAB = TAB;
44648 var UP_ARROW = 38;
44649
44650 // RENDERING
44651 /**
44652 * @property {String} BLEND
44653 * @final
44654 * @default source-over
44655 */ exports.UP_ARROW = UP_ARROW;
44656 var BLEND = 'source-over';
44657 /**
44658 * @property {String} REMOVE
44659 * @final
44660 * @default destination-out
44661 */ exports.BLEND = BLEND;
44662 var REMOVE = 'destination-out';
44663 /**
44664 * @property {String} ADD
44665 * @final
44666 * @default lighter
44667 */ exports.REMOVE = REMOVE;
44668 var ADD = 'lighter';
44669 //ADD: 'add', //
44670 //SUBTRACT: 'subtract', //
44671 /**
44672 * @property {String} DARKEST
44673 * @final
44674 */ exports.ADD = ADD;
44675 var DARKEST = 'darken';
44676 /**
44677 * @property {String} LIGHTEST
44678 * @final
44679 * @default lighten
44680 */ exports.DARKEST = DARKEST;
44681 var LIGHTEST = 'lighten';
44682 /**
44683 * @property {String} DIFFERENCE
44684 * @final
44685 */ exports.LIGHTEST = LIGHTEST;
44686 var DIFFERENCE = 'difference';
44687 /**
44688 * @property {String} SUBTRACT
44689 * @final
44690 */ exports.DIFFERENCE = DIFFERENCE;
44691 var SUBTRACT = 'subtract';
44692 /**
44693 * @property {String} EXCLUSION
44694 * @final
44695 */ exports.SUBTRACT = SUBTRACT;
44696 var EXCLUSION = 'exclusion';
44697 /**
44698 * @property {String} MULTIPLY
44699 * @final
44700 */ exports.EXCLUSION = EXCLUSION;
44701 var MULTIPLY = 'multiply';
44702 /**
44703 * @property {String} SCREEN
44704 * @final
44705 */ exports.MULTIPLY = MULTIPLY;
44706 var SCREEN = 'screen';
44707 /**
44708 * @property {String} REPLACE
44709 * @final
44710 * @default copy
44711 */ exports.SCREEN = SCREEN;
44712 var REPLACE = 'copy';
44713 /**
44714 * @property {String} OVERLAY
44715 * @final
44716 */ exports.REPLACE = REPLACE;
44717 var OVERLAY = 'overlay';
44718 /**
44719 * @property {String} HARD_LIGHT
44720 * @final
44721 */ exports.OVERLAY = OVERLAY;
44722 var HARD_LIGHT = 'hard-light';
44723 /**
44724 * @property {String} SOFT_LIGHT
44725 * @final
44726 */ exports.HARD_LIGHT = HARD_LIGHT;
44727 var SOFT_LIGHT = 'soft-light';
44728 /**
44729 * @property {String} DODGE
44730 * @final
44731 * @default color-dodge
44732 */ exports.SOFT_LIGHT = SOFT_LIGHT;
44733 var DODGE = 'color-dodge';
44734 /**
44735 * @property {String} BURN
44736 * @final
44737 * @default color-burn
44738 */ exports.DODGE = DODGE;
44739 var BURN = 'color-burn';
44740
44741 // FILTERS
44742 /**
44743 * @property {String} THRESHOLD
44744 * @final
44745 */ exports.BURN = BURN;
44746 var THRESHOLD = 'threshold';
44747 /**
44748 * @property {String} GRAY
44749 * @final
44750 */ exports.THRESHOLD = THRESHOLD;
44751 var GRAY = 'gray';
44752 /**
44753 * @property {String} OPAQUE
44754 * @final
44755 */ exports.GRAY = GRAY;
44756 var OPAQUE = 'opaque';
44757 /**
44758 * @property {String} INVERT
44759 * @final
44760 */ exports.OPAQUE = OPAQUE;
44761 var INVERT = 'invert';
44762 /**
44763 * @property {String} POSTERIZE
44764 * @final
44765 */ exports.INVERT = INVERT;
44766 var POSTERIZE = 'posterize';
44767 /**
44768 * @property {String} DILATE
44769 * @final
44770 */ exports.POSTERIZE = POSTERIZE;
44771 var DILATE = 'dilate';
44772 /**
44773 * @property {String} ERODE
44774 * @final
44775 */ exports.DILATE = DILATE;
44776 var ERODE = 'erode';
44777 /**
44778 * @property {String} BLUR
44779 * @final
44780 */ exports.ERODE = ERODE;
44781 var BLUR = 'blur';
44782
44783 // TYPOGRAPHY
44784 /**
44785 * @property {String} NORMAL
44786 * @final
44787 */ exports.BLUR = BLUR;
44788 var NORMAL = 'normal';
44789 /**
44790 * @property {String} ITALIC
44791 * @final
44792 */ exports.NORMAL = NORMAL;
44793 var ITALIC = 'italic';
44794 /**
44795 * @property {String} BOLD
44796 * @final
44797 */ exports.ITALIC = ITALIC;
44798 var BOLD = 'bold';
44799 /**
44800 * @property {String} BOLDITALIC
44801 * @final
44802 */ exports.BOLD = BOLD;
44803 var BOLDITALIC = 'bold italic';
44804
44805 // TYPOGRAPHY-INTERNAL
44806 exports.BOLDITALIC = BOLDITALIC;
44807 var _DEFAULT_TEXT_FILL = '#000000';
44808 exports._DEFAULT_TEXT_FILL = _DEFAULT_TEXT_FILL;
44809 var _DEFAULT_LEADMULT = 1.25;
44810 exports._DEFAULT_LEADMULT = _DEFAULT_LEADMULT;
44811 var _CTX_MIDDLE = 'middle';
44812
44813 // VERTICES
44814 /**
44815 * @property {String} LINEAR
44816 * @final
44817 */ exports._CTX_MIDDLE = _CTX_MIDDLE;
44818 var LINEAR = 'linear';
44819 /**
44820 * @property {String} QUADRATIC
44821 * @final
44822 */ exports.LINEAR = LINEAR;
44823 var QUADRATIC = 'quadratic';
44824 /**
44825 * @property {String} BEZIER
44826 * @final
44827 */ exports.QUADRATIC = QUADRATIC;
44828 var BEZIER = 'bezier';
44829 /**
44830 * @property {String} CURVE
44831 * @final
44832 */ exports.BEZIER = BEZIER;
44833 var CURVE = 'curve';
44834
44835 // WEBGL DRAWMODES
44836 /**
44837 * @property {String} STROKE
44838 * @final
44839 */ exports.CURVE = CURVE;
44840 var STROKE = 'stroke';
44841 /**
44842 * @property {String} FILL
44843 * @final
44844 */ exports.STROKE = STROKE;
44845 var FILL = 'fill';
44846 /**
44847 * @property {String} TEXTURE
44848 * @final
44849 */ exports.FILL = FILL;
44850 var TEXTURE = 'texture';
44851 /**
44852 * @property {String} IMMEDIATE
44853 * @final
44854 */ exports.TEXTURE = TEXTURE;
44855 var IMMEDIATE = 'immediate';
44856
44857 // WEBGL TEXTURE MODE
44858 // NORMAL already exists for typography
44859 /**
44860 * @property {String} IMAGE
44861 * @final
44862 */ exports.IMMEDIATE = IMMEDIATE;
44863 var IMAGE = 'image';
44864
44865 // WEBGL TEXTURE WRAP AND FILTERING
44866 // LINEAR already exists above
44867 /**
44868 * @property {String} NEAREST
44869 * @final
44870 */ exports.IMAGE = IMAGE;
44871 var NEAREST = 'nearest';
44872 /**
44873 * @property {String} REPEAT
44874 * @final
44875 */ exports.NEAREST = NEAREST;
44876 var REPEAT = 'repeat';
44877 /**
44878 * @property {String} CLAMP
44879 * @final
44880 */ exports.REPEAT = REPEAT;
44881 var CLAMP = 'clamp';
44882 /**
44883 * @property {String} MIRROR
44884 * @final
44885 */ exports.CLAMP = CLAMP;
44886 var MIRROR = 'mirror';
44887
44888 // DEVICE-ORIENTATION
44889 /**
44890 * @property {String} LANDSCAPE
44891 * @final
44892 */ exports.MIRROR = MIRROR;
44893 var LANDSCAPE = 'landscape';
44894 /**
44895 * @property {String} PORTRAIT
44896 * @final
44897 */ exports.LANDSCAPE = LANDSCAPE;
44898 var PORTRAIT = 'portrait';
44899
44900 // DEFAULTS
44901 exports.PORTRAIT = PORTRAIT;
44902 var _DEFAULT_STROKE = '#000000';
44903 exports._DEFAULT_STROKE = _DEFAULT_STROKE;
44904 var _DEFAULT_FILL = '#FFFFFF';
44905
44906 /**
44907 * @property {String} GRID
44908 * @final
44909 */ exports._DEFAULT_FILL = _DEFAULT_FILL;
44910 var GRID = 'grid';
44911
44912 /**
44913 * @property {String} AXES
44914 * @final
44915 */ exports.GRID = GRID;
44916 var AXES = 'axes';
44917 exports.AXES = AXES;
44918 },
44919 {}
44920 ],
44921 44: [
44922 function(_dereq_, module, exports) {
44923 'use strict';
44924 function _typeof(obj) {
44925 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
44926 _typeof = function _typeof(obj) {
44927 return typeof obj;
44928 };
44929 } else {
44930 _typeof = function _typeof(obj) {
44931 return obj &&
44932 typeof Symbol === 'function' &&
44933 obj.constructor === Symbol &&
44934 obj !== Symbol.prototype
44935 ? 'symbol'
44936 : typeof obj;
44937 };
44938 }
44939 return _typeof(obj);
44940 }
44941 Object.defineProperty(exports, '__esModule', { value: true });
44942 exports.default = void 0;
44943
44944 var _main = _interopRequireDefault(_dereq_('./main'));
44945 var C = _interopRequireWildcard(_dereq_('./constants'));
44946 function _getRequireWildcardCache() {
44947 if (typeof WeakMap !== 'function') return null;
44948 var cache = new WeakMap();
44949 _getRequireWildcardCache = function _getRequireWildcardCache() {
44950 return cache;
44951 };
44952 return cache;
44953 }
44954 function _interopRequireWildcard(obj) {
44955 if (obj && obj.__esModule) {
44956 return obj;
44957 }
44958 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) {
44959 return { default: obj };
44960 }
44961 var cache = _getRequireWildcardCache();
44962 if (cache && cache.has(obj)) {
44963 return cache.get(obj);
44964 }
44965 var newObj = {};
44966 var hasPropertyDescriptor =
44967 Object.defineProperty && Object.getOwnPropertyDescriptor;
44968 for (var key in obj) {
44969 if (Object.prototype.hasOwnProperty.call(obj, key)) {
44970 var desc = hasPropertyDescriptor
44971 ? Object.getOwnPropertyDescriptor(obj, key)
44972 : null;
44973 if (desc && (desc.get || desc.set)) {
44974 Object.defineProperty(newObj, key, desc);
44975 } else {
44976 newObj[key] = obj[key];
44977 }
44978 }
44979 }
44980 newObj.default = obj;
44981 if (cache) {
44982 cache.set(obj, newObj);
44983 }
44984 return newObj;
44985 }
44986 function _interopRequireDefault(obj) {
44987 return obj && obj.__esModule ? obj : { default: obj };
44988 }
44989 /**
44990 * @module Environment
44991 * @submodule Environment
44992 * @for p5
44993 * @requires core
44994 * @requires constants
44995 */ var standardCursors = [C.ARROW, C.CROSS, C.HAND, C.MOVE, C.TEXT, C.WAIT];
44996 _main.default.prototype._frameRate = 0;
44997 _main.default.prototype._lastFrameTime = window.performance.now();
44998 _main.default.prototype._targetFrameRate = 60;
44999
45000 var _windowPrint = window.print;
45001
45002 /**
45003 * The <a href="#/p5/print">print()</a> function writes to the console area of
45004 * your browser. This function is often helpful for looking at the data a program
45005 * is producing. This function creates a new line of text for each call to
45006 * the function. Individual elements can be separated with quotes ("") and joined
45007 * with the addition operator (+).
45008 *
45009 * Note that calling print() without any arguments invokes the window.print()
45010 * function which opens the browser's print dialog. To print a blank line
45011 * to console you can write print('\n').
45012 *
45013 * @method print
45014 * @param {Any} contents any combination of Number, String, Object, Boolean,
45015 * Array to print
45016 * @example
45017 * <div><code class='norender'>
45018 * let x = 10;
45019 * print('The value of x is ' + x);
45020 * // prints "The value of x is 10"
45021 * </code></div>
45022 *
45023 * @alt
45024 * default grey canvas
45025 */
45026 _main.default.prototype.print = function() {
45027 if (!arguments.length) {
45028 _windowPrint();
45029 } else {
45030 var _console;
45031 (_console = console).log.apply(_console, arguments);
45032 }
45033 };
45034
45035 /**
45036 * The system variable <a href="#/p5/frameCount">frameCount</a> contains the
45037 * number of frames that have been displayed since the program started. Inside
45038 * <a href="#/p5/setup">setup()</a> the value is 0, after the first iteration
45039 * of draw it is 1, etc.
45040 *
45041 * @property {Integer} frameCount
45042 * @readOnly
45043 * @example
45044 * <div><code>
45045 * function setup() {
45046 * frameRate(30);
45047 * textSize(30);
45048 * textAlign(CENTER);
45049 * }
45050 *
45051 * function draw() {
45052 * background(200);
45053 * text(frameCount, width / 2, height / 2);
45054 * }
45055 * </code></div>
45056 *
45057 * @alt
45058 * numbers rapidly counting upward with frame count set to 30.
45059 */
45060 _main.default.prototype.frameCount = 0;
45061
45062 /**
45063 * The system variable <a href="#/p5/deltaTime">deltaTime</a> contains the time
45064 * difference between the beginning of the previous frame and the beginning
45065 * of the current frame in milliseconds.
45066 *
45067 * This variable is useful for creating time sensitive animation or physics
45068 * calculation that should stay constant regardless of frame rate.
45069 *
45070 * @property {Integer} deltaTime
45071 * @readOnly
45072 * @example
45073 * <div><code>
45074 * let rectX = 0;
45075 * let fr = 30; //starting FPS
45076 * let clr;
45077 *
45078 * function setup() {
45079 * background(200);
45080 * frameRate(fr); // Attempt to refresh at starting FPS
45081 * clr = color(255, 0, 0);
45082 * }
45083 *
45084 * function draw() {
45085 * background(200);
45086 * rectX = rectX + 1 * (deltaTime / 50); // Move Rectangle in relation to deltaTime
45087 *
45088 * if (rectX >= width) {
45089 * // If you go off screen.
45090 * if (fr === 30) {
45091 * clr = color(0, 0, 255);
45092 * fr = 10;
45093 * frameRate(fr); // make frameRate 10 FPS
45094 * } else {
45095 * clr = color(255, 0, 0);
45096 * fr = 30;
45097 * frameRate(fr); // make frameRate 30 FPS
45098 * }
45099 * rectX = 0;
45100 * }
45101 * fill(clr);
45102 * rect(rectX, 40, 20, 20);
45103 * }
45104 * </code></div>
45105 *
45106 * @alt
45107 * red rect moves left to right, followed by blue rect moving at the same speed
45108 * with a lower frame rate. Loops.
45109 */
45110 _main.default.prototype.deltaTime = 0;
45111
45112 /**
45113 * Confirms if the window a p5.js program is in is "focused," meaning that
45114 * the sketch will accept mouse or keyboard input. This variable is
45115 * "true" if the window is focused and "false" if not.
45116 *
45117 * @property {Boolean} focused
45118 * @readOnly
45119 * @example
45120 * <div><code>
45121 * // To demonstrate, put two windows side by side.
45122 * // Click on the window that the p5 sketch isn't in!
45123 * function draw() {
45124 * background(200);
45125 * noStroke();
45126 * fill(0, 200, 0);
45127 * ellipse(25, 25, 50, 50);
45128 *
45129 * if (!focused) {
45130 // or "if (focused === false)"
45131 * stroke(200, 0, 0);
45132 * line(0, 0, 100, 100);
45133 * line(100, 0, 0, 100);
45134 * }
45135 * }
45136 * </code></div>
45137 *
45138 * @alt
45139 * green 50x50 ellipse at top left. Red X covers canvas when page focus changes
45140 */
45141 _main.default.prototype.focused = document.hasFocus();
45142
45143 /**
45144 * Sets the cursor to a predefined symbol or an image, or makes it visible
45145 * if already hidden. If you are trying to set an image as the cursor, the
45146 * recommended size is 16x16 or 32x32 pixels. The values for parameters x and y
45147 * must be less than the dimensions of the image.
45148 *
45149 * @method cursor
45150 * @param {String|Constant} type Built-In: either ARROW, CROSS, HAND, MOVE, TEXT and WAIT
45151 * Native CSS properties: 'grab', 'progress', 'cell' etc.
45152 * External: path for cursor's images
45153 * (Allowed File extensions: .cur, .gif, .jpg, .jpeg, .png)
45154 * For more information on Native CSS cursors and url visit:
45155 * https://developer.mozilla.org/en-US/docs/Web/CSS/cursor
45156 * @param {Number} [x] the horizontal active spot of the cursor (must be less than 32)
45157 * @param {Number} [y] the vertical active spot of the cursor (must be less than 32)
45158 * @example
45159 * <div><code>
45160 * // Move the mouse across the quadrants
45161 * // to see the cursor change
45162 * function draw() {
45163 * line(width / 2, 0, width / 2, height);
45164 * line(0, height / 2, width, height / 2);
45165 * if (mouseX < 50 && mouseY < 50) {
45166 * cursor(CROSS);
45167 * } else if (mouseX > 50 && mouseY < 50) {
45168 * cursor('progress');
45169 * } else if (mouseX > 50 && mouseY > 50) {
45170 * cursor('https://avatars0.githubusercontent.com/u/1617169?s=16');
45171 * } else {
45172 * cursor('grab');
45173 * }
45174 * }
45175 * </code></div>
45176 *
45177 * @alt
45178 * canvas is divided into four quadrants. cursor on first is a cross, second is a progress,
45179 * third is a custom cursor using path to the cursor and fourth is a grab.
45180 */
45181 _main.default.prototype.cursor = function(type, x, y) {
45182 var cursor = 'auto';
45183 var canvas = this._curElement.elt;
45184 if (standardCursors.includes(type)) {
45185 // Standard css cursor
45186 cursor = type;
45187 } else if (typeof type === 'string') {
45188 var coords = '';
45189 if (x && y && typeof x === 'number' && typeof y === 'number') {
45190 // Note that x and y values must be unit-less positive integers < 32
45191 // https://developer.mozilla.org/en-US/docs/Web/CSS/cursor
45192 coords = ''.concat(x, ' ').concat(y);
45193 }
45194 if (
45195 type.substring(0, 7) === 'http://' ||
45196 type.substring(0, 8) === 'https://'
45197 ) {
45198 // Image (absolute url)
45199 cursor = 'url('.concat(type, ') ').concat(coords, ', auto');
45200 } else if (/\.(cur|jpg|jpeg|gif|png|CUR|JPG|JPEG|GIF|PNG)$/.test(type)) {
45201 // Image file (relative path) - Separated for performance reasons
45202 cursor = 'url('.concat(type, ') ').concat(coords, ', auto');
45203 } else {
45204 // Any valid string for the css cursor property
45205 cursor = type;
45206 }
45207 }
45208 canvas.style.cursor = cursor;
45209 };
45210
45211 /**
45212 * Specifies the number of frames to be displayed every second. For example,
45213 * the function call frameRate(30) will attempt to refresh 30 times a second.
45214 * If the processor is not fast enough to maintain the specified rate, the
45215 * frame rate will not be achieved. Setting the frame rate within
45216 * <a href="#/p5/setup">setup()</a> is recommended. The default frame rate is
45217 * based on the frame rate of the display (here also called "refresh rate"),
45218 * which is set to 60 frames per second on most computers. A frame rate of 24
45219 * frames per second (usual for movies) or above will be enough for smooth
45220 * animations. This is the same as setFrameRate(val).
45221 *
45222 * Calling <a href="#/p5/frameRate">frameRate()</a> with no arguments returns
45223 * the current framerate. The draw function must run at least once before it will
45224 * return a value. This is the same as <a href="#/p5/getFrameRate">getFrameRate()</a>.
45225 *
45226 * Calling <a href="#/p5/frameRate">frameRate()</a> with arguments that are not
45227 * of the type numbers or are non positive also returns current framerate.
45228 *
45229 * @method frameRate
45230 * @param {Number} fps number of frames to be displayed every second
45231 * @chainable
45232 *
45233 * @example
45234 *
45235 * <div><code>
45236 * let rectX = 0;
45237 * let fr = 30; //starting FPS
45238 * let clr;
45239 *
45240 * function setup() {
45241 * background(200);
45242 * frameRate(fr); // Attempt to refresh at starting FPS
45243 * clr = color(255, 0, 0);
45244 * }
45245 *
45246 * function draw() {
45247 * background(200);
45248 * rectX = rectX += 1; // Move Rectangle
45249 *
45250 * if (rectX >= width) {
45251 // If you go off screen.
45252 * if (fr === 30) {
45253 * clr = color(0, 0, 255);
45254 * fr = 10;
45255 * frameRate(fr); // make frameRate 10 FPS
45256 * } else {
45257 * clr = color(255, 0, 0);
45258 * fr = 30;
45259 * frameRate(fr); // make frameRate 30 FPS
45260 * }
45261 * rectX = 0;
45262 * }
45263 * fill(clr);
45264 * rect(rectX, 40, 20, 20);
45265 * }
45266 * </code></div>
45267 *
45268 * @alt
45269 * blue rect moves left to right, followed by red rect moving faster. Loops.
45270 */
45271 /**
45272 * @method frameRate
45273 * @return {Number} current frameRate
45274 */
45275 _main.default.prototype.frameRate = function(fps) {
45276 _main.default._validateParameters('frameRate', arguments);
45277 if (typeof fps !== 'number' || fps < 0) {
45278 return this._frameRate;
45279 } else {
45280 this._setProperty('_targetFrameRate', fps);
45281 if (fps === 0) {
45282 this._setProperty('_frameRate', fps);
45283 }
45284 return this;
45285 }
45286 };
45287
45288 /**
45289 * Returns the current framerate.
45290 *
45291 * @private
45292 * @return {Number} current frameRate
45293 */
45294 _main.default.prototype.getFrameRate = function() {
45295 return this.frameRate();
45296 };
45297
45298 /**
45299 * Specifies the number of frames to be displayed every second. For example,
45300 * the function call frameRate(30) will attempt to refresh 30 times a second.
45301 * If the processor is not fast enough to maintain the specified rate, the
45302 * frame rate will not be achieved. Setting the frame rate within <a href="#/p5/setup">setup()</a> is
45303 * recommended. The default rate is 60 frames per second.
45304 *
45305 * Calling <a href="#/p5/frameRate">frameRate()</a> with no arguments returns the current framerate.
45306 *
45307 * @private
45308 * @param {Number} [fps] number of frames to be displayed every second
45309 */
45310 _main.default.prototype.setFrameRate = function(fps) {
45311 return this.frameRate(fps);
45312 };
45313
45314 /**
45315 * Hides the cursor from view.
45316 *
45317 * @method noCursor
45318 * @example
45319 * <div><code>
45320 * function setup() {
45321 * noCursor();
45322 * }
45323 *
45324 * function draw() {
45325 * background(200);
45326 * ellipse(mouseX, mouseY, 10, 10);
45327 * }
45328 * </code></div>
45329 *
45330 * @alt
45331 * cursor becomes 10x 10 white ellipse the moves with mouse x and y.
45332 */
45333 _main.default.prototype.noCursor = function() {
45334 this._curElement.elt.style.cursor = 'none';
45335 };
45336
45337 /**
45338 * System variable that stores the width of the screen display according to The
45339 * default <a href="#/p5/pixelDensity">pixelDensity</a>. This is used to run a
45340 * full-screen program on any display size. To return actual screen size,
45341 * multiply this by pixelDensity.
45342 *
45343 * @property {Number} displayWidth
45344 * @readOnly
45345 * @example
45346 * <div class="norender"><code>
45347 * createCanvas(displayWidth, displayHeight);
45348 * </code></div>
45349 *
45350 * @alt
45351 * This example does not render anything.
45352 */
45353 _main.default.prototype.displayWidth = screen.width;
45354
45355 /**
45356 * System variable that stores the height of the screen display according to The
45357 * default <a href="#/p5/pixelDensity">pixelDensity</a>. This is used to run a
45358 * full-screen program on any display size. To return actual screen size,
45359 * multiply this by pixelDensity.
45360 *
45361 * @property {Number} displayHeight
45362 * @readOnly
45363 * @example
45364 * <div class="norender"><code>
45365 * createCanvas(displayWidth, displayHeight);
45366 * </code></div>
45367 *
45368 * @alt
45369 * This example does not render anything.
45370 */
45371 _main.default.prototype.displayHeight = screen.height;
45372
45373 /**
45374 * System variable that stores the width of the inner window, it maps to
45375 * window.innerWidth.
45376 *
45377 * @property {Number} windowWidth
45378 * @readOnly
45379 * @example
45380 * <div class="norender"><code>
45381 * createCanvas(windowWidth, windowHeight);
45382 * </code></div>
45383 *
45384 * @alt
45385 * This example does not render anything.
45386 */
45387 _main.default.prototype.windowWidth = getWindowWidth();
45388 /**
45389 * System variable that stores the height of the inner window, it maps to
45390 * window.innerHeight.
45391 *
45392 * @property {Number} windowHeight
45393 * @readOnly
45394 * @example
45395 * <div class="norender"><code>
45396 * createCanvas(windowWidth, windowHeight);
45397 * </code></div>
45398 *
45399 * @alt
45400 * This example does not render anything.
45401 */
45402 _main.default.prototype.windowHeight = getWindowHeight();
45403
45404 /**
45405 * The <a href="#/p5/windowResized">windowResized()</a> function is called once
45406 * every time the browser window is resized. This is a good place to resize the
45407 * canvas or do any other adjustments to accommodate the new window size.
45408 *
45409 * @method windowResized
45410 * @example
45411 * <div class="norender"><code>
45412 * function setup() {
45413 * createCanvas(windowWidth, windowHeight);
45414 * }
45415 *
45416 * function draw() {
45417 * background(0, 100, 200);
45418 * }
45419 *
45420 * function windowResized() {
45421 * resizeCanvas(windowWidth, windowHeight);
45422 * }
45423 * </code></div>
45424 * @alt
45425 * This example does not render anything.
45426 */
45427 _main.default.prototype._onresize = function(e) {
45428 this._setProperty('windowWidth', getWindowWidth());
45429 this._setProperty('windowHeight', getWindowHeight());
45430 var context = this._isGlobal ? window : this;
45431 var executeDefault;
45432 if (typeof context.windowResized === 'function') {
45433 executeDefault = context.windowResized(e);
45434 if (executeDefault !== undefined && !executeDefault) {
45435 e.preventDefault();
45436 }
45437 }
45438 };
45439
45440 function getWindowWidth() {
45441 return (
45442 window.innerWidth ||
45443 (document.documentElement && document.documentElement.clientWidth) ||
45444 (document.body && document.body.clientWidth) ||
45445 0
45446 );
45447 }
45448
45449 function getWindowHeight() {
45450 return (
45451 window.innerHeight ||
45452 (document.documentElement && document.documentElement.clientHeight) ||
45453 (document.body && document.body.clientHeight) ||
45454 0
45455 );
45456 }
45457
45458 /**
45459 * System variable that stores the width of the drawing canvas. This value
45460 * is set by the first parameter of the <a href="#/p5/createCanvas">createCanvas()</a> function.
45461 * For example, the function call createCanvas(320, 240) sets the width
45462 * variable to the value 320. The value of width defaults to 100 if
45463 * <a href="#/p5/createCanvas">createCanvas()</a> is not used in a program.
45464 *
45465 * @property {Number} width
45466 * @readOnly
45467 */
45468 _main.default.prototype.width = 0;
45469
45470 /**
45471 * System variable that stores the height of the drawing canvas. This value
45472 * is set by the second parameter of the <a href="#/p5/createCanvas">createCanvas()</a> function. For
45473 * example, the function call createCanvas(320, 240) sets the height
45474 * variable to the value 240. The value of height defaults to 100 if
45475 * <a href="#/p5/createCanvas">createCanvas()</a> is not used in a program.
45476 *
45477 * @property {Number} height
45478 * @readOnly
45479 */
45480 _main.default.prototype.height = 0;
45481
45482 /**
45483 * If argument is given, sets the sketch to fullscreen or not based on the
45484 * value of the argument. If no argument is given, returns the current
45485 * fullscreen state. Note that due to browser restrictions this can only
45486 * be called on user input, for example, on mouse press like the example
45487 * below.
45488 *
45489 * @method fullscreen
45490 * @param {Boolean} [val] whether the sketch should be in fullscreen mode
45491 * or not
45492 * @return {Boolean} current fullscreen state
45493 * @example
45494 * <div>
45495 * <code>
45496 * // Clicking in the box toggles fullscreen on and off.
45497 * function setup() {
45498 * background(200);
45499 * }
45500 * function mousePressed() {
45501 * if (mouseX > 0 && mouseX < 100 && mouseY > 0 && mouseY < 100) {
45502 * let fs = fullscreen();
45503 * fullscreen(!fs);
45504 * }
45505 * }
45506 * </code>
45507 * </div>
45508 *
45509 * @alt
45510 * This example does not render anything.
45511 */
45512 _main.default.prototype.fullscreen = function(val) {
45513 _main.default._validateParameters('fullscreen', arguments);
45514 // no arguments, return fullscreen or not
45515 if (typeof val === 'undefined') {
45516 return (
45517 document.fullscreenElement ||
45518 document.webkitFullscreenElement ||
45519 document.mozFullScreenElement ||
45520 document.msFullscreenElement
45521 );
45522 } else {
45523 // otherwise set to fullscreen or not
45524 if (val) {
45525 launchFullscreen(document.documentElement);
45526 } else {
45527 exitFullscreen();
45528 }
45529 }
45530 };
45531
45532 /**
45533 * Sets the pixel scaling for high pixel density displays. By default
45534 * pixel density is set to match display density, call pixelDensity(1)
45535 * to turn this off. Calling <a href="#/p5/pixelDensity">pixelDensity()</a> with no arguments returns
45536 * the current pixel density of the sketch.
45537 *
45538 * @method pixelDensity
45539 * @param {Number} val whether or how much the sketch should scale
45540 * @chainable
45541 * @example
45542 * <div>
45543 * <code>
45544 * function setup() {
45545 * pixelDensity(1);
45546 * createCanvas(100, 100);
45547 * background(200);
45548 * ellipse(width / 2, height / 2, 50, 50);
45549 * }
45550 * </code>
45551 * </div>
45552 *
45553 * <div>
45554 * <code>
45555 * function setup() {
45556 * pixelDensity(3.0);
45557 * createCanvas(100, 100);
45558 * background(200);
45559 * ellipse(width / 2, height / 2, 50, 50);
45560 * }
45561 * </code>
45562 * </div>
45563 *
45564 * @alt
45565 * fuzzy 50x50 white ellipse with black outline in center of canvas.
45566 * sharp 50x50 white ellipse with black outline in center of canvas.
45567 */
45568 /**
45569 * @method pixelDensity
45570 * @returns {Number} current pixel density of the sketch
45571 */
45572 _main.default.prototype.pixelDensity = function(val) {
45573 _main.default._validateParameters('pixelDensity', arguments);
45574 var returnValue;
45575 if (typeof val === 'number') {
45576 if (val !== this._pixelDensity) {
45577 this._pixelDensity = val;
45578 }
45579 returnValue = this;
45580 this.resizeCanvas(this.width, this.height, true); // as a side effect, it will clear the canvas
45581 } else {
45582 returnValue = this._pixelDensity;
45583 }
45584 return returnValue;
45585 };
45586
45587 /**
45588 * Returns the pixel density of the current display the sketch is running on.
45589 *
45590 * @method displayDensity
45591 * @returns {Number} current pixel density of the display
45592 * @example
45593 * <div>
45594 * <code>
45595 * function setup() {
45596 * let density = displayDensity();
45597 * pixelDensity(density);
45598 * createCanvas(100, 100);
45599 * background(200);
45600 * ellipse(width / 2, height / 2, 50, 50);
45601 * }
45602 * </code>
45603 * </div>
45604 *
45605 * @alt
45606 * 50x50 white ellipse with black outline in center of canvas.
45607 */
45608 _main.default.prototype.displayDensity = function() {
45609 return window.devicePixelRatio;
45610 };
45611
45612 function launchFullscreen(element) {
45613 var enabled =
45614 document.fullscreenEnabled ||
45615 document.webkitFullscreenEnabled ||
45616 document.mozFullScreenEnabled ||
45617 document.msFullscreenEnabled;
45618 if (!enabled) {
45619 throw new Error('Fullscreen not enabled in this browser.');
45620 }
45621 if (element.requestFullscreen) {
45622 element.requestFullscreen();
45623 } else if (element.mozRequestFullScreen) {
45624 element.mozRequestFullScreen();
45625 } else if (element.webkitRequestFullscreen) {
45626 element.webkitRequestFullscreen();
45627 } else if (element.msRequestFullscreen) {
45628 element.msRequestFullscreen();
45629 }
45630 }
45631
45632 function exitFullscreen() {
45633 if (document.exitFullscreen) {
45634 document.exitFullscreen();
45635 } else if (document.mozCancelFullScreen) {
45636 document.mozCancelFullScreen();
45637 } else if (document.webkitExitFullscreen) {
45638 document.webkitExitFullscreen();
45639 } else if (document.msExitFullscreen) {
45640 document.msExitFullscreen();
45641 }
45642 }
45643
45644 /**
45645 * Gets the current URL.
45646 * @method getURL
45647 * @return {String} url
45648 * @example
45649 * <div>
45650 * <code>
45651 * let url;
45652 * let x = 100;
45653 *
45654 * function setup() {
45655 * fill(0);
45656 * noStroke();
45657 * url = getURL();
45658 * }
45659 *
45660 * function draw() {
45661 * background(200);
45662 * text(url, x, height / 2);
45663 * x--;
45664 * }
45665 * </code>
45666 * </div>
45667 *
45668 * @alt
45669 * current url (http://p5js.org/reference/#/p5/getURL) moves right to left.
45670 */
45671 _main.default.prototype.getURL = function() {
45672 return location.href;
45673 };
45674 /**
45675 * Gets the current URL path as an array.
45676 * @method getURLPath
45677 * @return {String[]} path components
45678 * @example
45679 * <div class='norender'><code>
45680 * function setup() {
45681 * let urlPath = getURLPath();
45682 * for (let i = 0; i < urlPath.length; i++) {
45683 * text(urlPath[i], 10, i * 20 + 20);
45684 * }
45685 * }
45686 * </code></div>
45687 *
45688 * @alt
45689 * This example does not render anything.
45690 */
45691 _main.default.prototype.getURLPath = function() {
45692 return location.pathname.split('/').filter(function(v) {
45693 return v !== '';
45694 });
45695 };
45696 /**
45697 * Gets the current URL params as an Object.
45698 * @method getURLParams
45699 * @return {Object} URL params
45700 * @example
45701 * <div class='norender notest'>
45702 * <code>
45703 * // Example: http://p5js.org?year=2014&month=May&day=15
45704 *
45705 * function setup() {
45706 * let params = getURLParams();
45707 * text(params.day, 10, 20);
45708 * text(params.month, 10, 40);
45709 * text(params.year, 10, 60);
45710 * }
45711 * </code>
45712 * </div>
45713 *
45714 * @alt
45715 * This example does not render anything.
45716 */
45717 _main.default.prototype.getURLParams = function() {
45718 var re = /[?&]([^&=]+)(?:[&=])([^&=]+)/gim;
45719 var m;
45720 var v = {};
45721 while ((m = re.exec(location.search)) != null) {
45722 if (m.index === re.lastIndex) {
45723 re.lastIndex++;
45724 }
45725 v[m[1]] = m[2];
45726 }
45727 return v;
45728 };
45729 var _default = _main.default;
45730 exports.default = _default;
45731 },
45732 { './constants': 43, './main': 54 }
45733 ],
45734 45: [
45735 function(_dereq_, module, exports) {
45736 'use strict';
45737 Object.defineProperty(exports, '__esModule', { value: true });
45738 exports.default = void 0; // Different browsers may use different error strings for the same error.
45739 // Extracting info from them is much easier and cleaner if we have a predefined
45740 // lookup against which we try and match the errors obtained from the browser,
45741 // classify them into types and extract the required information. The contents
45742 // of this file serve as that lookup. The FES can use this to give a simplified
45743 // explanation for all kinds of errors.
45744 var strings = {
45745 ReferenceError: [
45746 {
45747 msg: '{{}} is not defined',
45748 type: 'NOTDEFINED',
45749 browser: 'all'
45750 },
45751
45752 {
45753 msg: "Can't find variable: {{}}",
45754 type: 'NOTDEFINED',
45755 browser: 'Safari'
45756 }
45757 ],
45758
45759 SyntaxError: [
45760 {
45761 msg: 'illegal character',
45762 type: 'INVALIDTOKEN',
45763 browser: 'Firefox'
45764 },
45765
45766 {
45767 msg: 'Invalid character',
45768 type: 'INVALIDTOKEN',
45769 browser: 'Safari'
45770 },
45771
45772 {
45773 msg: 'Invalid or unexpected token',
45774 type: 'INVALIDTOKEN',
45775 browser: 'Chrome'
45776 },
45777
45778 {
45779 msg: "Unexpected token '{{.}}'",
45780 type: 'UNEXPECTEDTOKEN',
45781 browser: 'Chrome'
45782 },
45783
45784 {
45785 msg: "expected {{.}}, got '{{.}}'",
45786 type: 'UNEXPECTEDTOKEN',
45787 browser: 'Chrome'
45788 }
45789 ],
45790
45791 TypeError: [
45792 {
45793 msg: '{{.}} is not a function',
45794 type: 'NOTFUNC',
45795 browser: 'all'
45796 }
45797 ]
45798 };
45799 var _default = strings;
45800 exports.default = _default;
45801 },
45802 {}
45803 ],
45804 46: [
45805 function(_dereq_, module, exports) {
45806 'use strict';
45807 Object.defineProperty(exports, '__esModule', { value: true });
45808 exports.default = void 0;
45809
45810 var _main = _interopRequireDefault(_dereq_('../main'));
45811 var _internationalization = _dereq_('../internationalization');
45812 function _interopRequireDefault(obj) {
45813 return obj && obj.__esModule ? obj : { default: obj };
45814 }
45815 function _slicedToArray(arr, i) {
45816 return (
45817 _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest()
45818 );
45819 }
45820 function _nonIterableRest() {
45821 throw new TypeError('Invalid attempt to destructure non-iterable instance');
45822 }
45823 function _iterableToArrayLimit(arr, i) {
45824 if (
45825 !(
45826 Symbol.iterator in Object(arr) ||
45827 Object.prototype.toString.call(arr) === '[object Arguments]'
45828 )
45829 ) {
45830 return;
45831 }
45832 var _arr = [];
45833 var _n = true;
45834 var _d = false;
45835 var _e = undefined;
45836 try {
45837 for (
45838 var _i = arr[Symbol.iterator](), _s;
45839 !(_n = (_s = _i.next()).done);
45840 _n = true
45841 ) {
45842 _arr.push(_s.value);
45843 if (i && _arr.length === i) break;
45844 }
45845 } catch (err) {
45846 _d = true;
45847 _e = err;
45848 } finally {
45849 try {
45850 if (!_n && _i['return'] != null) _i['return']();
45851 } finally {
45852 if (_d) throw _e;
45853 }
45854 }
45855 return _arr;
45856 }
45857 function _arrayWithHoles(arr) {
45858 if (Array.isArray(arr)) return arr;
45859 }
45860 function _typeof(obj) {
45861 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
45862 _typeof = function _typeof(obj) {
45863 return typeof obj;
45864 };
45865 } else {
45866 _typeof = function _typeof(obj) {
45867 return obj &&
45868 typeof Symbol === 'function' &&
45869 obj.constructor === Symbol &&
45870 obj !== Symbol.prototype
45871 ? 'symbol'
45872 : typeof obj;
45873 };
45874 }
45875 return _typeof(obj);
45876 }
45877
45878 // p5.js blue, p5.js orange, auto dark green; fallback p5.js darkened magenta
45879 // See testColors below for all the color codes and names
45880 var typeColors = ['#2D7BB6', '#EE9900', '#4DB200', '#C83C00'];
45881 var misusedAtTopLevelCode = null;
45882 var defineMisusedAtTopLevelCode = null;
45883
45884 // the threshold for the maximum allowed levenshtein distance
45885 // used in misspelling detection
45886 var EDIT_DIST_THRESHOLD = 2;
45887
45888 // to enable or disable styling (color, font-size, etc. ) for fes messages
45889 var ENABLE_FES_STYLING = false;
45890
45891 if (typeof IS_MINIFIED !== 'undefined') {
45892 _main.default._friendlyError = _main.default._checkForUserDefinedFunctions = _main.default._fesErrorMonitor = function() {};
45893 } else {
45894 var doFriendlyWelcome = false; // TEMP until we get it all working LM
45895
45896 var errorTable = _dereq_('./browser_errors').default;
45897
45898 // -- Borrowed from jQuery 1.11.3 --
45899 var class2type = {};
45900 var _toString = class2type.toString;
45901 var names = [
45902 'Boolean',
45903 'Number',
45904 'String',
45905 'Function',
45906 'Array',
45907 'Date',
45908 'RegExp',
45909 'Object',
45910 'Error'
45911 ];
45912
45913 for (var n = 0; n < names.length; n++) {
45914 class2type['[object '.concat(names[n], ']')] = names[n].toLowerCase();
45915 }
45916 var getType = function getType(obj) {
45917 if (obj == null) {
45918 return ''.concat(obj);
45919 }
45920 return _typeof(obj) === 'object' || typeof obj === 'function'
45921 ? class2type[_toString.call(obj)] || 'object'
45922 : _typeof(obj);
45923 };
45924
45925 // -- End borrow --
45926
45927 // entry points into user-defined code
45928 var entryPoints = [
45929 'setup',
45930 'draw',
45931 'preload',
45932 'deviceMoved',
45933 'deviceTurned',
45934 'deviceShaken',
45935 'doubleClicked',
45936 'mousePressed',
45937 'mouseReleased',
45938 'mouseMoved',
45939 'mouseDragged',
45940 'mouseClicked',
45941 'mouseWheel',
45942 'touchStarted',
45943 'touchMoved',
45944 'touchEnded',
45945 'keyPressed',
45946 'keyReleased',
45947 'keyTyped',
45948 'windowResized'
45949 ];
45950
45951 var friendlyWelcome = function friendlyWelcome() {
45952 // p5.js brand - magenta: #ED225D
45953 //const astrixBgColor = 'transparent';
45954 //const astrixTxtColor = '#ED225D';
45955 //const welcomeBgColor = '#ED225D';
45956 //const welcomeTextColor = 'white';
45957 var welcomeMessage = (0, _internationalization.translator)('fes.pre', {
45958 message: (0, _internationalization.translator)('fes.welcome')
45959 });
45960
45961 console.log(
45962 ' _ \n' +
45963 ' /\\| |/\\ \n' +
45964 " \\ ` ' / \n" +
45965 ' / , . \\ \n' +
45966 ' \\/|_|\\/ ' +
45967 '\n\n' +
45968 welcomeMessage
45969 );
45970 };
45971
45972 /**
45973 * Prints out a fancy, colorful message to the console log
45974 *
45975 * @method report
45976 * @private
45977 * @param {String} message the words to be said
45978 * @param {String} func the name of the function to link
45979 * @param {Number|String} color CSS color string or error type
45980 *
45981 * @return console logs
45982 */
45983 var report = function report(message, func, color) {
45984 // if p5._fesLogger is set ( i.e we are running tests ), use that
45985 // instead of console.log
45986 var log =
45987 _main.default._fesLogger == null
45988 ? console.log.bind(console)
45989 : _main.default._fesLogger;
45990
45991 if (doFriendlyWelcome) {
45992 friendlyWelcome();
45993 doFriendlyWelcome = false;
45994 }
45995 if ('undefined' === getType(color)) {
45996 color = '#B40033'; // dark magenta
45997 } else if (getType(color) === 'number') {
45998 // Type to color
45999 color = typeColors[color];
46000 }
46001
46002 var prefixedMsg;
46003 var style = [
46004 'color: '.concat(color),
46005 'font-family: Arial',
46006 'font-size: larger'
46007 ];
46008 if (func == null || func.substring(0, 4) === 'load') {
46009 prefixedMsg = (0, _internationalization.translator)('fes.pre', {
46010 message: message
46011 });
46012 } else {
46013 var methodParts = func.split('.');
46014 var referenceSection =
46015 methodParts.length > 1
46016 ? ''.concat(methodParts[0], '.').concat(methodParts[1])
46017 : 'p5';
46018
46019 var funcName =
46020 methodParts.length === 1 ? func : methodParts.slice(2).join('/');
46021
46022 prefixedMsg = (0, _internationalization.translator)('fes.pre', {
46023 message: ''
46024 .concat(message, ' (http://p5js.org/reference/#/')
46025 .concat(referenceSection, '/')
46026 .concat(funcName, ')')
46027 });
46028 }
46029 if (ENABLE_FES_STYLING) {
46030 log('%c' + prefixedMsg, style.join(';'));
46031 } else {
46032 log(prefixedMsg);
46033 }
46034 };
46035 /**
46036 * This is a generic method that can be called from anywhere in the p5
46037 * library to alert users to a common error.
46038 *
46039 * @method _friendlyError
46040 * @private
46041 * @param {Number} message message to be printed
46042 * @param {String} method name of method
46043 * @param {Number|String} [color] CSS color string or error type (Optional)
46044 */
46045 _main.default._friendlyError = function(message, method, color) {
46046 report(message, method, color);
46047 };
46048
46049 /**
46050 * This is called internally if there is a error with autoplay.
46051 *
46052 * @method _friendlyAutoplayError
46053 * @private
46054 */
46055 _main.default._friendlyAutoplayError = function(src) {
46056 var message = (0, _internationalization.translator)('fes.autoplay', {
46057 src: src,
46058 link: 'https://developer.mozilla.org/docs/Web/Media/Autoplay_guide'
46059 });
46060
46061 console.log(
46062 (0, _internationalization.translator)('fes.pre', { message: message })
46063 );
46064 };
46065
46066 var computeEditDistance = function computeEditDistance(w1, w2) {
46067 // An implementation of
46068 // https://en.wikipedia.org/wiki/Wagner%E2%80%93Fischer_algorithm to
46069 // compute the Levenshtein distance. It gives a measure of how dissimilar
46070 // two strings are. If the "distance" between them is small enough, it is
46071 // reasonable to think that one is the misspelled version of the other.
46072 var l1 = w1.length,
46073 l2 = w2.length;
46074 if (l1 === 0) return w2;
46075 if (l2 === 0) return w1;
46076
46077 var prev = [];
46078 var cur = [];
46079
46080 for (var j = 0; j < l2 + 1; j++) {
46081 cur[j] = j;
46082 }
46083
46084 prev = cur;
46085
46086 for (var i = 1; i < l1 + 1; i++) {
46087 cur = [];
46088 for (var _j = 0; _j < l2 + 1; _j++) {
46089 if (_j === 0) {
46090 cur[_j] = i;
46091 } else {
46092 var a1 = w1[i - 1],
46093 a2 = w2[_j - 1];
46094 var temp = 999999;
46095 var cost = a1.toLowerCase() === a2.toLowerCase() ? 0 : 1;
46096 temp = temp > cost + prev[_j - 1] ? cost + prev[_j - 1] : temp;
46097 temp = temp > 1 + cur[_j - 1] ? 1 + cur[_j - 1] : temp;
46098 temp = temp > 1 + prev[_j] ? 1 + prev[_j] : temp;
46099 cur[_j] = temp;
46100 }
46101 }
46102 prev = cur;
46103 }
46104
46105 return cur[l2];
46106 };
46107
46108 // checks if the various functions such as setup, draw, preload have been
46109 // defined with capitalization mistakes
46110 var checkForUserDefinedFunctions = function checkForUserDefinedFunctions(
46111 context
46112 ) {
46113 if (_main.default.disableFriendlyErrors) return;
46114
46115 // if using instance mode, this function would be called with the current
46116 // instance as context
46117 var instanceMode = context instanceof _main.default;
46118 context = instanceMode ? context : window;
46119 var fnNames = entryPoints;
46120
46121 var fxns = {};
46122 // lowercasename -> actualName mapping
46123 fnNames.forEach(function(symbol) {
46124 fxns[symbol.toLowerCase()] = symbol;
46125 });
46126
46127 for (
46128 var _i = 0, _Object$keys = Object.keys(context);
46129 _i < _Object$keys.length;
46130 _i++
46131 ) {
46132 var prop = _Object$keys[_i];
46133 var lowercase = prop.toLowerCase();
46134
46135 // check if the lowercase property name has an entry in fxns, if the
46136 // actual name with correct capitalization doesnt exist in context,
46137 // and if the user-defined symbol is of the type function
46138 if (
46139 fxns[lowercase] &&
46140 !context[fxns[lowercase]] &&
46141 typeof context[prop] === 'function'
46142 ) {
46143 var msg = (0, _internationalization.translator)(
46144 'fes.checkUserDefinedFns',
46145 {
46146 name: prop,
46147 actualName: fxns[lowercase]
46148 }
46149 );
46150
46151 _main.default._friendlyError(msg, fxns[lowercase]);
46152 }
46153 }
46154 };
46155
46156 // compares the the symbol caught in the ReferenceErrror to everything
46157 // in misusedAtTopLevel ( all public p5 properties ). The use of
46158 // misusedAtTopLevel here is for convenience as it was an array that was
46159 // already defined when spelling check was implemented. For this particular
46160 // use-case, it's a misnomer.
46161 var handleMisspelling = function handleMisspelling(errSym, error) {
46162 if (!misusedAtTopLevelCode) {
46163 defineMisusedAtTopLevelCode();
46164 }
46165
46166 var min = 999999,
46167 minIndex = 0;
46168 // compute the levenshtein distance for the symbol against all known
46169 // public p5 properties. Find the property with the minimum distance
46170 misusedAtTopLevelCode.forEach(function(symbol, idx) {
46171 var dist = computeEditDistance(errSym, symbol.name);
46172 if (dist < min) {
46173 min = dist;
46174 minIndex = idx;
46175 }
46176 });
46177
46178 if (min > Math.min(EDIT_DIST_THRESHOLD, errSym.length)) return false;
46179
46180 var symbol = misusedAtTopLevelCode[minIndex];
46181
46182 // Show a message only if the caught symbol and the matched property name
46183 // differ in their name ( either letter difference or difference of case )
46184 if (errSym !== symbol.name) {
46185 var parsed = _main.default._getErrorStackParser().parse(error);
46186 var locationObj;
46187 if (
46188 parsed &&
46189 parsed[0] &&
46190 parsed[0].fileName &&
46191 parsed[0].lineNumber &&
46192 parsed[0].columnNumber
46193 ) {
46194 locationObj = {
46195 location: ''
46196 .concat(parsed[0].fileName, ':')
46197 .concat(parsed[0].lineNumber, ':')
46198 .concat(parsed[0].columnNumber),
46199
46200 file: parsed[0].fileName,
46201 line: parsed[0].lineNumber
46202 };
46203 }
46204 var msg = (0, _internationalization.translator)('fes.misspelling', {
46205 name: errSym,
46206 actualName: symbol.name,
46207 type: symbol.type,
46208 location: locationObj
46209 ? (0, _internationalization.translator)('fes.location', locationObj)
46210 : ''
46211 });
46212
46213 _main.default._friendlyError(msg, symbol.name);
46214 return true;
46215 }
46216 return false;
46217 };
46218
46219 var processStack = function processStack(error, stacktrace) {
46220 // Responsible for removing internal library calls from the stacktrace
46221 // and also for detectiong if the error happened inside the library
46222
46223 // cannot process a stacktrace that doesn't exist
46224 if (!stacktrace) return [false, null];
46225
46226 stacktrace.forEach(function(frame) {
46227 frame.functionName = frame.functionName || '';
46228 });
46229
46230 // isInternal - Did this error happen inside the library
46231 var isInternal = false;
46232 var p5FileName, friendlyStack, currentEntryPoint;
46233 for (var i = stacktrace.length - 1; i >= 0; i--) {
46234 var splitted = stacktrace[i].functionName.split('.');
46235 if (entryPoints.includes(splitted[splitted.length - 1])) {
46236 // remove everything below an entry point function (setup, draw, etc).
46237 // (it's usually the internal initialization calls)
46238 friendlyStack = stacktrace.slice(0, i + 1);
46239 currentEntryPoint = splitted[splitted.length - 1];
46240 for (var j = 0; j < i; j++) {
46241 // Due to the current build process, all p5 functions have
46242 // _main.default in their names in the final build. This is the
46243 // easiest way to check if a function is inside the p5 library
46244 if (stacktrace[j].functionName.search('_main.default') !== -1) {
46245 isInternal = true;
46246 p5FileName = stacktrace[j].fileName;
46247 break;
46248 }
46249 }
46250 break;
46251 }
46252 }
46253
46254 // in some cases ( errors in promises, callbacks, etc), no entry-point
46255 // function may be found in the stacktrace. In that case just use the
46256 // entire stacktrace for friendlyStack
46257 if (!friendlyStack) friendlyStack = stacktrace;
46258
46259 if (isInternal) {
46260 // the frameIndex property is added before the filter, so frameIndex
46261 // corresponds to the index of a frame in the original stacktrace.
46262 // Then we filter out all frames which belong to the file that contains
46263 // the p5 library
46264 friendlyStack = friendlyStack
46265 .map(function(frame, index) {
46266 frame.frameIndex = index;
46267 return frame;
46268 })
46269 .filter(function(frame) {
46270 return frame.fileName !== p5FileName;
46271 });
46272
46273 // a weird case, if for some reason we can't identify the function called
46274 // from user's code
46275 if (friendlyStack.length === 0) return [true, null];
46276
46277 // get the function just above the topmost frame in the friendlyStack.
46278 // i.e the name of the library function called from user's code
46279 var func = stacktrace[friendlyStack[0].frameIndex - 1].functionName
46280 .split('.')
46281 .slice(-1)[0];
46282
46283 // Try and get the location (line no.) from the top element of the stack
46284 var locationObj;
46285 if (
46286 friendlyStack[0].fileName &&
46287 friendlyStack[0].lineNumber &&
46288 friendlyStack[0].columnNumber
46289 ) {
46290 locationObj = {
46291 location: ''
46292 .concat(friendlyStack[0].fileName, ':')
46293 .concat(friendlyStack[0].lineNumber, ':')
46294 .concat(friendlyStack[0].columnNumber),
46295 file: friendlyStack[0].fileName.split('/').slice(-1),
46296 line: friendlyStack[0].lineNumber
46297 };
46298
46299 // if already handled by another part of the FES, don't handle again
46300 if (_main.default._fesLogCache[locationObj.location]) return [true, null];
46301 }
46302
46303 // Check if the error is due to a non loadX method being used incorrectly
46304 // in preload
46305 if (
46306 currentEntryPoint === 'preload' &&
46307 _main.default.prototype._preloadMethods[func] == null
46308 ) {
46309 _main.default._friendlyError(
46310 (0, _internationalization.translator)('fes.wrongPreload', {
46311 func: func,
46312 location: locationObj
46313 ? (0, _internationalization.translator)('fes.location', locationObj)
46314 : '',
46315 error: error.message
46316 }),
46317
46318 'preload'
46319 );
46320 } else {
46321 // Library error
46322 _main.default._friendlyError(
46323 (0, _internationalization.translator)('fes.libraryError', {
46324 func: func,
46325 location: locationObj
46326 ? (0, _internationalization.translator)('fes.location', locationObj)
46327 : '',
46328 error: error.message
46329 }),
46330
46331 func
46332 );
46333 }
46334 }
46335 return [isInternal, friendlyStack];
46336 };
46337
46338 // prints a friendly stacktrace which only includes user-written functions
46339 // and is easier for newcomers to understand
46340 var printFriendlyStack = function printFriendlyStack(friendlyStack) {
46341 var log =
46342 _main.default._fesLogger && typeof _main.default._fesLogger === 'function'
46343 ? _main.default._fesLogger
46344 : console.log.bind(console);
46345 if (friendlyStack.length > 1) {
46346 var stacktraceMsg = '';
46347 friendlyStack.forEach(function(frame, idx) {
46348 var location = ''
46349 .concat(frame.fileName, ':')
46350 .concat(frame.lineNumber, ':')
46351 .concat(frame.columnNumber);
46352
46353 var frameMsg,
46354 translationObj = {
46355 func: frame.functionName,
46356 line: frame.lineNumber,
46357 location: location,
46358 file: frame.fileName.split('/').slice(-1)
46359 };
46360
46361 if (idx === 0) {
46362 frameMsg = (0, _internationalization.translator)(
46363 'fes.globalErrors.stackTop',
46364 translationObj
46365 );
46366 } else {
46367 frameMsg = (0, _internationalization.translator)(
46368 'fes.globalErrors.stackSubseq',
46369 translationObj
46370 );
46371 }
46372 stacktraceMsg += frameMsg;
46373 });
46374 log(stacktraceMsg);
46375 }
46376 };
46377
46378 var fesErrorMonitor = function fesErrorMonitor(e) {
46379 if (_main.default.disableFriendlyErrors) return;
46380 // Try to get the error object from e
46381 var error;
46382 if (e instanceof Error) {
46383 error = e;
46384 } else if (e instanceof ErrorEvent) {
46385 error = e.error;
46386 } else if (e instanceof PromiseRejectionEvent) {
46387 error = e.reason;
46388 if (!(error instanceof Error)) return;
46389 }
46390 if (!error) return;
46391
46392 var stacktrace = _main.default._getErrorStackParser().parse(error);
46393 // process the stacktrace from the browser and simplify it to give
46394 // friendlyStack.
46395 var _processStack = processStack(error, stacktrace),
46396 _processStack2 = _slicedToArray(_processStack, 2),
46397 isInternal = _processStack2[0],
46398 friendlyStack = _processStack2[1];
46399
46400 // if this is an internal library error, the type of the error is not relevant,
46401 // only the user code that lead to it is. Show the friendlyStack and return
46402 if (isInternal) {
46403 if (friendlyStack) printFriendlyStack(friendlyStack);
46404 return;
46405 }
46406
46407 var errList = errorTable[error.name];
46408 if (!errList) return; // this type of error can't be handled yet
46409 var matchedError;
46410 var _iteratorNormalCompletion = true;
46411 var _didIteratorError = false;
46412 var _iteratorError = undefined;
46413 try {
46414 for (
46415 var _iterator = errList[Symbol.iterator](), _step;
46416 !(_iteratorNormalCompletion = (_step = _iterator.next()).done);
46417 _iteratorNormalCompletion = true
46418 ) {
46419 var obj = _step.value;
46420 var string = obj.msg;
46421 // capture the primary symbol mentioned in the error
46422 string = string.replace(new RegExp('{{}}', 'g'), '([a-zA-Z0-9_]+)');
46423 string = string.replace(new RegExp('{{.}}', 'g'), '(.+)');
46424 string = string.replace(new RegExp('{}', 'g'), '(?:[a-zA-Z0-9_]+)');
46425 var matched = error.message.match(string);
46426
46427 if (matched) {
46428 matchedError = Object.assign({}, obj);
46429 matchedError.match = matched;
46430 break;
46431 }
46432 }
46433 } catch (err) {
46434 _didIteratorError = true;
46435 _iteratorError = err;
46436 } finally {
46437 try {
46438 if (!_iteratorNormalCompletion && _iterator.return != null) {
46439 _iterator.return();
46440 }
46441 } finally {
46442 if (_didIteratorError) {
46443 throw _iteratorError;
46444 }
46445 }
46446 }
46447
46448 if (!matchedError) return;
46449
46450 // Try and get the location from the top element of the stack
46451 var locationObj;
46452 if (
46453 stacktrace &&
46454 stacktrace[0].fileName &&
46455 stacktrace[0].lineNumber &&
46456 stacktrace[0].columnNumber
46457 ) {
46458 locationObj = {
46459 location: ''
46460 .concat(stacktrace[0].fileName, ':')
46461 .concat(stacktrace[0].lineNumber, ':')
46462 .concat(stacktrace[0].columnNumber),
46463
46464 file: stacktrace[0].fileName.split('/').slice(-1),
46465 line: friendlyStack[0].lineNumber
46466 };
46467 }
46468
46469 switch (error.name) {
46470 case 'SyntaxError': {
46471 // We can't really do much with syntax errors other than try to use
46472 // a simpler framing of the error message. The stack isn't available
46473 // for syntax errors
46474 switch (matchedError.type) {
46475 case 'INVALIDTOKEN': {
46476 var url =
46477 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Illegal_character#What_went_wrong';
46478 _main.default._friendlyError(
46479 (0, _internationalization.translator)(
46480 'fes.globalErrors.syntax.invalidToken',
46481 {
46482 url: url
46483 }
46484 )
46485 );
46486
46487 break;
46488 }
46489 case 'UNEXPECTEDTOKEN': {
46490 var _url =
46491 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Unexpected_token#What_went_wrong';
46492 _main.default._friendlyError(
46493 (0, _internationalization.translator)(
46494 'fes.globalErrors.syntax.unexpectedToken',
46495 {
46496 url: _url
46497 }
46498 )
46499 );
46500
46501 break;
46502 }
46503 }
46504
46505 break;
46506 }
46507 case 'ReferenceError': {
46508 switch (matchedError.type) {
46509 case 'NOTDEFINED': {
46510 var errSym = matchedError.match[1];
46511
46512 if (errSym && handleMisspelling(errSym, error)) {
46513 break;
46514 }
46515
46516 // if the flow gets this far, this is likely not a misspelling
46517 // of a p5 property/function
46518 var url1 = 'https://p5js.org/examples/data-variable-scope.html';
46519 var url2 =
46520 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_Defined#What_went_wrong';
46521 _main.default._friendlyError(
46522 (0, _internationalization.translator)(
46523 'fes.globalErrors.reference.notDefined',
46524 {
46525 url1: url1,
46526 url2: url2,
46527 symbol: errSym,
46528 location: locationObj
46529 ? (0, _internationalization.translator)(
46530 'fes.location',
46531 locationObj
46532 )
46533 : ''
46534 }
46535 )
46536 );
46537
46538 if (friendlyStack) printFriendlyStack(friendlyStack);
46539 break;
46540 }
46541 }
46542
46543 break;
46544 }
46545
46546 case 'TypeError': {
46547 switch (matchedError.type) {
46548 case 'NOTFUNC': {
46549 var _errSym = matchedError.match[1];
46550 var splitSym = _errSym.split('.');
46551 var _url2 =
46552 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_a_function#What_went_wrong';
46553
46554 // if errSym is aa.bb.cc , symbol would be cc and obj would aa.bb
46555 var translationObj = {
46556 url: _url2,
46557 symbol: splitSym[splitSym.length - 1],
46558 obj: splitSym.slice(0, splitSym.length - 1).join('.'),
46559 location: locationObj
46560 ? (0, _internationalization.translator)(
46561 'fes.location',
46562 locationObj
46563 )
46564 : ''
46565 };
46566
46567 // There are two cases to handle here. When the function is called
46568 // as a property of an object and when it's called independently.
46569 // Both have different explanations.
46570 if (splitSym.length > 1) {
46571 _main.default._friendlyError(
46572 (0, _internationalization.translator)(
46573 'fes.globalErrors.type.notfuncObj',
46574 translationObj
46575 )
46576 );
46577 } else {
46578 _main.default._friendlyError(
46579 (0, _internationalization.translator)(
46580 'fes.globalErrors.type.notfunc',
46581 translationObj
46582 )
46583 );
46584 }
46585
46586 if (friendlyStack) printFriendlyStack(friendlyStack);
46587 break;
46588 }
46589 }
46590 }
46591 }
46592 };
46593
46594 _main.default._fesErrorMonitor = fesErrorMonitor;
46595 _main.default._checkForUserDefinedFunctions = checkForUserDefinedFunctions;
46596
46597 // logger for testing purposes.
46598 _main.default._fesLogger = null;
46599 _main.default._fesLogCache = {};
46600
46601 window.addEventListener('load', checkForUserDefinedFunctions, false);
46602 window.addEventListener('error', _main.default._fesErrorMonitor, false);
46603 window.addEventListener(
46604 'unhandledrejection',
46605 _main.default._fesErrorMonitor,
46606 false
46607 );
46608
46609 /**
46610 * Prints out all the colors in the color pallete with white text.
46611 * For color blindness testing.
46612 */
46613 /* function testColors() {
46614 const str = 'A box of biscuits, a box of mixed biscuits and a biscuit mixer';
46615 report(str, 'print', '#ED225D'); // p5.js magenta
46616 report(str, 'print', '#2D7BB6'); // p5.js blue
46617 report(str, 'print', '#EE9900'); // p5.js orange
46618 report(str, 'print', '#A67F59'); // p5.js light brown
46619 report(str, 'print', '#704F21'); // p5.js gold
46620 report(str, 'print', '#1CC581'); // auto cyan
46621 report(str, 'print', '#FF6625'); // auto orange
46622 report(str, 'print', '#79EB22'); // auto green
46623 report(str, 'print', '#B40033'); // p5.js darkened magenta
46624 report(str, 'print', '#084B7F'); // p5.js darkened blue
46625 report(str, 'print', '#945F00'); // p5.js darkened orange
46626 report(str, 'print', '#6B441D'); // p5.js darkened brown
46627 report(str, 'print', '#2E1B00'); // p5.js darkened gold
46628 report(str, 'print', '#008851'); // auto dark cyan
46629 report(str, 'print', '#C83C00'); // auto dark orange
46630 report(str, 'print', '#4DB200'); // auto dark green
46631 } */
46632 }
46633
46634 // This is a lazily-defined list of p5 symbols that may be
46635 // misused by beginners at top-level code, outside of setup/draw. We'd like
46636 // to detect these errors and help the user by suggesting they move them
46637 // into setup/draw.
46638 //
46639 // For more details, see https://github.com/processing/p5.js/issues/1121.
46640 misusedAtTopLevelCode = null;
46641 var FAQ_URL =
46642 'https://github.com/processing/p5.js/wiki/p5.js-overview#why-cant-i-assign-variables-using-p5-functions-and-variables-before-setup';
46643
46644 defineMisusedAtTopLevelCode = function defineMisusedAtTopLevelCode() {
46645 var uniqueNamesFound = {};
46646
46647 var getSymbols = function getSymbols(obj) {
46648 return Object.getOwnPropertyNames(obj)
46649 .filter(function(name) {
46650 if (name[0] === '_') {
46651 return false;
46652 }
46653 if (name in uniqueNamesFound) {
46654 return false;
46655 }
46656
46657 uniqueNamesFound[name] = true;
46658
46659 return true;
46660 })
46661 .map(function(name) {
46662 var type;
46663
46664 if (typeof obj[name] === 'function') {
46665 type = 'function';
46666 } else if (name === name.toUpperCase()) {
46667 type = 'constant';
46668 } else {
46669 type = 'variable';
46670 }
46671
46672 return { name: name, type: type };
46673 });
46674 };
46675
46676 misusedAtTopLevelCode = [].concat(
46677 getSymbols(_main.default.prototype),
46678 // At present, p5 only adds its constants to p5.prototype during
46679 // construction, which may not have happened at the time a
46680 // ReferenceError is thrown, so we'll manually add them to our list.
46681 getSymbols(_dereq_('../constants'))
46682 );
46683
46684 // This will ultimately ensure that we report the most specific error
46685 // possible to the user, e.g. advising them about HALF_PI instead of PI
46686 // when their code misuses the former.
46687 misusedAtTopLevelCode.sort(function(a, b) {
46688 return b.name.length - a.name.length;
46689 });
46690 };
46691
46692 var helpForMisusedAtTopLevelCode = function helpForMisusedAtTopLevelCode(e, log) {
46693 if (!log) {
46694 log = console.log.bind(console);
46695 }
46696
46697 if (!misusedAtTopLevelCode) {
46698 defineMisusedAtTopLevelCode();
46699 }
46700
46701 // If we find that we're logging lots of false positives, we can
46702 // uncomment the following code to avoid displaying anything if the
46703 // user's code isn't likely to be using p5's global mode. (Note that
46704 // setup/draw are more likely to be defined due to JS function hoisting.)
46705 //
46706 //if (!('setup' in window || 'draw' in window)) {
46707 // return;
46708 //}
46709
46710 misusedAtTopLevelCode.some(function(symbol) {
46711 // Note that while just checking for the occurrence of the
46712 // symbol name in the error message could result in false positives,
46713 // a more rigorous test is difficult because different browsers
46714 // log different messages, and the format of those messages may
46715 // change over time.
46716 //
46717 // For example, if the user uses 'PI' in their code, it may result
46718 // in any one of the following messages:
46719 //
46720 // * 'PI' is undefined (Microsoft Edge)
46721 // * ReferenceError: PI is undefined (Firefox)
46722 // * Uncaught ReferenceError: PI is not defined (Chrome)
46723
46724 if (
46725 e.message &&
46726 e.message.match('\\W?'.concat(symbol.name, '\\W')) !== null
46727 ) {
46728 var symbolName =
46729 symbol.type === 'function' ? ''.concat(symbol.name, '()') : symbol.name;
46730 if (typeof IS_MINIFIED !== 'undefined') {
46731 log(
46732 "Did you just try to use p5.js's "
46733 .concat(symbolName, ' ')
46734 .concat(
46735 symbol.type,
46736 "? If so, you may want to move it into your sketch's setup() function.\n\nFor more details, see: "
46737 )
46738 .concat(FAQ_URL)
46739 );
46740 } else {
46741 log(
46742 (0, _internationalization.translator)('fes.misusedTopLevel', {
46743 symbolName: symbolName,
46744 symbolType: symbol.type,
46745 link: FAQ_URL
46746 })
46747 );
46748 }
46749 return true;
46750 }
46751 });
46752 };
46753
46754 // Exposing this primarily for unit testing.
46755 _main.default.prototype._helpForMisusedAtTopLevelCode = helpForMisusedAtTopLevelCode;
46756
46757 if (document.readyState !== 'complete') {
46758 window.addEventListener('error', helpForMisusedAtTopLevelCode, false);
46759
46760 // Our job is only to catch ReferenceErrors that are thrown when
46761 // global (non-instance mode) p5 APIs are used at the top-level
46762 // scope of a file, so we'll unbind our error listener now to make
46763 // sure we don't log false positives later.
46764 window.addEventListener('load', function() {
46765 window.removeEventListener('error', helpForMisusedAtTopLevelCode, false);
46766 });
46767 }
46768 var _default = _main.default;
46769 exports.default = _default;
46770 },
46771 {
46772 '../constants': 43,
46773 '../internationalization': 52,
46774 '../main': 54,
46775 './browser_errors': 45
46776 }
46777 ],
46778 47: [
46779 function(_dereq_, module, exports) {
46780 'use strict';
46781 Object.defineProperty(exports, '__esModule', { value: true });
46782 exports.default = void 0;
46783
46784 var _main = _interopRequireDefault(_dereq_('../main'));
46785 var _internationalization = _dereq_('../internationalization');
46786 function _interopRequireDefault(obj) {
46787 return obj && obj.__esModule ? obj : { default: obj };
46788 }
46789 /**
46790 * @for p5
46791 * @requires core
46792 */ if (typeof IS_MINIFIED !== 'undefined') {
46793 _main.default._friendlyFileLoadError = function() {};
46794 } else {
46795 // mapping used by `_friendlyFileLoadError`
46796 var fileLoadErrorCases = function fileLoadErrorCases(num, filePath) {
46797 var suggestion = (0, _internationalization.translator)(
46798 'fes.fileLoadError.suggestion',
46799 {
46800 filePath: filePath,
46801 link: 'https://github.com/processing/p5.js/wiki/Local-server'
46802 }
46803 );
46804
46805 switch (num) {
46806 case 0:
46807 return {
46808 message: (0, _internationalization.translator)(
46809 'fes.fileLoadError.image',
46810 {
46811 suggestion: suggestion
46812 }
46813 ),
46814
46815 method: 'loadImage'
46816 };
46817
46818 case 1:
46819 return {
46820 message: (0, _internationalization.translator)(
46821 'fes.fileLoadError.xml',
46822 {
46823 suggestion: suggestion
46824 }
46825 ),
46826
46827 method: 'loadXML'
46828 };
46829
46830 case 2:
46831 return {
46832 message: (0, _internationalization.translator)(
46833 'fes.fileLoadError.table',
46834 {
46835 suggestion: suggestion
46836 }
46837 ),
46838
46839 method: 'loadTable'
46840 };
46841
46842 case 3:
46843 return {
46844 message: (0, _internationalization.translator)(
46845 'fes.fileLoadError.strings',
46846 {
46847 suggestion: suggestion
46848 }
46849 ),
46850
46851 method: 'loadStrings'
46852 };
46853
46854 case 4:
46855 return {
46856 message: (0, _internationalization.translator)(
46857 'fes.fileLoadError.font',
46858 {
46859 suggestion: suggestion
46860 }
46861 ),
46862
46863 method: 'loadFont'
46864 };
46865
46866 case 5:
46867 return {
46868 message: (0, _internationalization.translator)(
46869 'fes.fileLoadError.json',
46870 {
46871 suggestion: suggestion
46872 }
46873 ),
46874
46875 method: 'loadJSON'
46876 };
46877
46878 case 6:
46879 return {
46880 message: (0, _internationalization.translator)(
46881 'fes.fileLoadError.bytes',
46882 {
46883 suggestion: suggestion
46884 }
46885 ),
46886
46887 method: 'loadBytes'
46888 };
46889
46890 case 7:
46891 return {
46892 message: (0, _internationalization.translator)(
46893 'fes.fileLoadError.large'
46894 ),
46895 method: 'loadX'
46896 };
46897
46898 case 8:
46899 return {
46900 message: (0, _internationalization.translator)('fes.fileLoadError.gif'),
46901 method: 'loadImage'
46902 };
46903 }
46904 };
46905
46906 /**
46907 * This is called internally if there is a error during file loading.
46908 *
46909 * @method _friendlyFileLoadError
46910 * @private
46911 * @param {Number} errorType
46912 * @param {String} filePath
46913 */
46914 _main.default._friendlyFileLoadError = function(errorType, filePath) {
46915 var _fileLoadErrorCases = fileLoadErrorCases(errorType, filePath),
46916 message = _fileLoadErrorCases.message,
46917 method = _fileLoadErrorCases.method;
46918 _main.default._friendlyError(message, method, 3);
46919 };
46920 }
46921 var _default = _main.default;
46922 exports.default = _default;
46923 },
46924 { '../internationalization': 52, '../main': 54 }
46925 ],
46926 48: [
46927 function(_dereq_, module, exports) {
46928 'use strict';
46929 Object.defineProperty(exports, '__esModule', { value: true });
46930 exports.default = void 0;
46931
46932 var _main = _interopRequireDefault(_dereq_('../main'));
46933 function _interopRequireDefault(obj) {
46934 return obj && obj.__esModule ? obj : { default: obj };
46935 } /** // Borrow from stacktracejs https://github.com/stacktracejs/stacktrace.js with
46936 * @for p5
46937 * @requires core
46938 */
46939 // minor modifications. The license for the same and the code is included below
46940 // Copyright (c) 2017 Eric Wendelin and other contributors
46941 // Permission is hereby granted, free of charge, to any person obtaining a copy of
46942 // this software and associated documentation files (the "Software"), to deal in
46943 // the Software without restriction, including without limitation the rights to
46944 // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
46945 // of the Software, and to permit persons to whom the Software is furnished to do
46946 // so, subject to the following conditions:
46947 // The above copyright notice and this permission notice shall be included in all
46948 // copies or substantial portions of the Software.
46949 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
46950 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
46951 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
46952 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
46953 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
46954 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
46955 // SOFTWARE.
46956 function ErrorStackParser() {
46957 'use strict';
46958
46959 var FIREFOX_SAFARI_STACK_REGEXP = /(^|@)\S+:\d+/;
46960 var CHROME_IE_STACK_REGEXP = /^\s*at .*(\S+:\d+|\(native\))/m;
46961 var SAFARI_NATIVE_CODE_REGEXP = /^(eval@)?(\[native code])?$/;
46962
46963 return {
46964 /**
46965 * Given an Error object, extract the most information from it.
46966 *
46967 * @param {Error} error object
46968 * @return {Array} of stack frames
46969 */
46970 parse: function ErrorStackParser$$parse(error) {
46971 if (
46972 typeof error.stacktrace !== 'undefined' ||
46973 typeof error['opera#sourceloc'] !== 'undefined'
46974 ) {
46975 return this.parseOpera(error);
46976 } else if (error.stack && error.stack.match(CHROME_IE_STACK_REGEXP)) {
46977 return this.parseV8OrIE(error);
46978 } else if (error.stack) {
46979 return this.parseFFOrSafari(error);
46980 } else {
46981 // throw new Error('Cannot parse given Error object');
46982 }
46983 },
46984
46985 // Separate line and column numbers from a string of the form: (URI:Line:Column)
46986 extractLocation: function ErrorStackParser$$extractLocation(urlLike) {
46987 // Fail-fast but return locations like "(native)"
46988 if (urlLike.indexOf(':') === -1) {
46989 return [urlLike];
46990 }
46991
46992 var regExp = /(.+?)(?::(\d+))?(?::(\d+))?$/;
46993 var parts = regExp.exec(urlLike.replace(/[()]/g, ''));
46994 return [parts[1], parts[2] || undefined, parts[3] || undefined];
46995 },
46996
46997 parseV8OrIE: function ErrorStackParser$$parseV8OrIE(error) {
46998 var filtered = error.stack.split('\n').filter(function(line) {
46999 return !!line.match(CHROME_IE_STACK_REGEXP);
47000 }, this);
47001
47002 return filtered.map(function(line) {
47003 if (line.indexOf('(eval ') > -1) {
47004 // Throw away eval information until we implement stacktrace.js/stackframe#8
47005 line = line
47006 .replace(/eval code/g, 'eval')
47007 .replace(/(\(eval at [^()]*)|(\),.*$)/g, '');
47008 }
47009 var sanitizedLine = line.replace(/^\s+/, '').replace(/\(eval code/g, '(');
47010
47011 // capture and preseve the parenthesized location "(/foo/my bar.js:12:87)" in
47012 // case it has spaces in it, as the string is split on \s+ later on
47013 var location = sanitizedLine.match(/ (\((.+):(\d+):(\d+)\)$)/);
47014
47015 // remove the parenthesized location from the line, if it was matched
47016 sanitizedLine = location
47017 ? sanitizedLine.replace(location[0], '')
47018 : sanitizedLine;
47019
47020 var tokens = sanitizedLine.split(/\s+/).slice(1);
47021 // if a location was matched, pass it to extractLocation() otherwise pop the last token
47022 var locationParts = this.extractLocation(
47023 location ? location[1] : tokens.pop()
47024 );
47025
47026 var functionName = tokens.join(' ') || undefined;
47027 var fileName =
47028 ['eval', '<anonymous>'].indexOf(locationParts[0]) > -1
47029 ? undefined
47030 : locationParts[0];
47031
47032 return {
47033 functionName: functionName,
47034 fileName: fileName,
47035 lineNumber: locationParts[1],
47036 columnNumber: locationParts[2],
47037 source: line
47038 };
47039 }, this);
47040 },
47041
47042 parseFFOrSafari: function ErrorStackParser$$parseFFOrSafari(error) {
47043 var filtered = error.stack.split('\n').filter(function(line) {
47044 return !line.match(SAFARI_NATIVE_CODE_REGEXP);
47045 }, this);
47046
47047 return filtered.map(function(line) {
47048 // Throw away eval information until we implement stacktrace.js/stackframe#8
47049 if (line.indexOf(' > eval') > -1) {
47050 line = line.replace(
47051 / line (\d+)(?: > eval line \d+)* > eval:\d+:\d+/g,
47052 ':$1'
47053 );
47054 }
47055
47056 if (line.indexOf('@') === -1 && line.indexOf(':') === -1) {
47057 // Safari eval frames only have function names and nothing else
47058 return {
47059 functionName: line
47060 };
47061 } else {
47062 var functionNameRegex = /((.*".+"[^@]*)?[^@]*)(?:@)/;
47063 var matches = line.match(functionNameRegex);
47064 var functionName = matches && matches[1] ? matches[1] : undefined;
47065 var locationParts = this.extractLocation(
47066 line.replace(functionNameRegex, '')
47067 );
47068
47069 return {
47070 functionName: functionName,
47071 fileName: locationParts[0],
47072 lineNumber: locationParts[1],
47073 columnNumber: locationParts[2],
47074 source: line
47075 };
47076 }
47077 }, this);
47078 },
47079
47080 parseOpera: function ErrorStackParser$$parseOpera(e) {
47081 if (
47082 !e.stacktrace ||
47083 (e.message.indexOf('\n') > -1 &&
47084 e.message.split('\n').length > e.stacktrace.split('\n').length)
47085 ) {
47086 return this.parseOpera9(e);
47087 } else if (!e.stack) {
47088 return this.parseOpera10(e);
47089 } else {
47090 return this.parseOpera11(e);
47091 }
47092 },
47093
47094 parseOpera9: function ErrorStackParser$$parseOpera9(e) {
47095 var lineRE = /Line (\d+).*script (?:in )?(\S+)/i;
47096 var lines = e.message.split('\n');
47097 var result = [];
47098
47099 for (var i = 2, len = lines.length; i < len; i += 2) {
47100 var match = lineRE.exec(lines[i]);
47101 if (match) {
47102 result.push({
47103 fileName: match[2],
47104 lineNumber: match[1],
47105 source: lines[i]
47106 });
47107 }
47108 }
47109
47110 return result;
47111 },
47112
47113 parseOpera10: function ErrorStackParser$$parseOpera10(e) {
47114 var lineRE = /Line (\d+).*script (?:in )?(\S+)(?:: In function (\S+))?$/i;
47115 var lines = e.stacktrace.split('\n');
47116 var result = [];
47117
47118 for (var i = 0, len = lines.length; i < len; i += 2) {
47119 var match = lineRE.exec(lines[i]);
47120 if (match) {
47121 result.push({
47122 functionName: match[3] || undefined,
47123 fileName: match[2],
47124 lineNumber: match[1],
47125 source: lines[i]
47126 });
47127 }
47128 }
47129
47130 return result;
47131 },
47132
47133 // Opera 10.65+ Error.stack very similar to FF/Safari
47134 parseOpera11: function ErrorStackParser$$parseOpera11(error) {
47135 var filtered = error.stack.split('\n').filter(function(line) {
47136 return (
47137 !!line.match(FIREFOX_SAFARI_STACK_REGEXP) &&
47138 !line.match(/^Error created at/)
47139 );
47140 }, this);
47141
47142 return filtered.map(function(line) {
47143 var tokens = line.split('@');
47144 var locationParts = this.extractLocation(tokens.pop());
47145 var functionCall = tokens.shift() || '';
47146 var functionName =
47147 functionCall
47148 .replace(/<anonymous function(: (\w+))?>/, '$2')
47149 .replace(/\([^)]*\)/g, '') || undefined;
47150 var argsRaw;
47151 if (functionCall.match(/\(([^)]*)\)/)) {
47152 argsRaw = functionCall.replace(/^[^(]+\(([^)]*)\)$/, '$1');
47153 }
47154 var args =
47155 argsRaw === undefined || argsRaw === '[arguments not available]'
47156 ? undefined
47157 : argsRaw.split(',');
47158
47159 return {
47160 functionName: functionName,
47161 args: args,
47162 fileName: locationParts[0],
47163 lineNumber: locationParts[1],
47164 columnNumber: locationParts[2],
47165 source: line
47166 };
47167 }, this);
47168 }
47169 };
47170 }
47171
47172 // End borrow
47173
47174 // wrapper exposing ErrorStackParser
47175 _main.default._getErrorStackParser = function getErrorStackParser() {
47176 return new ErrorStackParser();
47177 };
47178 var _default = _main.default;
47179 exports.default = _default;
47180 },
47181 { '../main': 54 }
47182 ],
47183 49: [
47184 function(_dereq_, module, exports) {
47185 'use strict';
47186 Object.defineProperty(exports, '__esModule', { value: true });
47187 exports.default = void 0;
47188
47189 var _main = _interopRequireDefault(_dereq_('../main'));
47190 var constants = _interopRequireWildcard(_dereq_('../constants'));
47191 var _internationalization = _dereq_('../internationalization');
47192 function _getRequireWildcardCache() {
47193 if (typeof WeakMap !== 'function') return null;
47194 var cache = new WeakMap();
47195 _getRequireWildcardCache = function _getRequireWildcardCache() {
47196 return cache;
47197 };
47198 return cache;
47199 }
47200 function _interopRequireWildcard(obj) {
47201 if (obj && obj.__esModule) {
47202 return obj;
47203 }
47204 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) {
47205 return { default: obj };
47206 }
47207 var cache = _getRequireWildcardCache();
47208 if (cache && cache.has(obj)) {
47209 return cache.get(obj);
47210 }
47211 var newObj = {};
47212 var hasPropertyDescriptor =
47213 Object.defineProperty && Object.getOwnPropertyDescriptor;
47214 for (var key in obj) {
47215 if (Object.prototype.hasOwnProperty.call(obj, key)) {
47216 var desc = hasPropertyDescriptor
47217 ? Object.getOwnPropertyDescriptor(obj, key)
47218 : null;
47219 if (desc && (desc.get || desc.set)) {
47220 Object.defineProperty(newObj, key, desc);
47221 } else {
47222 newObj[key] = obj[key];
47223 }
47224 }
47225 }
47226 newObj.default = obj;
47227 if (cache) {
47228 cache.set(obj, newObj);
47229 }
47230 return newObj;
47231 }
47232 function _interopRequireDefault(obj) {
47233 return obj && obj.__esModule ? obj : { default: obj };
47234 }
47235 function _classCallCheck(instance, Constructor) {
47236 if (!(instance instanceof Constructor)) {
47237 throw new TypeError('Cannot call a class as a function');
47238 }
47239 }
47240 function _possibleConstructorReturn(self, call) {
47241 if (call && (_typeof(call) === 'object' || typeof call === 'function')) {
47242 return call;
47243 }
47244 return _assertThisInitialized(self);
47245 }
47246 function _assertThisInitialized(self) {
47247 if (self === void 0) {
47248 throw new ReferenceError(
47249 "this hasn't been initialised - super() hasn't been called"
47250 );
47251 }
47252 return self;
47253 }
47254 function _inherits(subClass, superClass) {
47255 if (typeof superClass !== 'function' && superClass !== null) {
47256 throw new TypeError('Super expression must either be null or a function');
47257 }
47258 subClass.prototype = Object.create(superClass && superClass.prototype, {
47259 constructor: { value: subClass, writable: true, configurable: true }
47260 });
47261 if (superClass) _setPrototypeOf(subClass, superClass);
47262 }
47263 function _wrapNativeSuper(Class) {
47264 var _cache = typeof Map === 'function' ? new Map() : undefined;
47265 _wrapNativeSuper = function _wrapNativeSuper(Class) {
47266 if (Class === null || !_isNativeFunction(Class)) return Class;
47267 if (typeof Class !== 'function') {
47268 throw new TypeError('Super expression must either be null or a function');
47269 }
47270 if (typeof _cache !== 'undefined') {
47271 if (_cache.has(Class)) return _cache.get(Class);
47272 _cache.set(Class, Wrapper);
47273 }
47274 function Wrapper() {
47275 return _construct(Class, arguments, _getPrototypeOf(this).constructor);
47276 }
47277 Wrapper.prototype = Object.create(Class.prototype, {
47278 constructor: {
47279 value: Wrapper,
47280 enumerable: false,
47281 writable: true,
47282 configurable: true
47283 }
47284 });
47285 return _setPrototypeOf(Wrapper, Class);
47286 };
47287 return _wrapNativeSuper(Class);
47288 }
47289 function isNativeReflectConstruct() {
47290 if (typeof Reflect === 'undefined' || !Reflect.construct) return false;
47291 if (Reflect.construct.sham) return false;
47292 if (typeof Proxy === 'function') return true;
47293 try {
47294 Date.prototype.toString.call(Reflect.construct(Date, [], function() {}));
47295 return true;
47296 } catch (e) {
47297 return false;
47298 }
47299 }
47300 function _construct(Parent, args, Class) {
47301 if (isNativeReflectConstruct()) {
47302 _construct = Reflect.construct;
47303 } else {
47304 _construct = function _construct(Parent, args, Class) {
47305 var a = [null];
47306 a.push.apply(a, args);
47307 var Constructor = Function.bind.apply(Parent, a);
47308 var instance = new Constructor();
47309 if (Class) _setPrototypeOf(instance, Class.prototype);
47310 return instance;
47311 };
47312 }
47313 return _construct.apply(null, arguments);
47314 }
47315 function _isNativeFunction(fn) {
47316 return Function.toString.call(fn).indexOf('[native code]') !== -1;
47317 }
47318 function _setPrototypeOf(o, p) {
47319 _setPrototypeOf =
47320 Object.setPrototypeOf ||
47321 function _setPrototypeOf(o, p) {
47322 o.__proto__ = p;
47323 return o;
47324 };
47325 return _setPrototypeOf(o, p);
47326 }
47327 function _getPrototypeOf(o) {
47328 _getPrototypeOf = Object.setPrototypeOf
47329 ? Object.getPrototypeOf
47330 : function _getPrototypeOf(o) {
47331 return o.__proto__ || Object.getPrototypeOf(o);
47332 };
47333 return _getPrototypeOf(o);
47334 }
47335 function _typeof(obj) {
47336 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
47337 _typeof = function _typeof(obj) {
47338 return typeof obj;
47339 };
47340 } else {
47341 _typeof = function _typeof(obj) {
47342 return obj &&
47343 typeof Symbol === 'function' &&
47344 obj.constructor === Symbol &&
47345 obj !== Symbol.prototype
47346 ? 'symbol'
47347 : typeof obj;
47348 };
47349 }
47350 return _typeof(obj);
47351 }
47352
47353 if (typeof IS_MINIFIED !== 'undefined') {
47354 _main.default._validateParameters = _main.default._clearValidateParamsCache = function() {};
47355 } else {
47356 // for parameter validation
47357 var dataDoc = _dereq_('../../../docs/parameterData.json');
47358 var arrDoc = JSON.parse(JSON.stringify(dataDoc));
47359
47360 var docCache = {};
47361 var builtinTypes = new Set([
47362 'null',
47363 'number',
47364 'string',
47365 'boolean',
47366 'constant',
47367 'function',
47368 'any',
47369 'integer'
47370 ]);
47371
47372 var basicTypes = {
47373 number: true,
47374 boolean: true,
47375 string: true,
47376 function: true,
47377 undefined: true
47378 };
47379
47380 // reverse map of all constants
47381 var constantsReverseMap = {};
47382 for (var key in constants) {
47383 constantsReverseMap[constants[key]] = key;
47384 }
47385
47386 // mapping names of p5 types to their constructor function
47387 // p5Constructors:
47388 // - Color: f()
47389 // - Graphics: f()
47390 // - Vector: f()
47391 // and so on
47392 var p5Constructors = {};
47393
47394 // For speedup over many runs. funcSpecificConstructors[func] only has the
47395 // constructors for types which were seen earlier as args of "func"
47396 var funcSpecificConstructors = {};
47397 window.addEventListener('load', function() {
47398 // Make a list of all p5 classes to be used for argument validation
47399 // This must be done only when everything has loaded otherwise we get
47400 // an empty array
47401 for (
47402 var _i = 0, _Object$keys = Object.keys(_main.default);
47403 _i < _Object$keys.length;
47404 _i++
47405 ) {
47406 var _key = _Object$keys[_i];
47407 // Get a list of all constructors in p5. They are functions whose names
47408 // start with a capital letter
47409 if (
47410 typeof _main.default[_key] === 'function' &&
47411 _key[0] !== _key[0].toLowerCase()
47412 ) {
47413 p5Constructors[_key] = _main.default[_key];
47414 }
47415 }
47416 });
47417
47418 var argumentTree = {};
47419 // The following two functions are responsible for querying and inserting
47420 // into the argument tree. It stores the types of arguments that each
47421 // function has seen so far. It is used to query if a sequence of
47422 // arguments seen in validate parameters was seen before.
47423 // Lets consider that the following segment of code runs repeatedly, perhaps
47424 // in a loop or in draw()
47425 // color(10, 10, 10);
47426 // color(10, 10);
47427 // color('r', 'g', 'b');
47428 // After the first of run the code segment, the argument tree looks like
47429 // - color
47430 // - number
47431 // - number
47432 // - number
47433 // - seen: true
47434 // - seen: true
47435 // - string
47436 // - string
47437 // - string
47438 // - seen: true
47439 // seen: true signifies that this argument was also seen as the last
47440 // argument in a call. Now in the second run of the sketch, it would traverse
47441 // the existing tree and see seen: true, i.e this sequence was seen
47442 // before and so scoring can be skipped. This also prevents logging multiple
47443 // validation messages for the same thing.
47444
47445 // These two functions would be called repeatedly over and over again,
47446 // so they need to be as optimized for performance as possible
47447
47448 var addType = function addType(value, obj, func) {
47449 var type = _typeof(value);
47450 if (basicTypes[type]) {
47451 if (constantsReverseMap[value]) {
47452 // check if the value is a p5 constant and if it is, we would want the
47453 // value itself to be stored in the tree instead of the type
47454 obj = obj[value] || (obj[value] = {});
47455 } else {
47456 obj = obj[type] || (obj[type] = {});
47457 }
47458 } else if (value === null) {
47459 // typeof null -> "object". don't want that
47460 obj = obj['null'] || (obj['null'] = {});
47461 } else {
47462 // objects which are instances of p5 classes have nameless constructors.
47463 // native objects have a constructor named "Object". This check
47464 // differentiates between the two so that we dont waste time finding the
47465 // p5 class if we just have a native object
47466 if (value.constructor && value.constructor.name) {
47467 obj = obj[value.constructor.name] || (obj[value.constructor.name] = {});
47468 return obj;
47469 }
47470
47471 // constructors for types defined in p5 do not have a name property.
47472 // e.constructor.name gives "". Code in this segment is a workaround for it
47473
47474 // p5C will only have the name: constructor mapping for types
47475 // which were already seen as args of "func"
47476 var p5C = funcSpecificConstructors[func];
47477 // p5C would contain much fewer items than p5Constructors. if we find our
47478 // answer in p5C, we don't have to scan through p5Constructors
47479
47480 if (p5C === undefined) {
47481 // if there isn't an entry yet for func
47482 // make an entry of empty object
47483 p5C = funcSpecificConstructors[func] = {};
47484 }
47485
47486 for (var _key2 in p5C) {
47487 // search on the constructors we have already seen (smaller search space)
47488 if (value instanceof p5C[_key2]) {
47489 obj = obj[_key2] || (obj[_key2] = {});
47490 return obj;
47491 }
47492 }
47493
47494 for (var _key3 in p5Constructors) {
47495 // if the above search didn't work, search on all p5 constructors
47496 if (value instanceof p5Constructors[_key3]) {
47497 obj = obj[_key3] || (obj[_key3] = {});
47498 // if found, add to known constructors for this function
47499 p5C[_key3] = p5Constructors[_key3];
47500 return obj;
47501 }
47502 }
47503 // nothing worked, put the type as is
47504 obj = obj[type] || (obj[type] = {});
47505 }
47506
47507 return obj;
47508 };
47509 var buildArgTypeCache = function buildArgTypeCache(func, arr) {
47510 // get the if an argument tree for current function already exists
47511 var obj = argumentTree[func];
47512 if (obj === undefined) {
47513 // if it doesn't, create an empty tree
47514 obj = argumentTree[func] = {};
47515 }
47516
47517 for (var i = 0, len = arr.length; i < len; ++i) {
47518 var value = arr[i];
47519 if (value instanceof Array) {
47520 // an array is passed as an argument, expand it and get the type of
47521 // each of its element. We distinguish the start of an array with 'as'
47522 // or arraystart. This would help distinguish between the arguments
47523 // (number, number, number) and (number, [number, number])
47524 obj = obj['as'] || (obj['as'] = {});
47525 for (var j = 0, lenA = value.length; j < lenA; ++j) {
47526 obj = addType(value[j], obj, func);
47527 }
47528 } else {
47529 obj = addType(value, obj, func);
47530 }
47531 }
47532 return obj;
47533 };
47534
47535 // validateParameters() helper functions:
47536 // lookupParamDoc() for querying data.json
47537 var lookupParamDoc = function lookupParamDoc(func) {
47538 // look for the docs in the `data.json` datastructure
47539
47540 var ichDot = func.lastIndexOf('.');
47541 var funcName = func.substr(ichDot + 1);
47542 var funcClass = func.substr(0, ichDot) || 'p5';
47543
47544 var classitems = arrDoc;
47545 var queryResult = classitems[funcClass][funcName];
47546
47547 // different JSON structure for funct with multi-format
47548 var overloads = [];
47549 if (queryResult.hasOwnProperty('overloads')) {
47550 // add all the overloads
47551 for (var i = 0; i < queryResult.overloads.length; i++) {
47552 overloads.push({ formats: queryResult.overloads[i].params });
47553 }
47554 } else {
47555 // no overloads, just add the main method definition
47556 overloads.push({ formats: queryResult.params || [] });
47557 }
47558
47559 // parse the parameter types for each overload
47560 var mapConstants = {};
47561 var maxParams = 0;
47562 overloads.forEach(function(overload) {
47563 var formats = overload.formats;
47564
47565 // keep a record of the maximum number of arguments
47566 // this method requires.
47567 if (maxParams < formats.length) {
47568 maxParams = formats.length;
47569 }
47570
47571 // calculate the minimum number of arguments
47572 // this overload requires.
47573 var minParams = formats.length;
47574 while (minParams > 0 && formats[minParams - 1].optional) {
47575 minParams--;
47576 }
47577 overload.minParams = minParams;
47578
47579 // loop through each parameter position, and parse its types
47580 formats.forEach(function(format) {
47581 // split this parameter's types
47582 format.types = format.type.split('|').map(function ct(type) {
47583 // array
47584 if (type.substr(type.length - 2, 2) === '[]') {
47585 return {
47586 name: type,
47587 array: ct(type.substr(0, type.length - 2))
47588 };
47589 }
47590
47591 var lowerType = type.toLowerCase();
47592
47593 // contant
47594 if (lowerType === 'constant') {
47595 var constant;
47596 if (mapConstants.hasOwnProperty(format.name)) {
47597 constant = mapConstants[format.name];
47598 } else {
47599 // parse possible constant values from description
47600 var myRe = /either\s+(?:[A-Z0-9_]+\s*,?\s*(?:or)?\s*)+/g;
47601 var values = {};
47602 var names = [];
47603
47604 constant = mapConstants[format.name] = {
47605 values: values,
47606 names: names
47607 };
47608
47609 var myArray = myRe.exec(format.description);
47610 if (func === 'endShape' && format.name === 'mode') {
47611 values[constants.CLOSE] = true;
47612 names.push('CLOSE');
47613 } else {
47614 var match = myArray[0];
47615 var reConst = /[A-Z0-9_]+/g;
47616 var matchConst;
47617 while ((matchConst = reConst.exec(match)) !== null) {
47618 var name = matchConst[0];
47619 if (constants.hasOwnProperty(name)) {
47620 values[constants[name]] = true;
47621 names.push(name);
47622 }
47623 }
47624 }
47625 }
47626 return {
47627 name: type,
47628 builtin: lowerType,
47629 names: constant.names,
47630 values: constant.values
47631 };
47632 }
47633
47634 // function
47635 if (lowerType.substr(0, 'function'.length) === 'function') {
47636 lowerType = 'function';
47637 }
47638 // builtin
47639 if (builtinTypes.has(lowerType)) {
47640 return { name: type, builtin: lowerType };
47641 }
47642
47643 // find type's prototype
47644 var t = window;
47645 var typeParts = type.split('.');
47646
47647 // special-case 'p5' since it may be non-global
47648 if (typeParts[0] === 'p5') {
47649 t = _main.default;
47650 typeParts.shift();
47651 }
47652
47653 typeParts.forEach(function(p) {
47654 t = t && t[p];
47655 });
47656 if (t) {
47657 return { name: type, prototype: t };
47658 }
47659
47660 return { name: type, type: lowerType };
47661 });
47662 });
47663 });
47664 return {
47665 overloads: overloads,
47666 maxParams: maxParams
47667 };
47668 };
47669
47670 var isNumber = function isNumber(param) {
47671 switch (_typeof(param)) {
47672 case 'number':
47673 return true;
47674 case 'string':
47675 return !isNaN(param);
47676 default:
47677 return false;
47678 }
47679 };
47680
47681 var testParamType = function testParamType(param, type) {
47682 var isArray = param instanceof Array;
47683 var matches = true;
47684 if (type.array && isArray) {
47685 for (var i = 0; i < param.length; i++) {
47686 var error = testParamType(param[i], type.array);
47687 if (error) return error / 2; // half error for elements
47688 }
47689 } else if (type.prototype) {
47690 matches = param instanceof type.prototype;
47691 } else if (type.builtin) {
47692 switch (type.builtin) {
47693 case 'number':
47694 matches = isNumber(param);
47695 break;
47696 case 'integer':
47697 matches = isNumber(param) && Number(param) === Math.floor(param);
47698 break;
47699 case 'boolean':
47700 case 'any':
47701 matches = true;
47702 break;
47703 case 'array':
47704 matches = isArray;
47705 break;
47706 case 'string':
47707 matches = /*typeof param === 'number' ||*/ typeof param === 'string';
47708 break;
47709 case 'constant':
47710 matches = type.values.hasOwnProperty(param);
47711 break;
47712 case 'function':
47713 matches = param instanceof Function;
47714 break;
47715 case 'null':
47716 matches = param === null;
47717 break;
47718 }
47719 } else {
47720 matches = _typeof(param) === type.t;
47721 }
47722 return matches ? 0 : 1;
47723 };
47724
47725 // testType() for non-object type parameter validation
47726 var testParamTypes = function testParamTypes(param, types) {
47727 var minScore = 9999;
47728 for (var i = 0; minScore > 0 && i < types.length; i++) {
47729 var score = testParamType(param, types[i]);
47730 if (minScore > score) minScore = score;
47731 }
47732 return minScore;
47733 };
47734
47735 // generate a score (higher is worse) for applying these args to
47736 // this overload.
47737 var scoreOverload = function scoreOverload(args, argCount, overload, minScore) {
47738 var score = 0;
47739 var formats = overload.formats;
47740 var minParams = overload.minParams;
47741
47742 // check for too few/many args
47743 // the score is double number of extra/missing args
47744 if (argCount < minParams) {
47745 score = (minParams - argCount) * 2;
47746 } else if (argCount > formats.length) {
47747 score = (argCount - formats.length) * 2;
47748 }
47749
47750 // loop through the formats, adding up the error score for each arg.
47751 // quit early if the score gets higher than the previous best overload.
47752 for (var p = 0; score <= minScore && p < formats.length; p++) {
47753 var arg = args[p];
47754 var format = formats[p];
47755 // '== null' checks for 'null' and typeof 'undefined'
47756 if (arg == null) {
47757 // handle undefined args
47758 if (!format.optional || p < minParams || p < argCount) {
47759 score += 1;
47760 }
47761 } else {
47762 score += testParamTypes(arg, format.types);
47763 }
47764 }
47765 return score;
47766 };
47767
47768 // gets a list of errors for this overload
47769 var getOverloadErrors = function getOverloadErrors(args, argCount, overload) {
47770 var formats = overload.formats;
47771 var minParams = overload.minParams;
47772
47773 // check for too few/many args
47774 if (argCount < minParams) {
47775 return [
47776 {
47777 type: 'TOO_FEW_ARGUMENTS',
47778 argCount: argCount,
47779 minParams: minParams
47780 }
47781 ];
47782 } else if (argCount > formats.length) {
47783 return [
47784 {
47785 type: 'TOO_MANY_ARGUMENTS',
47786 argCount: argCount,
47787 maxParams: formats.length
47788 }
47789 ];
47790 }
47791
47792 var errorArray = [];
47793 for (var p = 0; p < formats.length; p++) {
47794 var arg = args[p];
47795 var format = formats[p];
47796 // '== null' checks for 'null' and typeof 'undefined'
47797 if (arg == null) {
47798 // handle undefined args
47799 if (!format.optional || p < minParams || p < argCount) {
47800 errorArray.push({
47801 type: 'EMPTY_VAR',
47802 position: p,
47803 format: format
47804 });
47805 }
47806 } else if (testParamTypes(arg, format.types) > 0) {
47807 errorArray.push({
47808 type: 'WRONG_TYPE',
47809 position: p,
47810 format: format,
47811 arg: arg
47812 });
47813 }
47814 }
47815
47816 return errorArray;
47817 };
47818
47819 // a custom error type, used by the mocha
47820 // tests when expecting validation errors
47821 _main.default.ValidationError = (function(name) {
47822 var err = /*#__PURE__*/ (function(_Error) {
47823 _inherits(err, _Error);
47824 function err(message, func, type) {
47825 var _this;
47826 _classCallCheck(this, err);
47827 _this = _possibleConstructorReturn(this, _getPrototypeOf(err).call(this));
47828 _this.message = message;
47829 _this.func = func;
47830 _this.type = type;
47831 if ('captureStackTrace' in Error)
47832 Error.captureStackTrace(_assertThisInitialized(_this), err);
47833 else _this.stack = new Error().stack;
47834 return _this;
47835 }
47836 return err;
47837 })(_wrapNativeSuper(Error));
47838
47839 err.prototype.name = name;
47840 return err;
47841 })('ValidationError');
47842
47843 // function for generating console.log() msg
47844 _main.default._friendlyParamError = function(errorObj, func) {
47845 var message;
47846 var translationObj;
47847
47848 function formatType() {
47849 var format = errorObj.format;
47850 return format.types
47851 .map(function(type) {
47852 return type.names ? type.names.join('|') : type.name;
47853 })
47854 .join('|');
47855 }
47856
47857 switch (errorObj.type) {
47858 case 'EMPTY_VAR': {
47859 translationObj = {
47860 func: func,
47861 formatType: formatType(),
47862 // It needs to be this way for i18next-extract to work. The comment
47863 // specifies the values that the context can take so that it can
47864 // statically prepare the translation files with them.
47865 /* i18next-extract-mark-context-next-line ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"] */
47866 position: (0, _internationalization.translator)('fes.positions.p', {
47867 context: (errorObj.position + 1).toString(),
47868 defaultValue: (errorObj.position + 1).toString()
47869 }),
47870
47871 link: '[https://p5js.org/examples/data-variable-scope.html]'
47872 };
47873
47874 break;
47875 }
47876 case 'WRONG_TYPE': {
47877 var arg = errorObj.arg;
47878 var argType =
47879 arg instanceof Array
47880 ? 'array'
47881 : arg === null ? 'null' : arg.name || _typeof(arg);
47882
47883 translationObj = {
47884 func: func,
47885 formatType: formatType(),
47886 argType: argType,
47887 /* i18next-extract-mark-context-next-line ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"] */
47888 position: (0, _internationalization.translator)('fes.positions.p', {
47889 context: (errorObj.position + 1).toString(),
47890 defaultValue: (errorObj.position + 1).toString()
47891 })
47892 };
47893
47894 break;
47895 }
47896 case 'TOO_FEW_ARGUMENTS': {
47897 translationObj = {
47898 func: func,
47899 minParams: errorObj.minParams,
47900 argCount: errorObj.argCount
47901 };
47902
47903 break;
47904 }
47905 case 'TOO_MANY_ARGUMENTS': {
47906 translationObj = {
47907 func: func,
47908 maxParams: errorObj.maxParams,
47909 argCount: errorObj.argCount
47910 };
47911
47912 break;
47913 }
47914 }
47915
47916 if (translationObj) {
47917 try {
47918 // const re = /Function\.validateParameters.*[\r\n].*[\r\n].*\(([^)]*)/;
47919 var myError = new Error();
47920 var parsed = _main.default._getErrorStackParser().parse(myError);
47921 if (
47922 parsed[3] &&
47923 parsed[3].functionName &&
47924 parsed[3].functionName.includes('.') &&
47925 _main.default.prototype[parsed[3].functionName.split('.').slice(-1)[0]]
47926 ) {
47927 return;
47928 }
47929 if (_main.default._throwValidationErrors) {
47930 throw new _main.default.ValidationError(message, func, errorObj.type);
47931 }
47932
47933 // try to extract the location from where the function was called
47934 if (
47935 parsed[3] &&
47936 parsed[3].fileName &&
47937 parsed[3].lineNumber &&
47938 parsed[3].columnNumber
47939 ) {
47940 var location = ''
47941 .concat(parsed[3].fileName, ':')
47942 .concat(parsed[3].lineNumber, ':')
47943 .concat(parsed[3].columnNumber);
47944
47945 translationObj.location = (0, _internationalization.translator)(
47946 'fes.location',
47947 {
47948 location: location,
47949 // for e.g. get "sketch.js" from "https://example.com/abc/sketch.js"
47950 file: parsed[3].fileName.split('/').slice(-1),
47951 line: parsed[3].lineNumber
47952 }
47953 );
47954
47955 // tell fesErrorMonitor that we have already given a friendly message
47956 // for this line, so it need not to do the same in case of an error
47957 _main.default._fesLogCache[location] = true;
47958 }
47959 } catch (err) {
47960 if (err instanceof _main.default.ValidationError) {
47961 throw err;
47962 }
47963 }
47964
47965 translationObj.context = errorObj.type;
47966 // i18next-extract-mark-context-next-line ["EMPTY_VAR", "TOO_MANY_ARGUMENTS", "TOO_FEW_ARGUMENTS", "WRONG_TYPE"]
47967 message = (0, _internationalization.translator)(
47968 'fes.friendlyParamError.type',
47969 translationObj
47970 );
47971
47972 _main.default._friendlyError(''.concat(message, '.'), func, 3);
47973 }
47974 };
47975
47976 // if a function is called with some set of wrong arguments, and then called
47977 // again with the same set of arguments, the messages due to the second call
47978 // will be supressed. If two tests test on the same wrong arguments, the
47979 // second test won't see the validationError. clearing argumentTree solves it
47980 _main.default._clearValidateParamsCache = function clearValidateParamsCache() {
47981 for (
47982 var _i2 = 0, _Object$keys2 = Object.keys(argumentTree);
47983 _i2 < _Object$keys2.length;
47984 _i2++
47985 ) {
47986 var _key4 = _Object$keys2[_i2];
47987 delete argumentTree[_key4];
47988 }
47989 };
47990
47991 // allowing access to argumentTree for testing
47992 _main.default._getValidateParamsArgTree = function getValidateParamsArgTree() {
47993 return argumentTree;
47994 };
47995
47996 /**
47997 * Validates parameters
47998 * param {String} func the name of the function
47999 * param {Array} args user input arguments
48000 *
48001 * example:
48002 * const a;
48003 * ellipse(10,10,a,5);
48004 * console ouput:
48005 * "It looks like ellipse received an empty variable in spot #2."
48006 *
48007 * example:
48008 * ellipse(10,"foo",5,5);
48009 * console output:
48010 * "ellipse was expecting a number for parameter #1,
48011 * received "foo" instead."
48012 */
48013 _main.default._validateParameters = function validateParameters(func, args) {
48014 if (_main.default.disableFriendlyErrors) {
48015 return; // skip FES
48016 }
48017
48018 // query / build the argument type tree and check if this sequence
48019 // has already been seen before.
48020 var obj = buildArgTypeCache(func, args);
48021 if (obj.seen) {
48022 return;
48023 }
48024 // mark this sequence as seen
48025 obj.seen = true;
48026 // lookup the docs in the 'data.json' file
48027 var docs = docCache[func] || (docCache[func] = lookupParamDoc(func));
48028 var overloads = docs.overloads;
48029
48030 var argCount = args.length;
48031
48032 // the following line ignores trailing undefined arguments, commenting
48033 // it to resolve https://github.com/processing/p5.js/issues/4571
48034 // '== null' checks for 'null' and typeof 'undefined'
48035 // while (argCount > 0 && args[argCount - 1] == null) argCount--;
48036
48037 // find the overload with the best score
48038 var minScore = 99999;
48039 var minOverload;
48040 for (var i = 0; i < overloads.length; i++) {
48041 var score = scoreOverload(args, argCount, overloads[i], minScore);
48042 if (score === 0) {
48043 return; // done!
48044 } else if (minScore > score) {
48045 // this score is better that what we have so far...
48046 minScore = score;
48047 minOverload = i;
48048 }
48049 }
48050
48051 // this should _always_ be true here...
48052 if (minScore > 0) {
48053 // get the errors for the best overload
48054 var errorArray = getOverloadErrors(args, argCount, overloads[minOverload]);
48055
48056 // generate err msg
48057 for (var n = 0; n < errorArray.length; n++) {
48058 _main.default._friendlyParamError(errorArray[n], func);
48059 }
48060 }
48061 };
48062 _main.default.prototype._validateParameters = _main.default.validateParameters;
48063 }
48064 var _default = _main.default;
48065 exports.default = _default;
48066 },
48067 {
48068 '../../../docs/parameterData.json': 1,
48069 '../constants': 43,
48070 '../internationalization': 52,
48071 '../main': 54
48072 }
48073 ],
48074 50: [
48075 function(_dereq_, module, exports) {
48076 'use strict';
48077 function _typeof(obj) {
48078 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
48079 _typeof = function _typeof(obj) {
48080 return typeof obj;
48081 };
48082 } else {
48083 _typeof = function _typeof(obj) {
48084 return obj &&
48085 typeof Symbol === 'function' &&
48086 obj.constructor === Symbol &&
48087 obj !== Symbol.prototype
48088 ? 'symbol'
48089 : typeof obj;
48090 };
48091 }
48092 return _typeof(obj);
48093 }
48094 Object.defineProperty(exports, '__esModule', { value: true });
48095 exports.default = void 0;
48096
48097 var constants = _interopRequireWildcard(_dereq_('./constants'));
48098 function _getRequireWildcardCache() {
48099 if (typeof WeakMap !== 'function') return null;
48100 var cache = new WeakMap();
48101 _getRequireWildcardCache = function _getRequireWildcardCache() {
48102 return cache;
48103 };
48104 return cache;
48105 }
48106 function _interopRequireWildcard(obj) {
48107 if (obj && obj.__esModule) {
48108 return obj;
48109 }
48110 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) {
48111 return { default: obj };
48112 }
48113 var cache = _getRequireWildcardCache();
48114 if (cache && cache.has(obj)) {
48115 return cache.get(obj);
48116 }
48117 var newObj = {};
48118 var hasPropertyDescriptor =
48119 Object.defineProperty && Object.getOwnPropertyDescriptor;
48120 for (var key in obj) {
48121 if (Object.prototype.hasOwnProperty.call(obj, key)) {
48122 var desc = hasPropertyDescriptor
48123 ? Object.getOwnPropertyDescriptor(obj, key)
48124 : null;
48125 if (desc && (desc.get || desc.set)) {
48126 Object.defineProperty(newObj, key, desc);
48127 } else {
48128 newObj[key] = obj[key];
48129 }
48130 }
48131 }
48132 newObj.default = obj;
48133 if (cache) {
48134 cache.set(obj, newObj);
48135 }
48136 return newObj;
48137 }
48138 /**
48139 * @requires constants
48140 */ function modeAdjust(a, b, c, d, mode) {
48141 if (mode === constants.CORNER) {
48142 return { x: a, y: b, w: c, h: d };
48143 } else if (mode === constants.CORNERS) {
48144 return { x: a, y: b, w: c - a, h: d - b };
48145 } else if (mode === constants.RADIUS) {
48146 return { x: a - c, y: b - d, w: 2 * c, h: 2 * d };
48147 } else if (mode === constants.CENTER) {
48148 return { x: a - c * 0.5, y: b - d * 0.5, w: c, h: d };
48149 }
48150 }
48151 var _default = { modeAdjust: modeAdjust };
48152 exports.default = _default;
48153 },
48154 { './constants': 43 }
48155 ],
48156 51: [
48157 function(_dereq_, module, exports) {
48158 'use strict';
48159 var _main = _interopRequireDefault(_dereq_('../core/main'));
48160 var _internationalization = _dereq_('./internationalization');
48161 function _interopRequireDefault(obj) {
48162 return obj && obj.__esModule ? obj : { default: obj };
48163 }
48164
48165 /**
48166 * _globalInit
48167 *
48168 * TODO: ???
48169 * if sketch is on window
48170 * assume "global" mode
48171 * and instantiate p5 automatically
48172 * otherwise do nothing
48173 *
48174 * @private
48175 * @return {Undefined}
48176 */
48177 var _globalInit = function _globalInit() {
48178 // Could have been any property defined within the p5 constructor.
48179 // If that property is already a part of the global object,
48180 // this code has already run before, likely due to a duplicate import
48181 if (typeof window._setupDone !== 'undefined') {
48182 console.warn(
48183 'p5.js seems to have been imported multiple times. Please remove the duplicate import'
48184 );
48185
48186 return;
48187 }
48188
48189 if (!window.mocha) {
48190 // If there is a setup or draw function on the window
48191 // then instantiate p5 in "global" mode
48192 if (
48193 ((window.setup && typeof window.setup === 'function') ||
48194 (window.draw && typeof window.draw === 'function')) &&
48195 !_main.default.instance
48196 ) {
48197 new _main.default();
48198 }
48199 }
48200 };
48201
48202 // make a promise that resolves when the document is ready
48203 var waitForDocumentReady = function waitForDocumentReady() {
48204 return new Promise(function(resolve, reject) {
48205 // if the page is ready, initialize p5 immediately
48206 if (document.readyState === 'complete') {
48207 resolve();
48208 // if the page is still loading, add an event listener
48209 // and initialize p5 as soon as it finishes loading
48210 } else {
48211 window.addEventListener('load', resolve, false);
48212 }
48213 });
48214 };
48215
48216 // only load translations if we're using the full, un-minified library
48217 var waitingForTranslator =
48218 typeof IS_MINIFIED === 'undefined'
48219 ? (0, _internationalization.initialize)()
48220 : Promise.resolve();
48221
48222 Promise.all([waitForDocumentReady(), waitingForTranslator]).then(_globalInit);
48223 },
48224 { '../core/main': 54, './internationalization': 52 }
48225 ],
48226 52: [
48227 function(_dereq_, module, exports) {
48228 'use strict';
48229 Object.defineProperty(exports, '__esModule', { value: true });
48230 exports.initialize = exports.translator = void 0;
48231 var _i18next = _interopRequireDefault(_dereq_('i18next'));
48232 var _i18nextBrowserLanguagedetector = _interopRequireDefault(
48233 _dereq_('i18next-browser-languagedetector')
48234 );
48235 function _interopRequireDefault(obj) {
48236 return obj && obj.__esModule ? obj : { default: obj };
48237 }
48238
48239 var resources;
48240 // Do not include translations in the minified js
48241 if (typeof IS_MINIFIED === 'undefined') {
48242 resources = _dereq_('../../translations').default;
48243 }
48244
48245 /**
48246 * This is our translation function. Give it a key and
48247 * it will retreive the appropriate string
48248 * (within supported languages) according to the
48249 * user's browser's language settings.
48250 * @function translator
48251 * @param {String} key a key that corresponds to a message in our translation files
48252 * @param {Object} values values for use in the message under the given `key`
48253 * @returns {String} message (with values inserted) in the user's browser language
48254 * @private
48255 */
48256 var translator = function translator() {
48257 console.debug('p5.js translator called before translations were loaded');
48258 return '';
48259 };
48260 // (We'll set this to a real value in the init function below!)
48261
48262 /**
48263 * Set up our translation function, with loaded languages
48264 */ exports.translator = translator;
48265 var initialize = function initialize() {
48266 return new Promise(function(resolve, reject) {
48267 _i18next.default
48268 .use(_i18nextBrowserLanguagedetector.default)
48269 .init({
48270 fallbackLng: 'en',
48271 nestingPrefix: '$tr(',
48272 nestingSuffix: ')',
48273 defaultNS: 'translation',
48274 returnEmptyString: false,
48275 interpolation: {
48276 escapeValue: false
48277 },
48278
48279 detection: {
48280 checkWhitelist: false
48281 },
48282
48283 resources: resources
48284 })
48285 .then(
48286 function(translateFn) {
48287 exports.translator = translator = translateFn;
48288 resolve();
48289 },
48290 function(e) {
48291 return reject('Translations failed to load ('.concat(e, ')'));
48292 }
48293 );
48294 });
48295 };
48296 exports.initialize = initialize;
48297 },
48298 { '../../translations': 114, i18next: 30, 'i18next-browser-languagedetector': 27 }
48299 ],
48300 53: [
48301 function(_dereq_, module, exports) {
48302 'use strict';
48303 Object.defineProperty(exports, '__esModule', { value: true });
48304 exports.default = void 0;
48305
48306 var _main = _interopRequireDefault(_dereq_('./main'));
48307 function _interopRequireDefault(obj) {
48308 return obj && obj.__esModule ? obj : { default: obj };
48309 }
48310 /**
48311 * @for p5
48312 * @requires core
48313 * These are functions that are part of the Processing API but are not part of
48314 * the p5.js API. In some cases they have a new name, in others, they are
48315 * removed completely. Not all unsupported Processing functions are listed here
48316 * but we try to include ones that a user coming from Processing might likely
48317 * call.
48318 */ _main.default.prototype.pushStyle = function() {
48319 throw new Error('pushStyle() not used, see push()');
48320 };
48321 _main.default.prototype.popStyle = function() {
48322 throw new Error('popStyle() not used, see pop()');
48323 };
48324
48325 _main.default.prototype.popMatrix = function() {
48326 throw new Error('popMatrix() not used, see pop()');
48327 };
48328
48329 _main.default.prototype.pushMatrix = function() {
48330 throw new Error('pushMatrix() not used, see push()');
48331 };
48332 var _default = _main.default;
48333 exports.default = _default;
48334 },
48335 { './main': 54 }
48336 ],
48337 54: [
48338 function(_dereq_, module, exports) {
48339 'use strict';
48340 function _typeof(obj) {
48341 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
48342 _typeof = function _typeof(obj) {
48343 return typeof obj;
48344 };
48345 } else {
48346 _typeof = function _typeof(obj) {
48347 return obj &&
48348 typeof Symbol === 'function' &&
48349 obj.constructor === Symbol &&
48350 obj !== Symbol.prototype
48351 ? 'symbol'
48352 : typeof obj;
48353 };
48354 }
48355 return _typeof(obj);
48356 }
48357 Object.defineProperty(exports, '__esModule', { value: true });
48358 exports.default = void 0;
48359
48360 _dereq_('./shim');
48361
48362 var constants = _interopRequireWildcard(_dereq_('./constants'));
48363 function _getRequireWildcardCache() {
48364 if (typeof WeakMap !== 'function') return null;
48365 var cache = new WeakMap();
48366 _getRequireWildcardCache = function _getRequireWildcardCache() {
48367 return cache;
48368 };
48369 return cache;
48370 }
48371 function _interopRequireWildcard(obj) {
48372 if (obj && obj.__esModule) {
48373 return obj;
48374 }
48375 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) {
48376 return { default: obj };
48377 }
48378 var cache = _getRequireWildcardCache();
48379 if (cache && cache.has(obj)) {
48380 return cache.get(obj);
48381 }
48382 var newObj = {};
48383 var hasPropertyDescriptor =
48384 Object.defineProperty && Object.getOwnPropertyDescriptor;
48385 for (var key in obj) {
48386 if (Object.prototype.hasOwnProperty.call(obj, key)) {
48387 var desc = hasPropertyDescriptor
48388 ? Object.getOwnPropertyDescriptor(obj, key)
48389 : null;
48390 if (desc && (desc.get || desc.set)) {
48391 Object.defineProperty(newObj, key, desc);
48392 } else {
48393 newObj[key] = obj[key];
48394 }
48395 }
48396 }
48397 newObj.default = obj;
48398 if (cache) {
48399 cache.set(obj, newObj);
48400 }
48401 return newObj;
48402 }
48403 function _classCallCheck(instance, Constructor) {
48404 if (!(instance instanceof Constructor)) {
48405 throw new TypeError('Cannot call a class as a function');
48406 }
48407 }
48408 function _defineProperties(target, props) {
48409 for (var i = 0; i < props.length; i++) {
48410 var descriptor = props[i];
48411 descriptor.enumerable = descriptor.enumerable || false;
48412 descriptor.configurable = true;
48413 if ('value' in descriptor) descriptor.writable = true;
48414 Object.defineProperty(target, descriptor.key, descriptor);
48415 }
48416 }
48417 function _createClass(Constructor, protoProps, staticProps) {
48418 if (protoProps) _defineProperties(Constructor.prototype, protoProps);
48419 if (staticProps) _defineProperties(Constructor, staticProps);
48420 return Constructor;
48421 }
48422
48423 /**
48424 * This is the p5 instance constructor.
48425 *
48426 * A p5 instance holds all the properties and methods related to
48427 * a p5 sketch. It expects an incoming sketch closure and it can also
48428 * take an optional node parameter for attaching the generated p5 canvas
48429 * to a node. The sketch closure takes the newly created p5 instance as
48430 * its sole argument and may optionally set <a href="#/p5/preload">preload()</a>,
48431 * <a href="#/p5/setup">setup()</a>, and/or
48432 * <a href="#/p5/draw">draw()</a> properties on it for running a sketch.
48433 *
48434 * A p5 sketch can run in "global" or "instance" mode:
48435 * "global" - all properties and methods are attached to the window
48436 * "instance" - all properties and methods are bound to this p5 object
48437 *
48438 * @class p5
48439 * @constructor
48440 * @param {function} sketch a closure that can set optional <a href="#/p5/preload">preload()</a>,
48441 * <a href="#/p5/setup">setup()</a>, and/or <a href="#/p5/draw">draw()</a> properties on the
48442 * given p5 instance
48443 * @param {HTMLElement} [node] element to attach canvas to
48444 * @return {p5} a p5 instance
48445 */ var p5 = /*#__PURE__*/ (function() {
48446 function p5(sketch, node, sync) {
48447 var _this = this;
48448 _classCallCheck(this, p5);
48449 //////////////////////////////////////////////
48450 // PUBLIC p5 PROPERTIES AND METHODS
48451 //////////////////////////////////////////////
48452
48453 /**
48454 * Called directly before <a href="#/p5/setup">setup()</a>, the <a href="#/p5/preload">preload()</a> function is used to handle
48455 * asynchronous loading of external files in a blocking way. If a preload
48456 * function is defined, <a href="#/p5/setup">setup()</a> will wait until any load calls within have
48457 * finished. Nothing besides load calls (<a href="#/p5/loadImage">loadImage</a>, <a href="#/p5/loadJSON">loadJSON</a>, <a href="#/p5/loadFont">loadFont</a>,
48458 * <a href="#/p5/loadStrings">loadStrings</a>, etc.) should be inside the preload function. If asynchronous
48459 * loading is preferred, the load methods can instead be called in <a href="#/p5/setup">setup()</a>
48460 * or anywhere else with the use of a callback parameter.
48461 *
48462 * By default the text "loading..." will be displayed. To make your own
48463 * loading page, include an HTML element with id "p5_loading" in your
48464 * page. More information <a href="http://bit.ly/2kQ6Nio">here</a>.
48465 *
48466 * @method preload
48467 * @example
48468 * <div><code>
48469 * let img;
48470 * let c;
48471 * function preload() {
48472 * // preload() runs once
48473 * img = loadImage('assets/laDefense.jpg');
48474 * }
48475 *
48476 * function setup() {
48477 * // setup() waits until preload() is done
48478 * img.loadPixels();
48479 * // get color of middle pixel
48480 * c = img.get(img.width / 2, img.height / 2);
48481 * }
48482 *
48483 * function draw() {
48484 * background(c);
48485 * image(img, 25, 25, 50, 50);
48486 * }
48487 * </code></div>
48488 *
48489 * @alt
48490 * nothing displayed
48491 *
48492 */
48493
48494 /**
48495 * The <a href="#/p5/setup">setup()</a> function is called once when the program starts. It's used to
48496 * define initial environment properties such as screen size and background
48497 * color and to load media such as images and fonts as the program starts.
48498 * There can only be one <a href="#/p5/setup">setup()</a> function for each program and it shouldn't
48499 * be called again after its initial execution.
48500 *
48501 * Note: Variables declared within <a href="#/p5/setup">setup()</a> are not accessible within other
48502 * functions, including <a href="#/p5/draw">draw()</a>.
48503 *
48504 * @method setup
48505 * @example
48506 * <div><code>
48507 * let a = 0;
48508 *
48509 * function setup() {
48510 * background(0);
48511 * noStroke();
48512 * fill(102);
48513 * }
48514 *
48515 * function draw() {
48516 * rect(a++ % width, 10, 2, 80);
48517 * }
48518 * </code></div>
48519 *
48520 * @alt
48521 * nothing displayed
48522 *
48523 */
48524
48525 /**
48526 * Called directly after <a href="#/p5/setup">setup()</a>, the <a href="#/p5/draw">draw()</a> function continuously executes
48527 * the lines of code contained inside its block until the program is stopped
48528 * or <a href="#/p5/noLoop">noLoop()</a> is called. Note if <a href="#/p5/noLoop">noLoop()</a> is called in <a href="#/p5/setup">setup()</a>, <a href="#/p5/draw">draw()</a> will
48529 * still be executed once before stopping. <a href="#/p5/draw">draw()</a> is called automatically and
48530 * should never be called explicitly.
48531 *
48532 * It should always be controlled with <a href="#/p5/noLoop">noLoop()</a>, <a href="#/p5/redraw">redraw()</a> and <a href="#/p5/loop">loop()</a>. After
48533 * <a href="#/p5/noLoop">noLoop()</a> stops the code in <a href="#/p5/draw">draw()</a> from executing, <a href="#/p5/redraw">redraw()</a> causes the
48534 * code inside <a href="#/p5/draw">draw()</a> to execute once, and <a href="#/p5/loop">loop()</a> will cause the code
48535 * inside <a href="#/p5/draw">draw()</a> to resume executing continuously.
48536 *
48537 * The number of times <a href="#/p5/draw">draw()</a> executes in each second may be controlled with
48538 * the <a href="#/p5/frameRate">frameRate()</a> function.
48539 *
48540 * There can only be one <a href="#/p5/draw">draw()</a> function for each sketch, and <a href="#/p5/draw">draw()</a> must
48541 * exist if you want the code to run continuously, or to process events such
48542 * as <a href="#/p5/mousePressed">mousePressed()</a>. Sometimes, you might have an empty call to <a href="#/p5/draw">draw()</a> in
48543 * your program, as shown in the above example.
48544 *
48545 * It is important to note that the drawing coordinate system will be reset
48546 * at the beginning of each <a href="#/p5/draw">draw()</a> call. If any transformations are performed
48547 * within <a href="#/p5/draw">draw()</a> (ex: scale, rotate, translate), their effects will be
48548 * undone at the beginning of <a href="#/p5/draw">draw()</a>, so transformations will not accumulate
48549 * over time. On the other hand, styling applied (ex: fill, stroke, etc) will
48550 * remain in effect.
48551 *
48552 * @method draw
48553 * @example
48554 * <div><code>
48555 * let yPos = 0;
48556 * function setup() {
48557 * // setup() runs once
48558 * frameRate(30);
48559 * }
48560 * function draw() {
48561 * // draw() loops forever, until stopped
48562 * background(204);
48563 * yPos = yPos - 1;
48564 * if (yPos < 0) {
48565 * yPos = height;
48566 * }
48567 * line(0, yPos, width, yPos);
48568 * }
48569 * </code></div>
48570 *
48571 * @alt
48572 * nothing displayed
48573 *
48574 */
48575
48576 //////////////////////////////////////////////
48577 // PRIVATE p5 PROPERTIES AND METHODS
48578 //////////////////////////////////////////////
48579
48580 this._setupDone = false;
48581 // for handling hidpi
48582 this._pixelDensity = Math.ceil(window.devicePixelRatio) || 1;
48583 this._userNode = node;
48584 this._curElement = null;
48585 this._elements = [];
48586 this._glAttributes = null;
48587 this._requestAnimId = 0;
48588 this._preloadCount = 0;
48589 this._isGlobal = false;
48590 this._loop = true;
48591 this._initializeInstanceVariables();
48592 this._defaultCanvasSize = {
48593 width: 100,
48594 height: 100
48595 };
48596
48597 this._events = {
48598 // keep track of user-events for unregistering later
48599 mousemove: null,
48600 mousedown: null,
48601 mouseup: null,
48602 dragend: null,
48603 dragover: null,
48604 click: null,
48605 dblclick: null,
48606 mouseover: null,
48607 mouseout: null,
48608 keydown: null,
48609 keyup: null,
48610 keypress: null,
48611 touchstart: null,
48612 touchmove: null,
48613 touchend: null,
48614 resize: null,
48615 blur: null
48616 };
48617
48618 this._millisStart = -1;
48619
48620 // States used in the custom random generators
48621 this._lcg_random_state = null;
48622 this._gaussian_previous = false;
48623
48624 this._events.wheel = null;
48625 this._loadingScreenId = 'p5_loading';
48626
48627 // Allows methods to be registered on an instance that
48628 // are instance-specific.
48629 this._registeredMethods = {};
48630 var methods = Object.getOwnPropertyNames(p5.prototype._registeredMethods);
48631 var _iteratorNormalCompletion = true;
48632 var _didIteratorError = false;
48633 var _iteratorError = undefined;
48634 try {
48635 for (
48636 var _iterator = methods[Symbol.iterator](), _step;
48637 !(_iteratorNormalCompletion = (_step = _iterator.next()).done);
48638 _iteratorNormalCompletion = true
48639 ) {
48640 var prop = _step.value;
48641 this._registeredMethods[prop] = p5.prototype._registeredMethods[
48642 prop
48643 ].slice();
48644 }
48645 } catch (err) {
48646 _didIteratorError = true;
48647 _iteratorError = err;
48648 } finally {
48649 try {
48650 if (!_iteratorNormalCompletion && _iterator.return != null) {
48651 _iterator.return();
48652 }
48653 } finally {
48654 if (_didIteratorError) {
48655 throw _iteratorError;
48656 }
48657 }
48658 }
48659
48660 if (window.DeviceOrientationEvent) {
48661 this._events.deviceorientation = null;
48662 }
48663 if (window.DeviceMotionEvent && !window._isNodeWebkit) {
48664 this._events.devicemotion = null;
48665 }
48666
48667 this._start = function() {
48668 // Find node if id given
48669 if (_this._userNode) {
48670 if (typeof _this._userNode === 'string') {
48671 _this._userNode = document.getElementById(_this._userNode);
48672 }
48673 }
48674
48675 var context = _this._isGlobal ? window : _this;
48676 var userPreload = context.preload;
48677 if (userPreload) {
48678 // Setup loading screen
48679 // Set loading screen into dom if not present
48680 // Otherwise displays and removes user provided loading screen
48681 var loadingScreen = document.getElementById(_this._loadingScreenId);
48682 if (!loadingScreen) {
48683 loadingScreen = document.createElement('div');
48684 loadingScreen.innerHTML = 'Loading...';
48685 loadingScreen.style.position = 'absolute';
48686 loadingScreen.id = _this._loadingScreenId;
48687 var _node = _this._userNode || document.body;
48688 _node.appendChild(loadingScreen);
48689 }
48690 var _methods = _this._preloadMethods;
48691 for (var method in _methods) {
48692 // default to p5 if no object defined
48693 _methods[method] = _methods[method] || p5;
48694 var obj = _methods[method];
48695 //it's p5, check if it's global or instance
48696 if (obj === p5.prototype || obj === p5) {
48697 if (_this._isGlobal) {
48698 window[method] = _this._wrapPreload(_this, method);
48699 }
48700 obj = _this;
48701 }
48702 _this._registeredPreloadMethods[method] = obj[method];
48703 obj[method] = _this._wrapPreload(obj, method);
48704 }
48705
48706 userPreload();
48707 _this._runIfPreloadsAreDone();
48708 } else {
48709 _this._setup();
48710 _this._draw();
48711 }
48712 };
48713
48714 this._runIfPreloadsAreDone = function() {
48715 var context = this._isGlobal ? window : this;
48716 if (context._preloadCount === 0) {
48717 var loadingScreen = document.getElementById(context._loadingScreenId);
48718 if (loadingScreen) {
48719 loadingScreen.parentNode.removeChild(loadingScreen);
48720 }
48721 this._lastFrameTime = window.performance.now();
48722 context._setup();
48723 context._draw();
48724 }
48725 };
48726
48727 this._decrementPreload = function() {
48728 var context = this._isGlobal ? window : this;
48729 if (typeof context.preload === 'function') {
48730 context._setProperty('_preloadCount', context._preloadCount - 1);
48731 context._runIfPreloadsAreDone();
48732 }
48733 };
48734
48735 this._wrapPreload = function(obj, fnName) {
48736 var _this2 = this;
48737 return function() {
48738 //increment counter
48739 _this2._incrementPreload();
48740 //call original function
48741 for (
48742 var _len = arguments.length, args = new Array(_len), _key = 0;
48743 _key < _len;
48744 _key++
48745 ) {
48746 args[_key] = arguments[_key];
48747 }
48748 return _this2._registeredPreloadMethods[fnName].apply(obj, args);
48749 };
48750 };
48751
48752 this._incrementPreload = function() {
48753 var context = this._isGlobal ? window : this;
48754 context._setProperty('_preloadCount', context._preloadCount + 1);
48755 };
48756
48757 this._setup = function() {
48758 // Always create a default canvas.
48759 // Later on if the user calls createCanvas, this default one
48760 // will be replaced
48761 _this.createCanvas(
48762 _this._defaultCanvasSize.width,
48763 _this._defaultCanvasSize.height,
48764 'p2d'
48765 );
48766
48767 // return preload functions to their normal vals if switched by preload
48768 var context = _this._isGlobal ? window : _this;
48769 if (typeof context.preload === 'function') {
48770 for (var f in _this._preloadMethods) {
48771 context[f] = _this._preloadMethods[f][f];
48772 if (context[f] && _this) {
48773 context[f] = context[f].bind(_this);
48774 }
48775 }
48776 }
48777
48778 // Record the time when sketch starts
48779 _this._millisStart = window.performance.now();
48780
48781 // Short-circuit on this, in case someone used the library in "global"
48782 // mode earlier
48783 if (typeof context.setup === 'function') {
48784 context.setup();
48785 }
48786
48787 // unhide any hidden canvases that were created
48788 var canvases = document.getElementsByTagName('canvas');
48789 var _iteratorNormalCompletion2 = true;
48790 var _didIteratorError2 = false;
48791 var _iteratorError2 = undefined;
48792 try {
48793 for (
48794 var _iterator2 = canvases[Symbol.iterator](), _step2;
48795 !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done);
48796 _iteratorNormalCompletion2 = true
48797 ) {
48798 var k = _step2.value;
48799 if (k.dataset.hidden === 'true') {
48800 k.style.visibility = '';
48801 delete k.dataset.hidden;
48802 }
48803 }
48804 } catch (err) {
48805 _didIteratorError2 = true;
48806 _iteratorError2 = err;
48807 } finally {
48808 try {
48809 if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
48810 _iterator2.return();
48811 }
48812 } finally {
48813 if (_didIteratorError2) {
48814 throw _iteratorError2;
48815 }
48816 }
48817 }
48818
48819 _this._lastFrameTime = window.performance.now();
48820 _this._setupDone = true;
48821 };
48822
48823 this._draw = function() {
48824 var now = window.performance.now();
48825 var time_since_last = now - _this._lastFrameTime;
48826 var target_time_between_frames = 1000 / _this._targetFrameRate;
48827
48828 // only draw if we really need to; don't overextend the browser.
48829 // draw if we're within 5ms of when our next frame should paint
48830 // (this will prevent us from giving up opportunities to draw
48831 // again when it's really about time for us to do so). fixes an
48832 // issue where the frameRate is too low if our refresh loop isn't
48833 // in sync with the browser. note that we have to draw once even
48834 // if looping is off, so we bypass the time delay if that
48835 // is the case.
48836 var epsilon = 5;
48837 if (
48838 !_this._loop ||
48839 time_since_last >= target_time_between_frames - epsilon
48840 ) {
48841 //mandatory update values(matrixs and stack)
48842 _this.redraw();
48843 _this._frameRate = 1000.0 / (now - _this._lastFrameTime);
48844 _this.deltaTime = now - _this._lastFrameTime;
48845 _this._setProperty('deltaTime', _this.deltaTime);
48846 _this._lastFrameTime = now;
48847
48848 // If the user is actually using mouse module, then update
48849 // coordinates, otherwise skip. We can test this by simply
48850 // checking if any of the mouse functions are available or not.
48851 // NOTE : This reflects only in complete build or modular build.
48852 if (typeof _this._updateMouseCoords !== 'undefined') {
48853 _this._updateMouseCoords();
48854
48855 //reset delta values so they reset even if there is no mouse event to set them
48856 // for example if the mouse is outside the screen
48857 _this._setProperty('movedX', 0);
48858 _this._setProperty('movedY', 0);
48859 }
48860 }
48861
48862 // get notified the next time the browser gives us
48863 // an opportunity to draw.
48864 if (_this._loop) {
48865 _this._requestAnimId = window.requestAnimationFrame(_this._draw);
48866 }
48867 };
48868
48869 this._setProperty = function(prop, value) {
48870 _this[prop] = value;
48871 if (_this._isGlobal) {
48872 window[prop] = value;
48873 }
48874 };
48875
48876 /**
48877 * Removes the entire p5 sketch. This will remove the canvas and any
48878 * elements created by p5.js. It will also stop the draw loop and unbind
48879 * any properties or methods from the window global scope. It will
48880 * leave a variable p5 in case you wanted to create a new p5 sketch.
48881 * If you like, you can set p5 = null to erase it. While all functions and
48882 * variables and objects created by the p5 library will be removed, any
48883 * other global variables created by your code will remain.
48884 *
48885 * @method remove
48886 * @example
48887 * <div class='norender'><code>
48888 * function draw() {
48889 * ellipse(50, 50, 10, 10);
48890 * }
48891 *
48892 * function mousePressed() {
48893 * remove(); // remove whole sketch on mouse press
48894 * }
48895 * </code></div>
48896 *
48897 * @alt
48898 * nothing displayed
48899 *
48900 */
48901 this.remove = function() {
48902 var loadingScreen = document.getElementById(_this._loadingScreenId);
48903 if (loadingScreen) {
48904 loadingScreen.parentNode.removeChild(loadingScreen);
48905 // Add 1 to preload counter to prevent the sketch ever executing setup()
48906 _this._incrementPreload();
48907 }
48908 if (_this._curElement) {
48909 // stop draw
48910 _this._loop = false;
48911 if (_this._requestAnimId) {
48912 window.cancelAnimationFrame(_this._requestAnimId);
48913 }
48914
48915 // unregister events sketch-wide
48916 for (var ev in _this._events) {
48917 window.removeEventListener(ev, _this._events[ev]);
48918 }
48919
48920 // remove DOM elements created by p5, and listeners
48921 var _iteratorNormalCompletion3 = true;
48922 var _didIteratorError3 = false;
48923 var _iteratorError3 = undefined;
48924 try {
48925 for (
48926 var _iterator3 = _this._elements[Symbol.iterator](), _step3;
48927 !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done);
48928 _iteratorNormalCompletion3 = true
48929 ) {
48930 var e = _step3.value;
48931 if (e.elt && e.elt.parentNode) {
48932 e.elt.parentNode.removeChild(e.elt);
48933 }
48934 for (var elt_ev in e._events) {
48935 e.elt.removeEventListener(elt_ev, e._events[elt_ev]);
48936 }
48937 }
48938
48939 // call any registered remove functions
48940 } catch (err) {
48941 _didIteratorError3 = true;
48942 _iteratorError3 = err;
48943 } finally {
48944 try {
48945 if (!_iteratorNormalCompletion3 && _iterator3.return != null) {
48946 _iterator3.return();
48947 }
48948 } finally {
48949 if (_didIteratorError3) {
48950 throw _iteratorError3;
48951 }
48952 }
48953 }
48954 var self = _this;
48955 _this._registeredMethods.remove.forEach(function(f) {
48956 if (typeof f !== 'undefined') {
48957 f.call(self);
48958 }
48959 });
48960 }
48961 // remove window bound properties and methods
48962 if (_this._isGlobal) {
48963 for (var p in p5.prototype) {
48964 try {
48965 delete window[p];
48966 } catch (x) {
48967 window[p] = undefined;
48968 }
48969 }
48970 for (var p2 in _this) {
48971 if (_this.hasOwnProperty(p2)) {
48972 try {
48973 delete window[p2];
48974 } catch (x) {
48975 window[p2] = undefined;
48976 }
48977 }
48978 }
48979 p5.instance = null;
48980 }
48981 };
48982
48983 // call any registered init functions
48984 this._registeredMethods.init.forEach(function(f) {
48985 if (typeof f !== 'undefined') {
48986 f.call(this);
48987 }
48988 }, this);
48989 // Set up promise preloads
48990 this._setupPromisePreloads();
48991
48992 var friendlyBindGlobal = this._createFriendlyGlobalFunctionBinder();
48993
48994 // If the user has created a global setup or draw function,
48995 // assume "global" mode and make everything global (i.e. on the window)
48996 if (!sketch) {
48997 this._isGlobal = true;
48998 p5.instance = this;
48999 // Loop through methods on the prototype and attach them to the window
49000 for (var p in p5.prototype) {
49001 if (typeof p5.prototype[p] === 'function') {
49002 var ev = p.substring(2);
49003 if (!this._events.hasOwnProperty(ev)) {
49004 if (Math.hasOwnProperty(p) && Math[p] === p5.prototype[p]) {
49005 // Multiple p5 methods are just native Math functions. These can be
49006 // called without any binding.
49007 friendlyBindGlobal(p, p5.prototype[p]);
49008 } else {
49009 friendlyBindGlobal(p, p5.prototype[p].bind(this));
49010 }
49011 }
49012 } else {
49013 friendlyBindGlobal(p, p5.prototype[p]);
49014 }
49015 }
49016 // Attach its properties to the window
49017 for (var p2 in this) {
49018 if (this.hasOwnProperty(p2)) {
49019 friendlyBindGlobal(p2, this[p2]);
49020 }
49021 }
49022 } else {
49023 // Else, the user has passed in a sketch closure that may set
49024 // user-provided 'setup', 'draw', etc. properties on this instance of p5
49025 sketch(this);
49026
49027 // Run a check to see if the user has misspelled 'setup', 'draw', etc
49028 // detects capitalization mistakes only ( Setup, SETUP, MouseClicked, etc)
49029 p5._checkForUserDefinedFunctions(this);
49030 }
49031
49032 // Bind events to window (not using container div bc key events don't work)
49033
49034 for (var e in this._events) {
49035 var f = this['_on'.concat(e)];
49036 if (f) {
49037 var m = f.bind(this);
49038 window.addEventListener(e, m, { passive: false });
49039 this._events[e] = m;
49040 }
49041 }
49042
49043 var focusHandler = function focusHandler() {
49044 _this._setProperty('focused', true);
49045 };
49046 var blurHandler = function blurHandler() {
49047 _this._setProperty('focused', false);
49048 };
49049 window.addEventListener('focus', focusHandler);
49050 window.addEventListener('blur', blurHandler);
49051 this.registerMethod('remove', function() {
49052 window.removeEventListener('focus', focusHandler);
49053 window.removeEventListener('blur', blurHandler);
49054 });
49055
49056 if (document.readyState === 'complete') {
49057 this._start();
49058 } else {
49059 window.addEventListener('load', this._start.bind(this), false);
49060 }
49061 }
49062 _createClass(p5, [
49063 {
49064 key: '_initializeInstanceVariables',
49065 value: function _initializeInstanceVariables() {
49066 this._styles = [];
49067
49068 this._bezierDetail = 20;
49069 this._curveDetail = 20;
49070
49071 this._colorMode = constants.RGB;
49072 this._colorMaxes = {
49073 rgb: [255, 255, 255, 255],
49074 hsb: [360, 100, 100, 1],
49075 hsl: [360, 100, 100, 1]
49076 };
49077
49078 this._downKeys = {}; //Holds the key codes of currently pressed keys
49079 }
49080 },
49081 {
49082 key: 'registerPreloadMethod',
49083 value: function registerPreloadMethod(fnString, obj) {
49084 // obj = obj || p5.prototype;
49085 if (!p5.prototype._preloadMethods.hasOwnProperty(fnString)) {
49086 p5.prototype._preloadMethods[fnString] = obj;
49087 }
49088 }
49089 },
49090 {
49091 key: 'registerMethod',
49092 value: function registerMethod(name, m) {
49093 var target = this || p5.prototype;
49094 if (!target._registeredMethods.hasOwnProperty(name)) {
49095 target._registeredMethods[name] = [];
49096 }
49097 target._registeredMethods[name].push(m);
49098 }
49099
49100 // create a function which provides a standardized process for binding
49101 // globals; this is implemented as a factory primarily so that there's a
49102 // way to redefine what "global" means for the binding function so it
49103 // can be used in scenarios like unit testing where the window object
49104 // might not exist
49105 },
49106 {
49107 key: '_createFriendlyGlobalFunctionBinder',
49108 value: function _createFriendlyGlobalFunctionBinder() {
49109 var options =
49110 arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
49111 var globalObject = options.globalObject || window;
49112 var log = options.log || console.log.bind(console);
49113 var propsToForciblyOverwrite = {
49114 // p5.print actually always overwrites an existing global function,
49115 // albeit one that is very unlikely to be used:
49116 //
49117 // https://developer.mozilla.org/en-US/docs/Web/API/Window/print
49118 print: true
49119 };
49120
49121 return function(prop, value) {
49122 if (
49123 !p5.disableFriendlyErrors &&
49124 typeof IS_MINIFIED === 'undefined' &&
49125 typeof value === 'function' &&
49126 !(prop in p5.prototype._preloadMethods)
49127 ) {
49128 try {
49129 // Because p5 has so many common function names, it's likely
49130 // that users may accidentally overwrite global p5 functions with
49131 // their own variables. Let's allow this but log a warning to
49132 // help users who may be doing this unintentionally.
49133 //
49134 // For more information, see:
49135 //
49136 // https://github.com/processing/p5.js/issues/1317
49137
49138 if (prop in globalObject && !(prop in propsToForciblyOverwrite)) {
49139 throw new Error('global "'.concat(prop, '" already exists'));
49140 }
49141
49142 // It's possible that this might throw an error because there
49143 // are a lot of edge-cases in which `Object.defineProperty` might
49144 // not succeed; since this functionality is only intended to
49145 // help beginners anyways, we'll just catch such an exception
49146 // if it occurs, and fall back to legacy behavior.
49147 Object.defineProperty(globalObject, prop, {
49148 configurable: true,
49149 enumerable: true,
49150 get: function get() {
49151 return value;
49152 },
49153 set: function set(newValue) {
49154 Object.defineProperty(globalObject, prop, {
49155 configurable: true,
49156 enumerable: true,
49157 value: newValue,
49158 writable: true
49159 });
49160
49161 log(
49162 'You just changed the value of "'.concat(
49163 prop,
49164 '", which was a p5 function. This could cause problems later if you\'re not careful.'
49165 )
49166 );
49167 }
49168 });
49169 } catch (e) {
49170 log(
49171 'p5 had problems creating the global function "'.concat(
49172 prop,
49173 '", possibly because your code is already using that name as a variable. You may want to rename your variable to something else.'
49174 )
49175 );
49176
49177 globalObject[prop] = value;
49178 }
49179 } else {
49180 globalObject[prop] = value;
49181 }
49182 };
49183 }
49184 }
49185 ]);
49186 return p5;
49187 })();
49188
49189 // This is a pointer to our global mode p5 instance, if we're in
49190 // global mode.
49191 p5.instance = null;
49192
49193 /**
49194 * Allows for the friendly error system (FES) to be turned off when creating a sketch,
49195 * which can give a significant boost to performance when needed.
49196 * See <a href='https://github.com/processing/p5.js/wiki/Optimizing-p5.js-Code-for-Performance#disable-the-friendly-error-system-fes'>
49197 * disabling the friendly error system</a>.
49198 *
49199 * @property {Boolean} disableFriendlyErrors
49200 * @example
49201 * <div class="norender notest"><code>
49202 * p5.disableFriendlyErrors = true;
49203 *
49204 * function setup() {
49205 * createCanvas(100, 50);
49206 * }
49207 * </code></div>
49208 */
49209 p5.disableFriendlyErrors = false;
49210
49211 // attach constants to p5 prototype
49212 for (var k in constants) {
49213 p5.prototype[k] = constants[k];
49214 }
49215
49216 // functions that cause preload to wait
49217 // more can be added by using registerPreloadMethod(func)
49218 p5.prototype._preloadMethods = {
49219 loadJSON: p5.prototype,
49220 loadImage: p5.prototype,
49221 loadStrings: p5.prototype,
49222 loadXML: p5.prototype,
49223 loadBytes: p5.prototype,
49224 loadTable: p5.prototype,
49225 loadFont: p5.prototype,
49226 loadModel: p5.prototype,
49227 loadShader: p5.prototype
49228 };
49229
49230 p5.prototype._registeredMethods = { init: [], pre: [], post: [], remove: [] };
49231
49232 p5.prototype._registeredPreloadMethods = {};
49233 var _default = p5;
49234 exports.default = _default;
49235 },
49236 { './constants': 43, './shim': 65 }
49237 ],
49238 55: [
49239 function(_dereq_, module, exports) {
49240 'use strict';
49241 Object.defineProperty(exports, '__esModule', { value: true });
49242 exports.default = void 0;
49243
49244 var _main = _interopRequireDefault(_dereq_('./main'));
49245 function _interopRequireDefault(obj) {
49246 return obj && obj.__esModule ? obj : { default: obj };
49247 }
49248 /**
49249 * @module DOM
49250 * @submodule DOM
49251 * @for p5.Element
49252 */ /**
49253 * Base class for all elements added to a sketch, including canvas,
49254 * graphics buffers, and other HTML elements. It is not called directly, but <a href="#/p5.Element">p5.Element</a>
49255 * objects are created by calling <a href="#/p5/createCanvas">createCanvas</a>, <a href="#/p5/createGraphics">createGraphics</a>,
49256 * <a href="#/p5/createDiv">createDiv</a>, <a href="#/p5/createImg">createImg</a>, <a href="#/p5/createInput">createInput</a>, etc.
49257 *
49258 * @class p5.Element
49259 * @constructor
49260 * @param {String} elt DOM node that is wrapped
49261 * @param {p5} [pInst] pointer to p5 instance
49262 */ _main.default.Element = function(elt, pInst) {
49263 /**
49264 * Underlying HTML element. All normal HTML methods can be called on this.
49265 * @example
49266 * <div>
49267 * <code>
49268 * function setup() {
49269 * let c = createCanvas(50, 50);
49270 * c.elt.style.border = '5px solid red';
49271 * }
49272 *
49273 * function draw() {
49274 * background(220);
49275 * }
49276 * </code>
49277 * </div>
49278 *
49279 * @property elt
49280 * @readOnly
49281 */
49282 this.elt = elt;
49283 this._pInst = this._pixelsState = pInst;
49284 this._events = {};
49285 this.width = this.elt.offsetWidth;
49286 this.height = this.elt.offsetHeight;
49287 };
49288
49289 /**
49290 *
49291 * Attaches the element to the parent specified. A way of setting
49292 * the container for the element. Accepts either a string ID, DOM
49293 * node, or <a href="#/p5.Element">p5.Element</a>. If no arguments given, parent node is returned.
49294 * For more ways to position the canvas, see the
49295 * <a href='https://github.com/processing/p5.js/wiki/Positioning-your-canvas'>
49296 * positioning the canvas</a> wiki page.
49297 *
49298 * @method parent
49299 * @param {String|p5.Element|Object} parent the ID, DOM node, or <a href="#/p5.Element">p5.Element</a>
49300 * of desired parent element
49301 * @chainable
49302 *
49303 * @example
49304 * <div class="norender notest"><code>
49305 * // Add the following comment to html file.
49306 * // &lt;div id="myContainer">&lt;/div>
49307 *
49308 * // The js code
49309 * let cnv = createCanvas(100, 100);
49310 * cnv.parent('myContainer');
49311 * </code></div>
49312 *
49313 * <div class='norender'><code>
49314 * let div0 = createDiv('this is the parent');
49315 * let div1 = createDiv('this is the child');
49316 * div1.parent(div0); // use p5.Element
49317 * </code></div>
49318 *
49319 * <div class='norender'><code>
49320 * let div0 = createDiv('this is the parent');
49321 * div0.id('apples');
49322 * let div1 = createDiv('this is the child');
49323 * div1.parent('apples'); // use id
49324 * </code></div>
49325 *
49326 * <div class='norender notest'><code>
49327 * let elt = document.getElementById('myParentDiv');
49328 * let div1 = createDiv('this is the child');
49329 * div1.parent(elt); // use element from page
49330 * </code></div>
49331 *
49332 * @alt
49333 * no display.
49334 */
49335 /**
49336 * @method parent
49337 * @return {p5.Element}
49338 */
49339 _main.default.Element.prototype.parent = function(p) {
49340 if (typeof p === 'undefined') {
49341 return this.elt.parentNode;
49342 }
49343
49344 if (typeof p === 'string') {
49345 if (p[0] === '#') {
49346 p = p.substring(1);
49347 }
49348 p = document.getElementById(p);
49349 } else if (p instanceof _main.default.Element) {
49350 p = p.elt;
49351 }
49352 p.appendChild(this.elt);
49353 return this;
49354 };
49355
49356 /**
49357 *
49358 * Sets the ID of the element. If no ID argument is passed in, it instead
49359 * returns the current ID of the element.
49360 * Note that only one element can have a particular id in a page.
49361 * The <a href="#/p5.Element/class">.class()</a> function can be used
49362 * to identify multiple elements with the same class name.
49363 *
49364 * @method id
49365 * @param {String} id ID of the element
49366 * @chainable
49367 *
49368 * @example
49369 * <div class='norender'><code>
49370 * function setup() {
49371 * let cnv = createCanvas(100, 100);
49372 * // Assigns a CSS selector ID to
49373 * // the canvas element.
49374 * cnv.id('mycanvas');
49375 * }
49376 * </code></div>
49377 *
49378 * @alt
49379 * no display.
49380 */
49381 /**
49382 * @method id
49383 * @return {String} the id of the element
49384 */
49385 _main.default.Element.prototype.id = function(id) {
49386 if (typeof id === 'undefined') {
49387 return this.elt.id;
49388 }
49389
49390 this.elt.id = id;
49391 this.width = this.elt.offsetWidth;
49392 this.height = this.elt.offsetHeight;
49393 return this;
49394 };
49395
49396 /**
49397 *
49398 * Adds given class to the element. If no class argument is passed in, it
49399 * instead returns a string containing the current class(es) of the element.
49400 *
49401 * @method class
49402 * @param {String} class class to add
49403 * @chainable
49404 *
49405 * @example
49406 * <div class='norender'><code>
49407 * function setup() {
49408 * let cnv = createCanvas(100, 100);
49409 * // Assigns a CSS selector class 'small'
49410 * // to the canvas element.
49411 * cnv.class('small');
49412 * }
49413 * </code></div>
49414 *
49415 * @alt
49416 * no display.
49417 */
49418 /**
49419 * @method class
49420 * @return {String} the class of the element
49421 */
49422 _main.default.Element.prototype.class = function(c) {
49423 if (typeof c === 'undefined') {
49424 return this.elt.className;
49425 }
49426
49427 this.elt.className = c;
49428 return this;
49429 };
49430
49431 /**
49432 * The .<a href="#/p5.Element/mousePressed">mousePressed()</a> function is called
49433 * once after every time a mouse button is pressed over the element. Some mobile
49434 * browsers may also trigger this event on a touch screen, if the user performs
49435 * a quick tap. This can be used to attach element specific event listeners.
49436 *
49437 * @method mousePressed
49438 * @param {Function|Boolean} fxn function to be fired when mouse is
49439 * pressed over the element.
49440 * if `false` is passed instead, the previously
49441 * firing function will no longer fire.
49442 * @chainable
49443 * @example
49444 * <div class='norender'><code>
49445 * let cnv, d, g;
49446 * function setup() {
49447 * cnv = createCanvas(100, 100);
49448 * cnv.mousePressed(changeGray); // attach listener for
49449 * // canvas click only
49450 * d = 10;
49451 * g = 100;
49452 * }
49453 *
49454 * function draw() {
49455 * background(g);
49456 * ellipse(width / 2, height / 2, d, d);
49457 * }
49458 *
49459 * // this function fires with any click anywhere
49460 * function mousePressed() {
49461 * d = d + 10;
49462 * }
49463 *
49464 * // this function fires only when cnv is clicked
49465 * function changeGray() {
49466 * g = random(0, 255);
49467 * }
49468 * </code></div>
49469 *
49470 * @alt
49471 * no display.
49472 */
49473 _main.default.Element.prototype.mousePressed = function(fxn) {
49474 // Prepend the mouse property setters to the event-listener.
49475 // This is required so that mouseButton is set correctly prior to calling the callback (fxn).
49476 // For details, see https://github.com/processing/p5.js/issues/3087.
49477 var eventPrependedFxn = function eventPrependedFxn(event) {
49478 this._pInst._setProperty('mouseIsPressed', true);
49479 this._pInst._setMouseButton(event);
49480 // Pass along the return-value of the callback:
49481 return fxn.call(this);
49482 };
49483 // Pass along the event-prepended form of the callback.
49484 _main.default.Element._adjustListener('mousedown', eventPrependedFxn, this);
49485 return this;
49486 };
49487
49488 /**
49489 * The .<a href="#/p5.Element/doubleClicked">doubleClicked()</a> function is called once after every time a
49490 * mouse button is pressed twice over the element. This can be used to
49491 * attach element and action specific event listeners.
49492 *
49493 * @method doubleClicked
49494 * @param {Function|Boolean} fxn function to be fired when mouse is
49495 * double clicked over the element.
49496 * if `false` is passed instead, the previously
49497 * firing function will no longer fire.
49498 * @return {p5.Element}
49499 * @example
49500 * <div class='norender'><code>
49501 * let cnv, d, g;
49502 * function setup() {
49503 * cnv = createCanvas(100, 100);
49504 * cnv.doubleClicked(changeGray); // attach listener for
49505 * // canvas double click only
49506 * d = 10;
49507 * g = 100;
49508 * }
49509 *
49510 * function draw() {
49511 * background(g);
49512 * ellipse(width / 2, height / 2, d, d);
49513 * }
49514 *
49515 * // this function fires with any double click anywhere
49516 * function doubleClicked() {
49517 * d = d + 10;
49518 * }
49519 *
49520 * // this function fires only when cnv is double clicked
49521 * function changeGray() {
49522 * g = random(0, 255);
49523 * }
49524 * </code></div>
49525 *
49526 * @alt
49527 * no display.
49528 */
49529 _main.default.Element.prototype.doubleClicked = function(fxn) {
49530 _main.default.Element._adjustListener('dblclick', fxn, this);
49531 return this;
49532 };
49533
49534 /**
49535 * The <a href="#/p5.Element/mouseWheel">mouseWheel()</a> function is called
49536 * once after every time a mouse wheel is scrolled over the element. This can
49537 * be used to attach element specific event listeners.
49538 *
49539 * The function accepts a callback function as argument which will be executed
49540 * when the `wheel` event is triggered on the element, the callback function is
49541 * passed one argument `event`. The `event.deltaY` property returns negative
49542 * values if the mouse wheel is rotated up or away from the user and positive
49543 * in the other direction. The `event.deltaX` does the same as `event.deltaY`
49544 * except it reads the horizontal wheel scroll of the mouse wheel.
49545 *
49546 * On OS X with "natural" scrolling enabled, the `event.deltaY` values are
49547 * reversed.
49548 *
49549 * @method mouseWheel
49550 * @param {Function|Boolean} fxn function to be fired when mouse is
49551 * scrolled over the element.
49552 * if `false` is passed instead, the previously
49553 * firing function will no longer fire.
49554 * @chainable
49555 * @example
49556 * <div class='norender'><code>
49557 * let cnv, d, g;
49558 * function setup() {
49559 * cnv = createCanvas(100, 100);
49560 * cnv.mouseWheel(changeSize); // attach listener for
49561 * // activity on canvas only
49562 * d = 10;
49563 * g = 100;
49564 * }
49565 *
49566 * function draw() {
49567 * background(g);
49568 * ellipse(width / 2, height / 2, d, d);
49569 * }
49570 *
49571 * // this function fires with mousewheel movement
49572 * // anywhere on screen
49573 * function mouseWheel() {
49574 * g = g + 10;
49575 * }
49576 *
49577 * // this function fires with mousewheel movement
49578 * // over canvas only
49579 * function changeSize(event) {
49580 * if (event.deltaY > 0) {
49581 * d = d + 10;
49582 * } else {
49583 * d = d - 10;
49584 * }
49585 * }
49586 * </code></div>
49587 *
49588 * @alt
49589 * no display.
49590 */
49591 _main.default.Element.prototype.mouseWheel = function(fxn) {
49592 _main.default.Element._adjustListener('wheel', fxn, this);
49593 return this;
49594 };
49595
49596 /**
49597 * The <a href="#/p5.Element/mouseReleased">mouseReleased()</a> function is
49598 * called once after every time a mouse button is released over the element.
49599 * Some mobile browsers may also trigger this event on a touch screen, if the
49600 * user performs a quick tap. This can be used to attach element specific event listeners.
49601 *
49602 * @method mouseReleased
49603 * @param {Function|Boolean} fxn function to be fired when mouse is
49604 * released over the element.
49605 * if `false` is passed instead, the previously
49606 * firing function will no longer fire.
49607 * @chainable
49608 * @example
49609 * <div class='norender'><code>
49610 * let cnv, d, g;
49611 * function setup() {
49612 * cnv = createCanvas(100, 100);
49613 * cnv.mouseReleased(changeGray); // attach listener for
49614 * // activity on canvas only
49615 * d = 10;
49616 * g = 100;
49617 * }
49618 *
49619 * function draw() {
49620 * background(g);
49621 * ellipse(width / 2, height / 2, d, d);
49622 * }
49623 *
49624 * // this function fires after the mouse has been
49625 * // released
49626 * function mouseReleased() {
49627 * d = d + 10;
49628 * }
49629 *
49630 * // this function fires after the mouse has been
49631 * // released while on canvas
49632 * function changeGray() {
49633 * g = random(0, 255);
49634 * }
49635 * </code></div>
49636 *
49637 * @alt
49638 * no display.
49639 */
49640 _main.default.Element.prototype.mouseReleased = function(fxn) {
49641 _main.default.Element._adjustListener('mouseup', fxn, this);
49642 return this;
49643 };
49644
49645 /**
49646 * The .<a href="#/p5.Element/mouseClicked">mouseClicked()</a> function is
49647 * called once after a mouse button is pressed and released over the element.
49648 * Some mobile browsers may also trigger this event on a touch screen, if the
49649 * user performs a quick tap.This can be used to attach element specific event listeners.
49650 *
49651 * @method mouseClicked
49652 * @param {Function|Boolean} fxn function to be fired when mouse is
49653 * clicked over the element.
49654 * if `false` is passed instead, the previously
49655 * firing function will no longer fire.
49656 * @chainable
49657 * @example
49658 * <div class="norender">
49659 * <code>
49660 * let cnv, d, g;
49661 * function setup() {
49662 * cnv = createCanvas(100, 100);
49663 * cnv.mouseClicked(changeGray); // attach listener for
49664 * // activity on canvas only
49665 * d = 10;
49666 * g = 100;
49667 * }
49668 *
49669 * function draw() {
49670 * background(g);
49671 * ellipse(width / 2, height / 2, d, d);
49672 * }
49673 *
49674 * // this function fires after the mouse has been
49675 * // clicked anywhere
49676 * function mouseClicked() {
49677 * d = d + 10;
49678 * }
49679 *
49680 * // this function fires after the mouse has been
49681 * // clicked on canvas
49682 * function changeGray() {
49683 * g = random(0, 255);
49684 * }
49685 * </code>
49686 * </div>
49687 *
49688 * @alt
49689 * no display.
49690 */
49691 _main.default.Element.prototype.mouseClicked = function(fxn) {
49692 _main.default.Element._adjustListener('click', fxn, this);
49693 return this;
49694 };
49695
49696 /**
49697 * The .<a href="#/p5.Element/mouseMoved">mouseMoved()</a> function is called once every time a
49698 * mouse moves over the element. This can be used to attach an
49699 * element specific event listener.
49700 *
49701 * @method mouseMoved
49702 * @param {Function|Boolean} fxn function to be fired when a mouse moves
49703 * over the element.
49704 * if `false` is passed instead, the previously
49705 * firing function will no longer fire.
49706 * @chainable
49707 * @example
49708 * <div class='norender'><code>
49709 * let cnv;
49710 * let d = 30;
49711 * let g;
49712 * function setup() {
49713 * cnv = createCanvas(100, 100);
49714 * cnv.mouseMoved(changeSize); // attach listener for
49715 * // activity on canvas only
49716 * d = 10;
49717 * g = 100;
49718 * }
49719 *
49720 * function draw() {
49721 * background(g);
49722 * fill(200);
49723 * ellipse(width / 2, height / 2, d, d);
49724 * }
49725 *
49726 * // this function fires when mouse moves anywhere on
49727 * // page
49728 * function mouseMoved() {
49729 * g = g + 5;
49730 * if (g > 255) {
49731 * g = 0;
49732 * }
49733 * }
49734 *
49735 * // this function fires when mouse moves over canvas
49736 * function changeSize() {
49737 * d = d + 2;
49738 * if (d > 100) {
49739 * d = 0;
49740 * }
49741 * }
49742 * </code></div>
49743 *
49744 * @alt
49745 * no display.
49746 */
49747 _main.default.Element.prototype.mouseMoved = function(fxn) {
49748 _main.default.Element._adjustListener('mousemove', fxn, this);
49749 return this;
49750 };
49751
49752 /**
49753 * The .<a href="#/p5.Element/mouseOver">mouseOver()</a> function is called once after every time a
49754 * mouse moves onto the element. This can be used to attach an
49755 * element specific event listener.
49756 *
49757 * @method mouseOver
49758 * @param {Function|Boolean} fxn function to be fired when a mouse moves
49759 * onto the element.
49760 * if `false` is passed instead, the previously
49761 * firing function will no longer fire.
49762 * @chainable
49763 * @example
49764 * <div class='norender'><code>
49765 * let cnv;
49766 * let d;
49767 * function setup() {
49768 * cnv = createCanvas(100, 100);
49769 * cnv.mouseOver(changeGray);
49770 * d = 10;
49771 * }
49772 *
49773 * function draw() {
49774 * ellipse(width / 2, height / 2, d, d);
49775 * }
49776 *
49777 * function changeGray() {
49778 * d = d + 10;
49779 * if (d > 100) {
49780 * d = 0;
49781 * }
49782 * }
49783 * </code></div>
49784 *
49785 * @alt
49786 * no display.
49787 */
49788 _main.default.Element.prototype.mouseOver = function(fxn) {
49789 _main.default.Element._adjustListener('mouseover', fxn, this);
49790 return this;
49791 };
49792
49793 /**
49794 * The .<a href="#/p5.Element/mouseOut">mouseOut()</a> function is called once after every time a
49795 * mouse moves off the element. This can be used to attach an
49796 * element specific event listener.
49797 *
49798 * @method mouseOut
49799 * @param {Function|Boolean} fxn function to be fired when a mouse
49800 * moves off of an element.
49801 * if `false` is passed instead, the previously
49802 * firing function will no longer fire.
49803 * @chainable
49804 * @example
49805 * <div class='norender'><code>
49806 * let cnv;
49807 * let d;
49808 * function setup() {
49809 * cnv = createCanvas(100, 100);
49810 * cnv.mouseOut(changeGray);
49811 * d = 10;
49812 * }
49813 *
49814 * function draw() {
49815 * ellipse(width / 2, height / 2, d, d);
49816 * }
49817 *
49818 * function changeGray() {
49819 * d = d + 10;
49820 * if (d > 100) {
49821 * d = 0;
49822 * }
49823 * }
49824 * </code></div>
49825 *
49826 * @alt
49827 * no display.
49828 */
49829 _main.default.Element.prototype.mouseOut = function(fxn) {
49830 _main.default.Element._adjustListener('mouseout', fxn, this);
49831 return this;
49832 };
49833
49834 /**
49835 * The .<a href="#/p5.Element/touchStarted">touchStarted()</a> function is called once after every time a touch is
49836 * registered. This can be used to attach element specific event listeners.
49837 *
49838 * @method touchStarted
49839 * @param {Function|Boolean} fxn function to be fired when a touch
49840 * starts over the element.
49841 * if `false` is passed instead, the previously
49842 * firing function will no longer fire.
49843 * @chainable
49844 * @example
49845 * <div class='norender'><code>
49846 * let cnv;
49847 * let d;
49848 * let g;
49849 * function setup() {
49850 * cnv = createCanvas(100, 100);
49851 * cnv.touchStarted(changeGray); // attach listener for
49852 * // canvas click only
49853 * d = 10;
49854 * g = 100;
49855 * }
49856 *
49857 * function draw() {
49858 * background(g);
49859 * ellipse(width / 2, height / 2, d, d);
49860 * }
49861 *
49862 * // this function fires with any touch anywhere
49863 * function touchStarted() {
49864 * d = d + 10;
49865 * }
49866 *
49867 * // this function fires only when cnv is clicked
49868 * function changeGray() {
49869 * g = random(0, 255);
49870 * }
49871 * </code></div>
49872 *
49873 * @alt
49874 * no display.
49875 */
49876 _main.default.Element.prototype.touchStarted = function(fxn) {
49877 _main.default.Element._adjustListener('touchstart', fxn, this);
49878 return this;
49879 };
49880
49881 /**
49882 * The .<a href="#/p5.Element/touchMoved">touchMoved()</a> function is called once after every time a touch move is
49883 * registered. This can be used to attach element specific event listeners.
49884 *
49885 * @method touchMoved
49886 * @param {Function|Boolean} fxn function to be fired when a touch moves over
49887 * the element.
49888 * if `false` is passed instead, the previously
49889 * firing function will no longer fire.
49890 * @chainable
49891 * @example
49892 * <div class='norender'><code>
49893 * let cnv;
49894 * let g;
49895 * function setup() {
49896 * cnv = createCanvas(100, 100);
49897 * cnv.touchMoved(changeGray); // attach listener for
49898 * // canvas click only
49899 * g = 100;
49900 * }
49901 *
49902 * function draw() {
49903 * background(g);
49904 * }
49905 *
49906 * // this function fires only when cnv is clicked
49907 * function changeGray() {
49908 * g = random(0, 255);
49909 * }
49910 * </code></div>
49911 *
49912 * @alt
49913 * no display.
49914 */
49915 _main.default.Element.prototype.touchMoved = function(fxn) {
49916 _main.default.Element._adjustListener('touchmove', fxn, this);
49917 return this;
49918 };
49919
49920 /**
49921 * The .<a href="#/p5.Element/touchEnded">touchEnded()</a> function is called once after every time a touch is
49922 * registered. This can be used to attach element specific event listeners.
49923 *
49924 * @method touchEnded
49925 * @param {Function|Boolean} fxn function to be fired when a touch ends
49926 * over the element.
49927 * if `false` is passed instead, the previously
49928 * firing function will no longer fire.
49929 * @chainable
49930 * @example
49931 * <div class='norender'><code>
49932 * let cnv;
49933 * let d;
49934 * let g;
49935 * function setup() {
49936 * cnv = createCanvas(100, 100);
49937 * cnv.touchEnded(changeGray); // attach listener for
49938 * // canvas click only
49939 * d = 10;
49940 * g = 100;
49941 * }
49942 *
49943 * function draw() {
49944 * background(g);
49945 * ellipse(width / 2, height / 2, d, d);
49946 * }
49947 *
49948 * // this function fires with any touch anywhere
49949 * function touchEnded() {
49950 * d = d + 10;
49951 * }
49952 *
49953 * // this function fires only when cnv is clicked
49954 * function changeGray() {
49955 * g = random(0, 255);
49956 * }
49957 * </code></div>
49958 *
49959 * @alt
49960 * no display.
49961 */
49962 _main.default.Element.prototype.touchEnded = function(fxn) {
49963 _main.default.Element._adjustListener('touchend', fxn, this);
49964 return this;
49965 };
49966
49967 /**
49968 * The .<a href="#/p5.Element/dragOver">dragOver()</a> function is called once after every time a
49969 * file is dragged over the element. This can be used to attach an
49970 * element specific event listener.
49971 *
49972 * @method dragOver
49973 * @param {Function|Boolean} fxn function to be fired when a file is
49974 * dragged over the element.
49975 * if `false` is passed instead, the previously
49976 * firing function will no longer fire.
49977 * @chainable
49978 * @example
49979 * <div><code>
49980 * // To test this sketch, simply drag a
49981 * // file over the canvas
49982 * function setup() {
49983 * let c = createCanvas(100, 100);
49984 * background(200);
49985 * textAlign(CENTER);
49986 * text('Drag file', width / 2, height / 2);
49987 * c.dragOver(dragOverCallback);
49988 * }
49989 *
49990 * // This function will be called whenever
49991 * // a file is dragged over the canvas
49992 * function dragOverCallback() {
49993 * background(240);
49994 * text('Dragged over', width / 2, height / 2);
49995 * }
49996 * </code></div>
49997 * @alt
49998 * nothing displayed
49999 */
50000 _main.default.Element.prototype.dragOver = function(fxn) {
50001 _main.default.Element._adjustListener('dragover', fxn, this);
50002 return this;
50003 };
50004
50005 /**
50006 * The .dragLeave() function is called once after every time a
50007 * dragged file leaves the element area. This can be used to attach an
50008 * element specific event listener.
50009 *
50010 * @method dragLeave
50011 * @param {Function|Boolean} fxn function to be fired when a file is
50012 * dragged off the element.
50013 * if `false` is passed instead, the previously
50014 * firing function will no longer fire.
50015 * @chainable
50016 * @example
50017 * <div><code>
50018 * // To test this sketch, simply drag a file
50019 * // over and then out of the canvas area
50020 * function setup() {
50021 * let c = createCanvas(100, 100);
50022 * background(200);
50023 * textAlign(CENTER);
50024 * text('Drag file', width / 2, height / 2);
50025 * c.dragLeave(dragLeaveCallback);
50026 * }
50027 *
50028 * // This function will be called whenever
50029 * // a file is dragged out of the canvas
50030 * function dragLeaveCallback() {
50031 * background(240);
50032 * text('Dragged off', width / 2, height / 2);
50033 * }
50034 * </code></div>
50035 * @alt
50036 * nothing displayed
50037 */
50038 _main.default.Element.prototype.dragLeave = function(fxn) {
50039 _main.default.Element._adjustListener('dragleave', fxn, this);
50040 return this;
50041 };
50042
50043 // General handler for event attaching and detaching
50044 _main.default.Element._adjustListener = function(ev, fxn, ctx) {
50045 if (fxn === false) {
50046 _main.default.Element._detachListener(ev, ctx);
50047 } else {
50048 _main.default.Element._attachListener(ev, fxn, ctx);
50049 }
50050 return this;
50051 };
50052
50053 _main.default.Element._attachListener = function(ev, fxn, ctx) {
50054 // detach the old listener if there was one
50055 if (ctx._events[ev]) {
50056 _main.default.Element._detachListener(ev, ctx);
50057 }
50058 var f = fxn.bind(ctx);
50059 ctx.elt.addEventListener(ev, f, false);
50060 ctx._events[ev] = f;
50061 };
50062
50063 _main.default.Element._detachListener = function(ev, ctx) {
50064 var f = ctx._events[ev];
50065 ctx.elt.removeEventListener(ev, f, false);
50066 ctx._events[ev] = null;
50067 };
50068
50069 /**
50070 * Helper fxn for sharing pixel methods
50071 */
50072 _main.default.Element.prototype._setProperty = function(prop, value) {
50073 this[prop] = value;
50074 };
50075 var _default = _main.default.Element;
50076 exports.default = _default;
50077 },
50078 { './main': 54 }
50079 ],
50080 56: [
50081 function(_dereq_, module, exports) {
50082 'use strict';
50083 function _typeof(obj) {
50084 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
50085 _typeof = function _typeof(obj) {
50086 return typeof obj;
50087 };
50088 } else {
50089 _typeof = function _typeof(obj) {
50090 return obj &&
50091 typeof Symbol === 'function' &&
50092 obj.constructor === Symbol &&
50093 obj !== Symbol.prototype
50094 ? 'symbol'
50095 : typeof obj;
50096 };
50097 }
50098 return _typeof(obj);
50099 }
50100 Object.defineProperty(exports, '__esModule', { value: true });
50101 exports.default = void 0;
50102
50103 var _main = _interopRequireDefault(_dereq_('./main'));
50104 var constants = _interopRequireWildcard(_dereq_('./constants'));
50105 function _getRequireWildcardCache() {
50106 if (typeof WeakMap !== 'function') return null;
50107 var cache = new WeakMap();
50108 _getRequireWildcardCache = function _getRequireWildcardCache() {
50109 return cache;
50110 };
50111 return cache;
50112 }
50113 function _interopRequireWildcard(obj) {
50114 if (obj && obj.__esModule) {
50115 return obj;
50116 }
50117 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) {
50118 return { default: obj };
50119 }
50120 var cache = _getRequireWildcardCache();
50121 if (cache && cache.has(obj)) {
50122 return cache.get(obj);
50123 }
50124 var newObj = {};
50125 var hasPropertyDescriptor =
50126 Object.defineProperty && Object.getOwnPropertyDescriptor;
50127 for (var key in obj) {
50128 if (Object.prototype.hasOwnProperty.call(obj, key)) {
50129 var desc = hasPropertyDescriptor
50130 ? Object.getOwnPropertyDescriptor(obj, key)
50131 : null;
50132 if (desc && (desc.get || desc.set)) {
50133 Object.defineProperty(newObj, key, desc);
50134 } else {
50135 newObj[key] = obj[key];
50136 }
50137 }
50138 }
50139 newObj.default = obj;
50140 if (cache) {
50141 cache.set(obj, newObj);
50142 }
50143 return newObj;
50144 }
50145 function _interopRequireDefault(obj) {
50146 return obj && obj.__esModule ? obj : { default: obj };
50147 }
50148 /**
50149 * @module Rendering
50150 * @submodule Rendering
50151 * @for p5
50152 */ /**
50153 * Thin wrapper around a renderer, to be used for creating a
50154 * graphics buffer object. Use this class if you need
50155 * to draw into an off-screen graphics buffer. The two parameters define the
50156 * width and height in pixels. The fields and methods for this class are
50157 * extensive, but mirror the normal drawing API for p5.
50158 *
50159 * @class p5.Graphics
50160 * @constructor
50161 * @extends p5.Element
50162 * @param {Number} w width
50163 * @param {Number} h height
50164 * @param {Constant} renderer the renderer to use, either P2D or WEBGL
50165 * @param {p5} [pInst] pointer to p5 instance
50166 */ _main.default.Graphics = function(w, h, renderer, pInst) {
50167 var r = renderer || constants.P2D;
50168
50169 this.canvas = document.createElement('canvas');
50170 var node = pInst._userNode || document.body;
50171 node.appendChild(this.canvas);
50172
50173 _main.default.Element.call(this, this.canvas, pInst);
50174
50175 // bind methods and props of p5 to the new object
50176 for (var p in _main.default.prototype) {
50177 if (!this[p]) {
50178 if (typeof _main.default.prototype[p] === 'function') {
50179 this[p] = _main.default.prototype[p].bind(this);
50180 } else {
50181 this[p] = _main.default.prototype[p];
50182 }
50183 }
50184 }
50185
50186 _main.default.prototype._initializeInstanceVariables.apply(this);
50187 this.width = w;
50188 this.height = h;
50189 this._pixelDensity = pInst._pixelDensity;
50190
50191 if (r === constants.WEBGL) {
50192 this._renderer = new _main.default.RendererGL(this.canvas, this, false);
50193 } else {
50194 this._renderer = new _main.default.Renderer2D(this.canvas, this, false);
50195 }
50196 pInst._elements.push(this);
50197
50198 Object.defineProperty(this, 'deltaTime', {
50199 get: function get() {
50200 return this._pInst.deltaTime;
50201 }
50202 });
50203
50204 this._renderer.resize(w, h);
50205 this._renderer._applyDefaults();
50206 return this;
50207 };
50208
50209 _main.default.Graphics.prototype = Object.create(_main.default.Element.prototype);
50210
50211 /**
50212 * Resets certain values such as those modified by functions in the Transform category
50213 * and in the Lights category that are not automatically reset
50214 * with graphics buffer objects. Calling this in <a href='#/p5/draw'>draw()</a> will copy the behavior
50215 * of the standard canvas.
50216 *
50217 * @method reset
50218 * @example
50219 *
50220 * <div><code>
50221 * let pg;
50222 * function setup() {
50223 * createCanvas(100, 100);
50224 * background(0);
50225 * pg = createGraphics(50, 100);
50226 * pg.fill(0);
50227 * frameRate(5);
50228 * }
50229 *
50230 * function draw() {
50231 * image(pg, width / 2, 0);
50232 * pg.background(255);
50233 * // p5.Graphics object behave a bit differently in some cases
50234 * // The normal canvas on the left resets the translate
50235 * // with every loop through draw()
50236 * // the graphics object on the right doesn't automatically reset
50237 * // so translate() is additive and it moves down the screen
50238 * rect(0, 0, width / 2, 5);
50239 * pg.rect(0, 0, width / 2, 5);
50240 * translate(0, 5, 0);
50241 * pg.translate(0, 5, 0);
50242 * }
50243 * function mouseClicked() {
50244 * // if you click you will see that
50245 * // reset() resets the translate back to the initial state
50246 * // of the Graphics object
50247 * pg.reset();
50248 * }
50249 * </code></div>
50250 *
50251 * @alt
50252 * A white line on a black background stays still on the top-left half.
50253 * A black line animates from top to bottom on a white background on the right half.
50254 * When clicked, the black line starts back over at the top.
50255 */
50256 _main.default.Graphics.prototype.reset = function() {
50257 this._renderer.resetMatrix();
50258 if (this._renderer.isP3D) {
50259 this._renderer._update();
50260 }
50261 };
50262
50263 /**
50264 * Removes a Graphics object from the page and frees any resources
50265 * associated with it.
50266 *
50267 * @method remove
50268 *
50269 * @example
50270 * <div class='norender'><code>
50271 * let bg;
50272 * function setup() {
50273 * bg = createCanvas(100, 100);
50274 * bg.background(0);
50275 * image(bg, 0, 0);
50276 * bg.remove();
50277 * }
50278 * </code></div>
50279 *
50280 * <div><code>
50281 * let bg;
50282 * function setup() {
50283 * pixelDensity(1);
50284 * createCanvas(100, 100);
50285 * stroke(255);
50286 * fill(0);
50287 *
50288 * // create and draw the background image
50289 * bg = createGraphics(100, 100);
50290 * bg.background(200);
50291 * bg.ellipse(50, 50, 80, 80);
50292 * }
50293 * function draw() {
50294 * let t = millis() / 1000;
50295 * // draw the background
50296 * if (bg) {
50297 * image(bg, frameCount % 100, 0);
50298 * image(bg, frameCount % 100 - 100, 0);
50299 * }
50300 * // draw the foreground
50301 * let p = p5.Vector.fromAngle(t, 35).add(50, 50);
50302 * ellipse(p.x, p.y, 30);
50303 * }
50304 * function mouseClicked() {
50305 * // remove the background
50306 * if (bg) {
50307 * bg.remove();
50308 * bg = null;
50309 * }
50310 * }
50311 * </code></div>
50312 *
50313 * @alt
50314 * no image
50315 * a multi-colored circle moving back and forth over a scrolling background.
50316 */
50317 _main.default.Graphics.prototype.remove = function() {
50318 if (this.elt.parentNode) {
50319 this.elt.parentNode.removeChild(this.elt);
50320 }
50321 var idx = this._pInst._elements.indexOf(this);
50322 if (idx !== -1) {
50323 this._pInst._elements.splice(idx, 1);
50324 }
50325 for (var elt_ev in this._events) {
50326 this.elt.removeEventListener(elt_ev, this._events[elt_ev]);
50327 }
50328 };
50329 var _default = _main.default.Graphics;
50330 exports.default = _default;
50331 },
50332 { './constants': 43, './main': 54 }
50333 ],
50334 57: [
50335 function(_dereq_, module, exports) {
50336 'use strict';
50337 Object.defineProperty(exports, '__esModule', { value: true });
50338 exports.default = void 0;
50339
50340 var _main = _interopRequireDefault(_dereq_('./main'));
50341 var constants = _interopRequireWildcard(_dereq_('../core/constants'));
50342 function _getRequireWildcardCache() {
50343 if (typeof WeakMap !== 'function') return null;
50344 var cache = new WeakMap();
50345 _getRequireWildcardCache = function _getRequireWildcardCache() {
50346 return cache;
50347 };
50348 return cache;
50349 }
50350 function _interopRequireWildcard(obj) {
50351 if (obj && obj.__esModule) {
50352 return obj;
50353 }
50354 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) {
50355 return { default: obj };
50356 }
50357 var cache = _getRequireWildcardCache();
50358 if (cache && cache.has(obj)) {
50359 return cache.get(obj);
50360 }
50361 var newObj = {};
50362 var hasPropertyDescriptor =
50363 Object.defineProperty && Object.getOwnPropertyDescriptor;
50364 for (var key in obj) {
50365 if (Object.prototype.hasOwnProperty.call(obj, key)) {
50366 var desc = hasPropertyDescriptor
50367 ? Object.getOwnPropertyDescriptor(obj, key)
50368 : null;
50369 if (desc && (desc.get || desc.set)) {
50370 Object.defineProperty(newObj, key, desc);
50371 } else {
50372 newObj[key] = obj[key];
50373 }
50374 }
50375 }
50376 newObj.default = obj;
50377 if (cache) {
50378 cache.set(obj, newObj);
50379 }
50380 return newObj;
50381 }
50382 function _interopRequireDefault(obj) {
50383 return obj && obj.__esModule ? obj : { default: obj };
50384 }
50385 function _typeof(obj) {
50386 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
50387 _typeof = function _typeof(obj) {
50388 return typeof obj;
50389 };
50390 } else {
50391 _typeof = function _typeof(obj) {
50392 return obj &&
50393 typeof Symbol === 'function' &&
50394 obj.constructor === Symbol &&
50395 obj !== Symbol.prototype
50396 ? 'symbol'
50397 : typeof obj;
50398 };
50399 }
50400 return _typeof(obj);
50401 }
50402
50403 /**
50404 * Main graphics and rendering context, as well as the base API
50405 * implementation for p5.js "core". To be used as the superclass for
50406 * Renderer2D and Renderer3D classes, respectively.
50407 *
50408 * @class p5.Renderer
50409 * @constructor
50410 * @extends p5.Element
50411 * @param {String} elt DOM node that is wrapped
50412 * @param {p5} [pInst] pointer to p5 instance
50413 * @param {Boolean} [isMainCanvas] whether we're using it as main canvas
50414 */
50415 _main.default.Renderer = function(elt, pInst, isMainCanvas) {
50416 _main.default.Element.call(this, elt, pInst);
50417 this.canvas = elt;
50418 this._pixelsState = pInst;
50419 if (isMainCanvas) {
50420 this._isMainCanvas = true;
50421 // for pixel method sharing with pimage
50422 this._pInst._setProperty('_curElement', this);
50423 this._pInst._setProperty('canvas', this.canvas);
50424 this._pInst._setProperty('width', this.width);
50425 this._pInst._setProperty('height', this.height);
50426 } else {
50427 // hide if offscreen buffer by default
50428 this.canvas.style.display = 'none';
50429 this._styles = []; // non-main elt styles stored in p5.Renderer
50430 }
50431
50432 this._textSize = 12;
50433 this._textLeading = 15;
50434 this._textFont = 'sans-serif';
50435 this._textStyle = constants.NORMAL;
50436 this._textAscent = null;
50437 this._textDescent = null;
50438 this._textAlign = constants.LEFT;
50439 this._textBaseline = constants.BASELINE;
50440
50441 this._rectMode = constants.CORNER;
50442 this._ellipseMode = constants.CENTER;
50443 this._curveTightness = 0;
50444 this._imageMode = constants.CORNER;
50445
50446 this._tint = null;
50447 this._doStroke = true;
50448 this._doFill = true;
50449 this._strokeSet = false;
50450 this._fillSet = false;
50451 };
50452
50453 _main.default.Renderer.prototype = Object.create(_main.default.Element.prototype);
50454
50455 // the renderer should return a 'style' object that it wishes to
50456 // store on the push stack.
50457 _main.default.Renderer.prototype.push = function() {
50458 return {
50459 properties: {
50460 _doStroke: this._doStroke,
50461 _strokeSet: this._strokeSet,
50462 _doFill: this._doFill,
50463 _fillSet: this._fillSet,
50464 _tint: this._tint,
50465 _imageMode: this._imageMode,
50466 _rectMode: this._rectMode,
50467 _ellipseMode: this._ellipseMode,
50468 _textFont: this._textFont,
50469 _textLeading: this._textLeading,
50470 _textSize: this._textSize,
50471 _textAlign: this._textAlign,
50472 _textBaseline: this._textBaseline,
50473 _textStyle: this._textStyle
50474 }
50475 };
50476 };
50477
50478 // a pop() operation is in progress
50479 // the renderer is passed the 'style' object that it returned
50480 // from its push() method.
50481 _main.default.Renderer.prototype.pop = function(style) {
50482 if (style.properties) {
50483 // copy the style properties back into the renderer
50484 Object.assign(this, style.properties);
50485 }
50486 };
50487
50488 /**
50489 * Resize our canvas element.
50490 */
50491 _main.default.Renderer.prototype.resize = function(w, h) {
50492 this.width = w;
50493 this.height = h;
50494 this.elt.width = w * this._pInst._pixelDensity;
50495 this.elt.height = h * this._pInst._pixelDensity;
50496 this.elt.style.width = ''.concat(w, 'px');
50497 this.elt.style.height = ''.concat(h, 'px');
50498 if (this._isMainCanvas) {
50499 this._pInst._setProperty('width', this.width);
50500 this._pInst._setProperty('height', this.height);
50501 }
50502 };
50503
50504 _main.default.Renderer.prototype.get = function(x, y, w, h) {
50505 var pixelsState = this._pixelsState;
50506 var pd = pixelsState._pixelDensity;
50507 var canvas = this.canvas;
50508
50509 if (typeof x === 'undefined' && typeof y === 'undefined') {
50510 // get()
50511 x = y = 0;
50512 w = pixelsState.width;
50513 h = pixelsState.height;
50514 } else {
50515 x *= pd;
50516 y *= pd;
50517
50518 if (typeof w === 'undefined' && typeof h === 'undefined') {
50519 // get(x,y)
50520 if (x < 0 || y < 0 || x >= canvas.width || y >= canvas.height) {
50521 return [0, 0, 0, 0];
50522 }
50523
50524 return this._getPixel(x, y);
50525 }
50526 // get(x,y,w,h)
50527 }
50528
50529 var region = new _main.default.Image(w, h);
50530 region.canvas
50531 .getContext('2d')
50532 .drawImage(canvas, x, y, w * pd, h * pd, 0, 0, w, h);
50533
50534 return region;
50535 };
50536
50537 _main.default.Renderer.prototype.textLeading = function(l) {
50538 if (typeof l === 'number') {
50539 this._setProperty('_textLeading', l);
50540 return this._pInst;
50541 }
50542
50543 return this._textLeading;
50544 };
50545
50546 _main.default.Renderer.prototype.textSize = function(s) {
50547 if (typeof s === 'number') {
50548 this._setProperty('_textSize', s);
50549 this._setProperty('_textLeading', s * constants._DEFAULT_LEADMULT);
50550 return this._applyTextProperties();
50551 }
50552
50553 return this._textSize;
50554 };
50555
50556 _main.default.Renderer.prototype.textStyle = function(s) {
50557 if (s) {
50558 if (
50559 s === constants.NORMAL ||
50560 s === constants.ITALIC ||
50561 s === constants.BOLD ||
50562 s === constants.BOLDITALIC
50563 ) {
50564 this._setProperty('_textStyle', s);
50565 }
50566
50567 return this._applyTextProperties();
50568 }
50569
50570 return this._textStyle;
50571 };
50572
50573 _main.default.Renderer.prototype.textAscent = function() {
50574 if (this._textAscent === null) {
50575 this._updateTextMetrics();
50576 }
50577 return this._textAscent;
50578 };
50579
50580 _main.default.Renderer.prototype.textDescent = function() {
50581 if (this._textDescent === null) {
50582 this._updateTextMetrics();
50583 }
50584 return this._textDescent;
50585 };
50586
50587 _main.default.Renderer.prototype.textAlign = function(h, v) {
50588 if (typeof h !== 'undefined') {
50589 this._setProperty('_textAlign', h);
50590
50591 if (typeof v !== 'undefined') {
50592 this._setProperty('_textBaseline', v);
50593 }
50594
50595 return this._applyTextProperties();
50596 } else {
50597 return {
50598 horizontal: this._textAlign,
50599 vertical: this._textBaseline
50600 };
50601 }
50602 };
50603
50604 _main.default.Renderer.prototype.text = function(str, x, y, maxWidth, maxHeight) {
50605 var p = this._pInst;
50606 var cars;
50607 var n;
50608 var ii;
50609 var jj;
50610 var line;
50611 var testLine;
50612 var currentLineLength;
50613 var testWidth;
50614 var words;
50615 var totalHeight;
50616 var finalMaxHeight = Number.MAX_VALUE;
50617
50618 if (!(this._doFill || this._doStroke)) {
50619 return;
50620 }
50621
50622 if (typeof str === 'undefined') {
50623 return;
50624 } else if (typeof str !== 'string') {
50625 str = str.toString();
50626 }
50627
50628 str = str.replace(/(\t)/g, ' ');
50629 cars = str.split('\n');
50630
50631 if (typeof maxWidth !== 'undefined') {
50632 totalHeight = 0;
50633 currentLineLength = 1;
50634 for (ii = 0; ii < cars.length; ii++) {
50635 line = '';
50636 words = cars[ii].split(' ');
50637 for (n = 0; n < words.length; n++) {
50638 testLine = ''.concat(line + words[n], ' ');
50639 testWidth = this.textWidth(testLine);
50640 if (testWidth > maxWidth && currentLineLength > 1) {
50641 line = ''.concat(words[n], ' ');
50642 totalHeight += p.textLeading();
50643 currentLineLength = 1;
50644 } else {
50645 line = testLine;
50646 currentLineLength += 1;
50647 }
50648 }
50649 if (ii < cars.length - 1) {
50650 totalHeight += p.textLeading();
50651 }
50652 }
50653
50654 if (this._rectMode === constants.CENTER) {
50655 x -= maxWidth / 2;
50656 y -= maxHeight / 2;
50657 }
50658
50659 switch (this._textAlign) {
50660 case constants.CENTER:
50661 x += maxWidth / 2;
50662 break;
50663 case constants.RIGHT:
50664 x += maxWidth;
50665 break;
50666 }
50667
50668 var baselineHacked = false;
50669 if (typeof maxHeight !== 'undefined') {
50670 switch (this._textBaseline) {
50671 case constants.BOTTOM:
50672 y += maxHeight - totalHeight;
50673 break;
50674 case constants.CENTER:
50675 y += (maxHeight - totalHeight) / 2;
50676 break;
50677 case constants.BASELINE:
50678 baselineHacked = true;
50679 this._textBaseline = constants.TOP;
50680 break;
50681 }
50682
50683 // remember the max-allowed y-position for any line (fix to #928)
50684 finalMaxHeight = y + maxHeight - p.textAscent();
50685 }
50686
50687 for (ii = 0; ii < cars.length; ii++) {
50688 line = '';
50689 words = cars[ii].split(' ');
50690 for (n = 0; n < words.length; n++) {
50691 testLine = ''.concat(line + words[n], ' ');
50692 testWidth = this.textWidth(testLine);
50693 if (testWidth > maxWidth && line.length > 0) {
50694 this._renderText(p, line, x, y, finalMaxHeight);
50695 line = ''.concat(words[n], ' ');
50696 y += p.textLeading();
50697 } else {
50698 line = testLine;
50699 }
50700 }
50701
50702 this._renderText(p, line, x, y, finalMaxHeight);
50703 y += p.textLeading();
50704
50705 if (baselineHacked) {
50706 this._textBaseline = constants.BASELINE;
50707 }
50708 }
50709 } else {
50710 // Offset to account for vertically centering multiple lines of text - no
50711 // need to adjust anything for vertical align top or baseline
50712 var offset = 0;
50713
50714 var vAlign = p.textAlign().vertical;
50715 if (vAlign === constants.CENTER) {
50716 offset = (cars.length - 1) * p.textLeading() / 2;
50717 } else if (vAlign === constants.BOTTOM) {
50718 offset = (cars.length - 1) * p.textLeading();
50719 }
50720
50721 for (jj = 0; jj < cars.length; jj++) {
50722 this._renderText(p, cars[jj], x, y - offset, finalMaxHeight);
50723 y += p.textLeading();
50724 }
50725 }
50726
50727 return p;
50728 };
50729
50730 _main.default.Renderer.prototype._applyDefaults = function() {
50731 return this;
50732 };
50733
50734 /**
50735 * Helper fxn to check font type (system or otf)
50736 */
50737 _main.default.Renderer.prototype._isOpenType = function() {
50738 var f =
50739 arguments.length > 0 && arguments[0] !== undefined
50740 ? arguments[0]
50741 : this._textFont;
50742 return _typeof(f) === 'object' && f.font && f.font.supported;
50743 };
50744
50745 _main.default.Renderer.prototype._updateTextMetrics = function() {
50746 if (this._isOpenType()) {
50747 this._setProperty('_textAscent', this._textFont._textAscent());
50748 this._setProperty('_textDescent', this._textFont._textDescent());
50749 return this;
50750 }
50751
50752 // Adapted from http://stackoverflow.com/a/25355178
50753 var text = document.createElement('span');
50754 text.style.fontFamily = this._textFont;
50755 text.style.fontSize = ''.concat(this._textSize, 'px');
50756 text.innerHTML = 'ABCjgq|';
50757
50758 var block = document.createElement('div');
50759 block.style.display = 'inline-block';
50760 block.style.width = '1px';
50761 block.style.height = '0px';
50762
50763 var container = document.createElement('div');
50764 container.appendChild(text);
50765 container.appendChild(block);
50766
50767 container.style.height = '0px';
50768 container.style.overflow = 'hidden';
50769 document.body.appendChild(container);
50770
50771 block.style.verticalAlign = 'baseline';
50772 var blockOffset = calculateOffset(block);
50773 var textOffset = calculateOffset(text);
50774 var ascent = blockOffset[1] - textOffset[1];
50775
50776 block.style.verticalAlign = 'bottom';
50777 blockOffset = calculateOffset(block);
50778 textOffset = calculateOffset(text);
50779 var height = blockOffset[1] - textOffset[1];
50780 var descent = height - ascent;
50781
50782 document.body.removeChild(container);
50783
50784 this._setProperty('_textAscent', ascent);
50785 this._setProperty('_textDescent', descent);
50786
50787 return this;
50788 };
50789
50790 /**
50791 * Helper fxn to measure ascent and descent.
50792 * Adapted from http://stackoverflow.com/a/25355178
50793 */
50794 function calculateOffset(object) {
50795 var currentLeft = 0,
50796 currentTop = 0;
50797 if (object.offsetParent) {
50798 do {
50799 currentLeft += object.offsetLeft;
50800 currentTop += object.offsetTop;
50801 } while ((object = object.offsetParent));
50802 } else {
50803 currentLeft += object.offsetLeft;
50804 currentTop += object.offsetTop;
50805 }
50806 return [currentLeft, currentTop];
50807 }
50808 var _default = _main.default.Renderer;
50809 exports.default = _default;
50810 },
50811 { '../core/constants': 43, './main': 54 }
50812 ],
50813 58: [
50814 function(_dereq_, module, exports) {
50815 'use strict';
50816 function _typeof(obj) {
50817 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
50818 _typeof = function _typeof(obj) {
50819 return typeof obj;
50820 };
50821 } else {
50822 _typeof = function _typeof(obj) {
50823 return obj &&
50824 typeof Symbol === 'function' &&
50825 obj.constructor === Symbol &&
50826 obj !== Symbol.prototype
50827 ? 'symbol'
50828 : typeof obj;
50829 };
50830 }
50831 return _typeof(obj);
50832 }
50833 Object.defineProperty(exports, '__esModule', { value: true });
50834 exports.default = void 0;
50835 var _main = _interopRequireDefault(_dereq_('./main'));
50836 var constants = _interopRequireWildcard(_dereq_('./constants'));
50837 var _filters = _interopRequireDefault(_dereq_('../image/filters'));
50838
50839 _dereq_('./p5.Renderer');
50840 function _getRequireWildcardCache() {
50841 if (typeof WeakMap !== 'function') return null;
50842 var cache = new WeakMap();
50843 _getRequireWildcardCache = function _getRequireWildcardCache() {
50844 return cache;
50845 };
50846 return cache;
50847 }
50848 function _interopRequireWildcard(obj) {
50849 if (obj && obj.__esModule) {
50850 return obj;
50851 }
50852 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) {
50853 return { default: obj };
50854 }
50855 var cache = _getRequireWildcardCache();
50856 if (cache && cache.has(obj)) {
50857 return cache.get(obj);
50858 }
50859 var newObj = {};
50860 var hasPropertyDescriptor =
50861 Object.defineProperty && Object.getOwnPropertyDescriptor;
50862 for (var key in obj) {
50863 if (Object.prototype.hasOwnProperty.call(obj, key)) {
50864 var desc = hasPropertyDescriptor
50865 ? Object.getOwnPropertyDescriptor(obj, key)
50866 : null;
50867 if (desc && (desc.get || desc.set)) {
50868 Object.defineProperty(newObj, key, desc);
50869 } else {
50870 newObj[key] = obj[key];
50871 }
50872 }
50873 }
50874 newObj.default = obj;
50875 if (cache) {
50876 cache.set(obj, newObj);
50877 }
50878 return newObj;
50879 }
50880 function _interopRequireDefault(obj) {
50881 return obj && obj.__esModule ? obj : { default: obj };
50882 }
50883
50884 /**
50885 * p5.Renderer2D
50886 * The 2D graphics canvas renderer class.
50887 * extends p5.Renderer
50888 */
50889 var styleEmpty = 'rgba(0,0,0,0)';
50890 // const alphaThreshold = 0.00125; // minimum visible
50891
50892 _main.default.Renderer2D = function(elt, pInst, isMainCanvas) {
50893 _main.default.Renderer.call(this, elt, pInst, isMainCanvas);
50894 this.drawingContext = this.canvas.getContext('2d');
50895 this._pInst._setProperty('drawingContext', this.drawingContext);
50896 return this;
50897 };
50898
50899 _main.default.Renderer2D.prototype = Object.create(
50900 _main.default.Renderer.prototype
50901 );
50902
50903 _main.default.Renderer2D.prototype._applyDefaults = function() {
50904 this._cachedFillStyle = this._cachedStrokeStyle = undefined;
50905 this._cachedBlendMode = constants.BLEND;
50906 this._setFill(constants._DEFAULT_FILL);
50907 this._setStroke(constants._DEFAULT_STROKE);
50908 this.drawingContext.lineCap = constants.ROUND;
50909 this.drawingContext.font = 'normal 12px sans-serif';
50910 };
50911
50912 _main.default.Renderer2D.prototype.resize = function(w, h) {
50913 _main.default.Renderer.prototype.resize.call(this, w, h);
50914 this.drawingContext.scale(this._pInst._pixelDensity, this._pInst._pixelDensity);
50915 };
50916
50917 //////////////////////////////////////////////
50918 // COLOR | Setting
50919 //////////////////////////////////////////////
50920
50921 _main.default.Renderer2D.prototype.background = function() {
50922 this.drawingContext.save();
50923 this.resetMatrix();
50924
50925 if (
50926 (arguments.length <= 0 ? undefined : arguments[0]) instanceof
50927 _main.default.Image
50928 ) {
50929 this._pInst.image(
50930 arguments.length <= 0 ? undefined : arguments[0],
50931 0,
50932 0,
50933 this.width,
50934 this.height
50935 );
50936 } else {
50937 var _this$_pInst;
50938 var curFill = this._getFill();
50939 // create background rect
50940 var color = (_this$_pInst = this._pInst).color.apply(_this$_pInst, arguments);
50941 var newFill = color.toString();
50942 this._setFill(newFill);
50943
50944 if (this._isErasing) {
50945 this.blendMode(this._cachedBlendMode);
50946 }
50947
50948 this.drawingContext.fillRect(0, 0, this.width, this.height);
50949 // reset fill
50950 this._setFill(curFill);
50951
50952 if (this._isErasing) {
50953 this._pInst.erase();
50954 }
50955 }
50956 this.drawingContext.restore();
50957 };
50958
50959 _main.default.Renderer2D.prototype.clear = function() {
50960 this.drawingContext.save();
50961 this.resetMatrix();
50962 this.drawingContext.clearRect(0, 0, this.width, this.height);
50963 this.drawingContext.restore();
50964 };
50965
50966 _main.default.Renderer2D.prototype.fill = function() {
50967 var _this$_pInst2;
50968 var color = (_this$_pInst2 = this._pInst).color.apply(_this$_pInst2, arguments);
50969 this._setFill(color.toString());
50970 };
50971
50972 _main.default.Renderer2D.prototype.stroke = function() {
50973 var _this$_pInst3;
50974 var color = (_this$_pInst3 = this._pInst).color.apply(_this$_pInst3, arguments);
50975 this._setStroke(color.toString());
50976 };
50977
50978 _main.default.Renderer2D.prototype.erase = function(opacityFill, opacityStroke) {
50979 if (!this._isErasing) {
50980 // cache the fill style
50981 this._cachedFillStyle = this.drawingContext.fillStyle;
50982 var newFill = this._pInst.color(255, opacityFill).toString();
50983 this.drawingContext.fillStyle = newFill;
50984
50985 //cache the stroke style
50986 this._cachedStrokeStyle = this.drawingContext.strokeStyle;
50987 var newStroke = this._pInst.color(255, opacityStroke).toString();
50988 this.drawingContext.strokeStyle = newStroke;
50989
50990 //cache blendMode
50991 var tempBlendMode = this._cachedBlendMode;
50992 this.blendMode(constants.REMOVE);
50993 this._cachedBlendMode = tempBlendMode;
50994
50995 this._isErasing = true;
50996 }
50997 };
50998
50999 _main.default.Renderer2D.prototype.noErase = function() {
51000 if (this._isErasing) {
51001 this.drawingContext.fillStyle = this._cachedFillStyle;
51002 this.drawingContext.strokeStyle = this._cachedStrokeStyle;
51003
51004 this.blendMode(this._cachedBlendMode);
51005 this._isErasing = false;
51006 }
51007 };
51008
51009 //////////////////////////////////////////////
51010 // IMAGE | Loading & Displaying
51011 //////////////////////////////////////////////
51012
51013 _main.default.Renderer2D.prototype.image = function(
51014 img,
51015 sx,
51016 sy,
51017 sWidth,
51018 sHeight,
51019 dx,
51020 dy,
51021 dWidth,
51022 dHeight
51023 ) {
51024 var cnv;
51025 if (img.gifProperties) {
51026 img._animateGif(this._pInst);
51027 }
51028
51029 try {
51030 if (this._tint) {
51031 if (
51032 _main.default.MediaElement &&
51033 img instanceof _main.default.MediaElement
51034 ) {
51035 img.loadPixels();
51036 }
51037 if (img.canvas) {
51038 cnv = this._getTintedImageCanvas(img);
51039 }
51040 }
51041 if (!cnv) {
51042 cnv = img.canvas || img.elt;
51043 }
51044 var s = 1;
51045 if (img.width && img.width > 0) {
51046 s = cnv.width / img.width;
51047 }
51048 if (this._isErasing) {
51049 this.blendMode(this._cachedBlendMode);
51050 }
51051 this.drawingContext.drawImage(
51052 cnv,
51053 s * sx,
51054 s * sy,
51055 s * sWidth,
51056 s * sHeight,
51057 dx,
51058 dy,
51059 dWidth,
51060 dHeight
51061 );
51062
51063 if (this._isErasing) {
51064 this._pInst.erase();
51065 }
51066 } catch (e) {
51067 if (e.name !== 'NS_ERROR_NOT_AVAILABLE') {
51068 throw e;
51069 }
51070 }
51071 };
51072
51073 _main.default.Renderer2D.prototype._getTintedImageCanvas = function(img) {
51074 if (!img.canvas) {
51075 return img;
51076 }
51077 var pixels = _filters.default._toPixels(img.canvas);
51078 var tmpCanvas = document.createElement('canvas');
51079 tmpCanvas.width = img.canvas.width;
51080 tmpCanvas.height = img.canvas.height;
51081 var tmpCtx = tmpCanvas.getContext('2d');
51082 var id = tmpCtx.createImageData(img.canvas.width, img.canvas.height);
51083 var newPixels = id.data;
51084 for (var i = 0; i < pixels.length; i += 4) {
51085 var r = pixels[i];
51086 var g = pixels[i + 1];
51087 var b = pixels[i + 2];
51088 var a = pixels[i + 3];
51089 newPixels[i] = r * this._tint[0] / 255;
51090 newPixels[i + 1] = g * this._tint[1] / 255;
51091 newPixels[i + 2] = b * this._tint[2] / 255;
51092 newPixels[i + 3] = a * this._tint[3] / 255;
51093 }
51094 tmpCtx.putImageData(id, 0, 0);
51095 return tmpCanvas;
51096 };
51097
51098 //////////////////////////////////////////////
51099 // IMAGE | Pixels
51100 //////////////////////////////////////////////
51101
51102 _main.default.Renderer2D.prototype.blendMode = function(mode) {
51103 if (mode === constants.SUBTRACT) {
51104 console.warn('blendMode(SUBTRACT) only works in WEBGL mode.');
51105 } else if (
51106 mode === constants.BLEND ||
51107 mode === constants.REMOVE ||
51108 mode === constants.DARKEST ||
51109 mode === constants.LIGHTEST ||
51110 mode === constants.DIFFERENCE ||
51111 mode === constants.MULTIPLY ||
51112 mode === constants.EXCLUSION ||
51113 mode === constants.SCREEN ||
51114 mode === constants.REPLACE ||
51115 mode === constants.OVERLAY ||
51116 mode === constants.HARD_LIGHT ||
51117 mode === constants.SOFT_LIGHT ||
51118 mode === constants.DODGE ||
51119 mode === constants.BURN ||
51120 mode === constants.ADD
51121 ) {
51122 this._cachedBlendMode = mode;
51123 this.drawingContext.globalCompositeOperation = mode;
51124 } else {
51125 throw new Error('Mode '.concat(mode, ' not recognized.'));
51126 }
51127 };
51128
51129 _main.default.Renderer2D.prototype.blend = function() {
51130 var currBlend = this.drawingContext.globalCompositeOperation;
51131 for (
51132 var _len = arguments.length, args = new Array(_len), _key = 0;
51133 _key < _len;
51134 _key++
51135 ) {
51136 args[_key] = arguments[_key];
51137 }
51138 var blendMode = args[args.length - 1];
51139
51140 var copyArgs = Array.prototype.slice.call(args, 0, args.length - 1);
51141
51142 this.drawingContext.globalCompositeOperation = blendMode;
51143
51144 _main.default.prototype.copy.apply(this, copyArgs);
51145
51146 this.drawingContext.globalCompositeOperation = currBlend;
51147 };
51148
51149 // p5.Renderer2D.prototype.get = p5.Renderer.prototype.get;
51150 // .get() is not overridden
51151
51152 // x,y are canvas-relative (pre-scaled by _pixelDensity)
51153 _main.default.Renderer2D.prototype._getPixel = function(x, y) {
51154 var imageData, index;
51155 imageData = this.drawingContext.getImageData(x, y, 1, 1).data;
51156 index = 0;
51157 return [
51158 imageData[index + 0],
51159 imageData[index + 1],
51160 imageData[index + 2],
51161 imageData[index + 3]
51162 ];
51163 };
51164
51165 _main.default.Renderer2D.prototype.loadPixels = function() {
51166 var pixelsState = this._pixelsState; // if called by p5.Image
51167
51168 var pd = pixelsState._pixelDensity;
51169 var w = this.width * pd;
51170 var h = this.height * pd;
51171 var imageData = this.drawingContext.getImageData(0, 0, w, h);
51172 // @todo this should actually set pixels per object, so diff buffers can
51173 // have diff pixel arrays.
51174 pixelsState._setProperty('imageData', imageData);
51175 pixelsState._setProperty('pixels', imageData.data);
51176 };
51177
51178 _main.default.Renderer2D.prototype.set = function(x, y, imgOrCol) {
51179 // round down to get integer numbers
51180 x = Math.floor(x);
51181 y = Math.floor(y);
51182 var pixelsState = this._pixelsState;
51183 if (imgOrCol instanceof _main.default.Image) {
51184 this.drawingContext.save();
51185 this.drawingContext.setTransform(1, 0, 0, 1, 0, 0);
51186 this.drawingContext.scale(
51187 pixelsState._pixelDensity,
51188 pixelsState._pixelDensity
51189 );
51190
51191 this.drawingContext.clearRect(x, y, imgOrCol.width, imgOrCol.height);
51192 this.drawingContext.drawImage(imgOrCol.canvas, x, y);
51193 this.drawingContext.restore();
51194 } else {
51195 var r = 0,
51196 g = 0,
51197 b = 0,
51198 a = 0;
51199 var idx =
51200 4 *
51201 (y * pixelsState._pixelDensity * (this.width * pixelsState._pixelDensity) +
51202 x * pixelsState._pixelDensity);
51203 if (!pixelsState.imageData) {
51204 pixelsState.loadPixels.call(pixelsState);
51205 }
51206 if (typeof imgOrCol === 'number') {
51207 if (idx < pixelsState.pixels.length) {
51208 r = imgOrCol;
51209 g = imgOrCol;
51210 b = imgOrCol;
51211 a = 255;
51212 //this.updatePixels.call(this);
51213 }
51214 } else if (imgOrCol instanceof Array) {
51215 if (imgOrCol.length < 4) {
51216 throw new Error('pixel array must be of the form [R, G, B, A]');
51217 }
51218 if (idx < pixelsState.pixels.length) {
51219 r = imgOrCol[0];
51220 g = imgOrCol[1];
51221 b = imgOrCol[2];
51222 a = imgOrCol[3];
51223 //this.updatePixels.call(this);
51224 }
51225 } else if (imgOrCol instanceof _main.default.Color) {
51226 if (idx < pixelsState.pixels.length) {
51227 r = imgOrCol.levels[0];
51228 g = imgOrCol.levels[1];
51229 b = imgOrCol.levels[2];
51230 a = imgOrCol.levels[3];
51231 //this.updatePixels.call(this);
51232 }
51233 }
51234 // loop over pixelDensity * pixelDensity
51235 for (var i = 0; i < pixelsState._pixelDensity; i++) {
51236 for (var j = 0; j < pixelsState._pixelDensity; j++) {
51237 // loop over
51238 idx =
51239 4 *
51240 ((y * pixelsState._pixelDensity + j) *
51241 this.width *
51242 pixelsState._pixelDensity +
51243 (x * pixelsState._pixelDensity + i));
51244 pixelsState.pixels[idx] = r;
51245 pixelsState.pixels[idx + 1] = g;
51246 pixelsState.pixels[idx + 2] = b;
51247 pixelsState.pixels[idx + 3] = a;
51248 }
51249 }
51250 }
51251 };
51252
51253 _main.default.Renderer2D.prototype.updatePixels = function(x, y, w, h) {
51254 var pixelsState = this._pixelsState;
51255 var pd = pixelsState._pixelDensity;
51256 if (x === undefined && y === undefined && w === undefined && h === undefined) {
51257 x = 0;
51258 y = 0;
51259 w = this.width;
51260 h = this.height;
51261 }
51262 x *= pd;
51263 y *= pd;
51264 w *= pd;
51265 h *= pd;
51266
51267 if (this.gifProperties) {
51268 this.gifProperties.frames[this.gifProperties.displayIndex].image =
51269 pixelsState.imageData;
51270 }
51271
51272 this.drawingContext.putImageData(pixelsState.imageData, x, y, 0, 0, w, h);
51273 };
51274
51275 //////////////////////////////////////////////
51276 // SHAPE | 2D Primitives
51277 //////////////////////////////////////////////
51278
51279 /**
51280 * Generate a cubic Bezier representing an arc on the unit circle of total
51281 * angle `size` radians, beginning `start` radians above the x-axis. Up to
51282 * four of these curves are combined to make a full arc.
51283 *
51284 * See www.joecridge.me/bezier.pdf for an explanation of the method.
51285 */
51286 _main.default.Renderer2D.prototype._acuteArcToBezier = function _acuteArcToBezier(
51287 start,
51288 size
51289 ) {
51290 // Evaluate constants.
51291 var alpha = size / 2.0,
51292 cos_alpha = Math.cos(alpha),
51293 sin_alpha = Math.sin(alpha),
51294 cot_alpha = 1.0 / Math.tan(alpha),
51295 // This is how far the arc needs to be rotated.
51296 phi = start + alpha,
51297 cos_phi = Math.cos(phi),
51298 sin_phi = Math.sin(phi),
51299 lambda = (4.0 - cos_alpha) / 3.0,
51300 mu = sin_alpha + (cos_alpha - lambda) * cot_alpha;
51301
51302 // Return rotated waypoints.
51303 return {
51304 ax: Math.cos(start).toFixed(7),
51305 ay: Math.sin(start).toFixed(7),
51306 bx: (lambda * cos_phi + mu * sin_phi).toFixed(7),
51307 by: (lambda * sin_phi - mu * cos_phi).toFixed(7),
51308 cx: (lambda * cos_phi - mu * sin_phi).toFixed(7),
51309 cy: (lambda * sin_phi + mu * cos_phi).toFixed(7),
51310 dx: Math.cos(start + size).toFixed(7),
51311 dy: Math.sin(start + size).toFixed(7)
51312 };
51313 };
51314
51315 /*
51316 * This function requires that:
51317 *
51318 * 0 <= start < TWO_PI
51319 *
51320 * start <= stop < start + TWO_PI
51321 */
51322 _main.default.Renderer2D.prototype.arc = function(x, y, w, h, start, stop, mode) {
51323 var ctx = this.drawingContext;
51324 var rx = w / 2.0;
51325 var ry = h / 2.0;
51326 var epsilon = 0.00001; // Smallest visible angle on displays up to 4K.
51327 var arcToDraw = 0;
51328 var curves = [];
51329
51330 x += rx;
51331 y += ry;
51332
51333 // Create curves
51334 while (stop - start >= epsilon) {
51335 arcToDraw = Math.min(stop - start, constants.HALF_PI);
51336 curves.push(this._acuteArcToBezier(start, arcToDraw));
51337 start += arcToDraw;
51338 }
51339
51340 // Fill curves
51341 if (this._doFill) {
51342 ctx.beginPath();
51343 curves.forEach(function(curve, index) {
51344 if (index === 0) {
51345 ctx.moveTo(x + curve.ax * rx, y + curve.ay * ry);
51346 }
51347 // prettier-ignore
51348 ctx.bezierCurveTo(x + curve.bx * rx, y + curve.by * ry,
51349 x + curve.cx * rx, y + curve.cy * ry,
51350 x + curve.dx * rx, y + curve.dy * ry);
51351 });
51352 if (mode === constants.PIE || mode == null) {
51353 ctx.lineTo(x, y);
51354 }
51355 ctx.closePath();
51356 ctx.fill();
51357 }
51358
51359 // Stroke curves
51360 if (this._doStroke) {
51361 ctx.beginPath();
51362 curves.forEach(function(curve, index) {
51363 if (index === 0) {
51364 ctx.moveTo(x + curve.ax * rx, y + curve.ay * ry);
51365 }
51366 // prettier-ignore
51367 ctx.bezierCurveTo(x + curve.bx * rx, y + curve.by * ry,
51368 x + curve.cx * rx, y + curve.cy * ry,
51369 x + curve.dx * rx, y + curve.dy * ry);
51370 });
51371 if (mode === constants.PIE) {
51372 ctx.lineTo(x, y);
51373 ctx.closePath();
51374 } else if (mode === constants.CHORD) {
51375 ctx.closePath();
51376 }
51377 ctx.stroke();
51378 }
51379 return this;
51380 };
51381
51382 _main.default.Renderer2D.prototype.ellipse = function(args) {
51383 var ctx = this.drawingContext;
51384 var doFill = this._doFill,
51385 doStroke = this._doStroke;
51386 var x = parseFloat(args[0]),
51387 y = parseFloat(args[1]),
51388 w = parseFloat(args[2]),
51389 h = parseFloat(args[3]);
51390 if (doFill && !doStroke) {
51391 if (this._getFill() === styleEmpty) {
51392 return this;
51393 }
51394 } else if (!doFill && doStroke) {
51395 if (this._getStroke() === styleEmpty) {
51396 return this;
51397 }
51398 }
51399 var kappa = 0.5522847498,
51400 // control point offset horizontal
51401 ox = w / 2 * kappa,
51402 // control point offset vertical
51403 oy = h / 2 * kappa,
51404 // x-end
51405 xe = x + w,
51406 // y-end
51407 ye = y + h,
51408 // x-middle
51409 xm = x + w / 2,
51410 ym = y + h / 2; // y-middle
51411 ctx.beginPath();
51412 ctx.moveTo(x, ym);
51413 ctx.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y);
51414 ctx.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym);
51415 ctx.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye);
51416 ctx.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym);
51417 if (doFill) {
51418 ctx.fill();
51419 }
51420 if (doStroke) {
51421 ctx.stroke();
51422 }
51423 };
51424
51425 _main.default.Renderer2D.prototype.line = function(x1, y1, x2, y2) {
51426 var ctx = this.drawingContext;
51427 if (!this._doStroke) {
51428 return this;
51429 } else if (this._getStroke() === styleEmpty) {
51430 return this;
51431 }
51432 ctx.beginPath();
51433 ctx.moveTo(x1, y1);
51434 ctx.lineTo(x2, y2);
51435 ctx.stroke();
51436 return this;
51437 };
51438
51439 _main.default.Renderer2D.prototype.point = function(x, y) {
51440 var ctx = this.drawingContext;
51441 if (!this._doStroke) {
51442 return this;
51443 } else if (this._getStroke() === styleEmpty) {
51444 return this;
51445 }
51446 var s = this._getStroke();
51447 var f = this._getFill();
51448 x = Math.round(x);
51449 y = Math.round(y);
51450 // swapping fill color to stroke and back after for correct point rendering
51451 this._setFill(s);
51452 if (ctx.lineWidth > 1) {
51453 ctx.beginPath();
51454 ctx.arc(x, y, ctx.lineWidth / 2, 0, constants.TWO_PI, false);
51455 ctx.fill();
51456 } else {
51457 ctx.fillRect(x, y, 1, 1);
51458 }
51459 this._setFill(f);
51460 };
51461
51462 _main.default.Renderer2D.prototype.quad = function(
51463 x1,
51464 y1,
51465 x2,
51466 y2,
51467 x3,
51468 y3,
51469 x4,
51470 y4
51471 ) {
51472 var ctx = this.drawingContext;
51473 var doFill = this._doFill,
51474 doStroke = this._doStroke;
51475 if (doFill && !doStroke) {
51476 if (this._getFill() === styleEmpty) {
51477 return this;
51478 }
51479 } else if (!doFill && doStroke) {
51480 if (this._getStroke() === styleEmpty) {
51481 return this;
51482 }
51483 }
51484 ctx.beginPath();
51485 ctx.moveTo(x1, y1);
51486 ctx.lineTo(x2, y2);
51487 ctx.lineTo(x3, y3);
51488 ctx.lineTo(x4, y4);
51489 ctx.closePath();
51490 if (doFill) {
51491 ctx.fill();
51492 }
51493 if (doStroke) {
51494 ctx.stroke();
51495 }
51496 return this;
51497 };
51498
51499 _main.default.Renderer2D.prototype.rect = function(args) {
51500 var x = args[0];
51501 var y = args[1];
51502 var w = args[2];
51503 var h = args[3];
51504 var tl = args[4];
51505 var tr = args[5];
51506 var br = args[6];
51507 var bl = args[7];
51508 var ctx = this.drawingContext;
51509 var doFill = this._doFill,
51510 doStroke = this._doStroke;
51511 if (doFill && !doStroke) {
51512 if (this._getFill() === styleEmpty) {
51513 return this;
51514 }
51515 } else if (!doFill && doStroke) {
51516 if (this._getStroke() === styleEmpty) {
51517 return this;
51518 }
51519 }
51520 ctx.beginPath();
51521
51522 if (typeof tl === 'undefined') {
51523 // No rounded corners
51524 ctx.rect(x, y, w, h);
51525 } else {
51526 // At least one rounded corner
51527 // Set defaults when not specified
51528 if (typeof tr === 'undefined') {
51529 tr = tl;
51530 }
51531 if (typeof br === 'undefined') {
51532 br = tr;
51533 }
51534 if (typeof bl === 'undefined') {
51535 bl = br;
51536 }
51537
51538 // corner rounding must always be positive
51539 var absW = Math.abs(w);
51540 var absH = Math.abs(h);
51541 var hw = absW / 2;
51542 var hh = absH / 2;
51543
51544 // Clip radii
51545 if (absW < 2 * tl) {
51546 tl = hw;
51547 }
51548 if (absH < 2 * tl) {
51549 tl = hh;
51550 }
51551 if (absW < 2 * tr) {
51552 tr = hw;
51553 }
51554 if (absH < 2 * tr) {
51555 tr = hh;
51556 }
51557 if (absW < 2 * br) {
51558 br = hw;
51559 }
51560 if (absH < 2 * br) {
51561 br = hh;
51562 }
51563 if (absW < 2 * bl) {
51564 bl = hw;
51565 }
51566 if (absH < 2 * bl) {
51567 bl = hh;
51568 }
51569
51570 // Draw shape
51571 ctx.beginPath();
51572 ctx.moveTo(x + tl, y);
51573 ctx.arcTo(x + w, y, x + w, y + h, tr);
51574 ctx.arcTo(x + w, y + h, x, y + h, br);
51575 ctx.arcTo(x, y + h, x, y, bl);
51576 ctx.arcTo(x, y, x + w, y, tl);
51577 ctx.closePath();
51578 }
51579 if (this._doFill) {
51580 ctx.fill();
51581 }
51582 if (this._doStroke) {
51583 ctx.stroke();
51584 }
51585 return this;
51586 };
51587
51588 _main.default.Renderer2D.prototype.triangle = function(args) {
51589 var ctx = this.drawingContext;
51590 var doFill = this._doFill,
51591 doStroke = this._doStroke;
51592 var x1 = args[0],
51593 y1 = args[1];
51594 var x2 = args[2],
51595 y2 = args[3];
51596 var x3 = args[4],
51597 y3 = args[5];
51598 if (doFill && !doStroke) {
51599 if (this._getFill() === styleEmpty) {
51600 return this;
51601 }
51602 } else if (!doFill && doStroke) {
51603 if (this._getStroke() === styleEmpty) {
51604 return this;
51605 }
51606 }
51607 ctx.beginPath();
51608 ctx.moveTo(x1, y1);
51609 ctx.lineTo(x2, y2);
51610 ctx.lineTo(x3, y3);
51611 ctx.closePath();
51612 if (doFill) {
51613 ctx.fill();
51614 }
51615 if (doStroke) {
51616 ctx.stroke();
51617 }
51618 };
51619
51620 _main.default.Renderer2D.prototype.endShape = function(
51621 mode,
51622 vertices,
51623 isCurve,
51624 isBezier,
51625 isQuadratic,
51626 isContour,
51627 shapeKind
51628 ) {
51629 if (vertices.length === 0) {
51630 return this;
51631 }
51632 if (!this._doStroke && !this._doFill) {
51633 return this;
51634 }
51635 var closeShape = mode === constants.CLOSE;
51636 var v;
51637 if (closeShape && !isContour) {
51638 vertices.push(vertices[0]);
51639 }
51640 var i, j;
51641 var numVerts = vertices.length;
51642 if (isCurve && (shapeKind === constants.POLYGON || shapeKind === null)) {
51643 if (numVerts > 3) {
51644 var b = [],
51645 s = 1 - this._curveTightness;
51646 this.drawingContext.beginPath();
51647 this.drawingContext.moveTo(vertices[1][0], vertices[1][1]);
51648 for (i = 1; i + 2 < numVerts; i++) {
51649 v = vertices[i];
51650 b[0] = [v[0], v[1]];
51651 b[1] = [
51652 v[0] + (s * vertices[i + 1][0] - s * vertices[i - 1][0]) / 6,
51653 v[1] + (s * vertices[i + 1][1] - s * vertices[i - 1][1]) / 6
51654 ];
51655
51656 b[2] = [
51657 vertices[i + 1][0] + (s * vertices[i][0] - s * vertices[i + 2][0]) / 6,
51658 vertices[i + 1][1] + (s * vertices[i][1] - s * vertices[i + 2][1]) / 6
51659 ];
51660
51661 b[3] = [vertices[i + 1][0], vertices[i + 1][1]];
51662 this.drawingContext.bezierCurveTo(
51663 b[1][0],
51664 b[1][1],
51665 b[2][0],
51666 b[2][1],
51667 b[3][0],
51668 b[3][1]
51669 );
51670 }
51671 if (closeShape) {
51672 this.drawingContext.lineTo(vertices[i + 1][0], vertices[i + 1][1]);
51673 }
51674 this._doFillStrokeClose(closeShape);
51675 }
51676 } else if (
51677 isBezier &&
51678 (shapeKind === constants.POLYGON || shapeKind === null)
51679 ) {
51680 this.drawingContext.beginPath();
51681 for (i = 0; i < numVerts; i++) {
51682 if (vertices[i].isVert) {
51683 if (vertices[i].moveTo) {
51684 this.drawingContext.moveTo(vertices[i][0], vertices[i][1]);
51685 } else {
51686 this.drawingContext.lineTo(vertices[i][0], vertices[i][1]);
51687 }
51688 } else {
51689 this.drawingContext.bezierCurveTo(
51690 vertices[i][0],
51691 vertices[i][1],
51692 vertices[i][2],
51693 vertices[i][3],
51694 vertices[i][4],
51695 vertices[i][5]
51696 );
51697 }
51698 }
51699 this._doFillStrokeClose(closeShape);
51700 } else if (
51701 isQuadratic &&
51702 (shapeKind === constants.POLYGON || shapeKind === null)
51703 ) {
51704 this.drawingContext.beginPath();
51705 for (i = 0; i < numVerts; i++) {
51706 if (vertices[i].isVert) {
51707 if (vertices[i].moveTo) {
51708 this.drawingContext.moveTo(vertices[i][0], vertices[i][1]);
51709 } else {
51710 this.drawingContext.lineTo(vertices[i][0], vertices[i][1]);
51711 }
51712 } else {
51713 this.drawingContext.quadraticCurveTo(
51714 vertices[i][0],
51715 vertices[i][1],
51716 vertices[i][2],
51717 vertices[i][3]
51718 );
51719 }
51720 }
51721 this._doFillStrokeClose(closeShape);
51722 } else {
51723 if (shapeKind === constants.POINTS) {
51724 for (i = 0; i < numVerts; i++) {
51725 v = vertices[i];
51726 if (this._doStroke) {
51727 this._pInst.stroke(v[6]);
51728 }
51729 this._pInst.point(v[0], v[1]);
51730 }
51731 } else if (shapeKind === constants.LINES) {
51732 for (i = 0; i + 1 < numVerts; i += 2) {
51733 v = vertices[i];
51734 if (this._doStroke) {
51735 this._pInst.stroke(vertices[i + 1][6]);
51736 }
51737 this._pInst.line(v[0], v[1], vertices[i + 1][0], vertices[i + 1][1]);
51738 }
51739 } else if (shapeKind === constants.TRIANGLES) {
51740 for (i = 0; i + 2 < numVerts; i += 3) {
51741 v = vertices[i];
51742 this.drawingContext.beginPath();
51743 this.drawingContext.moveTo(v[0], v[1]);
51744 this.drawingContext.lineTo(vertices[i + 1][0], vertices[i + 1][1]);
51745 this.drawingContext.lineTo(vertices[i + 2][0], vertices[i + 2][1]);
51746 this.drawingContext.closePath();
51747 if (this._doFill) {
51748 this._pInst.fill(vertices[i + 2][5]);
51749 this.drawingContext.fill();
51750 }
51751 if (this._doStroke) {
51752 this._pInst.stroke(vertices[i + 2][6]);
51753 this.drawingContext.stroke();
51754 }
51755 }
51756 } else if (shapeKind === constants.TRIANGLE_STRIP) {
51757 for (i = 0; i + 1 < numVerts; i++) {
51758 v = vertices[i];
51759 this.drawingContext.beginPath();
51760 this.drawingContext.moveTo(vertices[i + 1][0], vertices[i + 1][1]);
51761 this.drawingContext.lineTo(v[0], v[1]);
51762 if (this._doStroke) {
51763 this._pInst.stroke(vertices[i + 1][6]);
51764 }
51765 if (this._doFill) {
51766 this._pInst.fill(vertices[i + 1][5]);
51767 }
51768 if (i + 2 < numVerts) {
51769 this.drawingContext.lineTo(vertices[i + 2][0], vertices[i + 2][1]);
51770 if (this._doStroke) {
51771 this._pInst.stroke(vertices[i + 2][6]);
51772 }
51773 if (this._doFill) {
51774 this._pInst.fill(vertices[i + 2][5]);
51775 }
51776 }
51777 this._doFillStrokeClose(closeShape);
51778 }
51779 } else if (shapeKind === constants.TRIANGLE_FAN) {
51780 if (numVerts > 2) {
51781 // For performance reasons, try to batch as many of the
51782 // fill and stroke calls as possible.
51783 this.drawingContext.beginPath();
51784 for (i = 2; i < numVerts; i++) {
51785 v = vertices[i];
51786 this.drawingContext.moveTo(vertices[0][0], vertices[0][1]);
51787 this.drawingContext.lineTo(vertices[i - 1][0], vertices[i - 1][1]);
51788 this.drawingContext.lineTo(v[0], v[1]);
51789 this.drawingContext.lineTo(vertices[0][0], vertices[0][1]);
51790 // If the next colour is going to be different, stroke / fill now
51791 if (i < numVerts - 1) {
51792 if (
51793 (this._doFill && v[5] !== vertices[i + 1][5]) ||
51794 (this._doStroke && v[6] !== vertices[i + 1][6])
51795 ) {
51796 if (this._doFill) {
51797 this._pInst.fill(v[5]);
51798 this.drawingContext.fill();
51799 this._pInst.fill(vertices[i + 1][5]);
51800 }
51801 if (this._doStroke) {
51802 this._pInst.stroke(v[6]);
51803 this.drawingContext.stroke();
51804 this._pInst.stroke(vertices[i + 1][6]);
51805 }
51806 this.drawingContext.closePath();
51807 this.drawingContext.beginPath(); // Begin the next one
51808 }
51809 }
51810 }
51811 this._doFillStrokeClose(closeShape);
51812 }
51813 } else if (shapeKind === constants.QUADS) {
51814 for (i = 0; i + 3 < numVerts; i += 4) {
51815 v = vertices[i];
51816 this.drawingContext.beginPath();
51817 this.drawingContext.moveTo(v[0], v[1]);
51818 for (j = 1; j < 4; j++) {
51819 this.drawingContext.lineTo(vertices[i + j][0], vertices[i + j][1]);
51820 }
51821 this.drawingContext.lineTo(v[0], v[1]);
51822 if (this._doFill) {
51823 this._pInst.fill(vertices[i + 3][5]);
51824 }
51825 if (this._doStroke) {
51826 this._pInst.stroke(vertices[i + 3][6]);
51827 }
51828 this._doFillStrokeClose(closeShape);
51829 }
51830 } else if (shapeKind === constants.QUAD_STRIP) {
51831 if (numVerts > 3) {
51832 for (i = 0; i + 1 < numVerts; i += 2) {
51833 v = vertices[i];
51834 this.drawingContext.beginPath();
51835 if (i + 3 < numVerts) {
51836 this.drawingContext.moveTo(vertices[i + 2][0], vertices[i + 2][1]);
51837 this.drawingContext.lineTo(v[0], v[1]);
51838 this.drawingContext.lineTo(vertices[i + 1][0], vertices[i + 1][1]);
51839 this.drawingContext.lineTo(vertices[i + 3][0], vertices[i + 3][1]);
51840 if (this._doFill) {
51841 this._pInst.fill(vertices[i + 3][5]);
51842 }
51843 if (this._doStroke) {
51844 this._pInst.stroke(vertices[i + 3][6]);
51845 }
51846 } else {
51847 this.drawingContext.moveTo(v[0], v[1]);
51848 this.drawingContext.lineTo(vertices[i + 1][0], vertices[i + 1][1]);
51849 }
51850 this._doFillStrokeClose(closeShape);
51851 }
51852 }
51853 } else {
51854 this.drawingContext.beginPath();
51855 this.drawingContext.moveTo(vertices[0][0], vertices[0][1]);
51856 for (i = 1; i < numVerts; i++) {
51857 v = vertices[i];
51858 if (v.isVert) {
51859 if (v.moveTo) {
51860 this.drawingContext.moveTo(v[0], v[1]);
51861 } else {
51862 this.drawingContext.lineTo(v[0], v[1]);
51863 }
51864 }
51865 }
51866 this._doFillStrokeClose(closeShape);
51867 }
51868 }
51869 isCurve = false;
51870 isBezier = false;
51871 isQuadratic = false;
51872 isContour = false;
51873 if (closeShape) {
51874 vertices.pop();
51875 }
51876
51877 return this;
51878 };
51879 //////////////////////////////////////////////
51880 // SHAPE | Attributes
51881 //////////////////////////////////////////////
51882
51883 _main.default.Renderer2D.prototype.strokeCap = function(cap) {
51884 if (
51885 cap === constants.ROUND ||
51886 cap === constants.SQUARE ||
51887 cap === constants.PROJECT
51888 ) {
51889 this.drawingContext.lineCap = cap;
51890 }
51891 return this;
51892 };
51893
51894 _main.default.Renderer2D.prototype.strokeJoin = function(join) {
51895 if (
51896 join === constants.ROUND ||
51897 join === constants.BEVEL ||
51898 join === constants.MITER
51899 ) {
51900 this.drawingContext.lineJoin = join;
51901 }
51902 return this;
51903 };
51904
51905 _main.default.Renderer2D.prototype.strokeWeight = function(w) {
51906 if (typeof w === 'undefined' || w === 0) {
51907 // hack because lineWidth 0 doesn't work
51908 this.drawingContext.lineWidth = 0.0001;
51909 } else {
51910 this.drawingContext.lineWidth = w;
51911 }
51912 return this;
51913 };
51914
51915 _main.default.Renderer2D.prototype._getFill = function() {
51916 if (!this._cachedFillStyle) {
51917 this._cachedFillStyle = this.drawingContext.fillStyle;
51918 }
51919 return this._cachedFillStyle;
51920 };
51921
51922 _main.default.Renderer2D.prototype._setFill = function(fillStyle) {
51923 if (fillStyle !== this._cachedFillStyle) {
51924 this.drawingContext.fillStyle = fillStyle;
51925 this._cachedFillStyle = fillStyle;
51926 }
51927 };
51928
51929 _main.default.Renderer2D.prototype._getStroke = function() {
51930 if (!this._cachedStrokeStyle) {
51931 this._cachedStrokeStyle = this.drawingContext.strokeStyle;
51932 }
51933 return this._cachedStrokeStyle;
51934 };
51935
51936 _main.default.Renderer2D.prototype._setStroke = function(strokeStyle) {
51937 if (strokeStyle !== this._cachedStrokeStyle) {
51938 this.drawingContext.strokeStyle = strokeStyle;
51939 this._cachedStrokeStyle = strokeStyle;
51940 }
51941 };
51942
51943 //////////////////////////////////////////////
51944 // SHAPE | Curves
51945 //////////////////////////////////////////////
51946 _main.default.Renderer2D.prototype.bezier = function(
51947 x1,
51948 y1,
51949 x2,
51950 y2,
51951 x3,
51952 y3,
51953 x4,
51954 y4
51955 ) {
51956 this._pInst.beginShape();
51957 this._pInst.vertex(x1, y1);
51958 this._pInst.bezierVertex(x2, y2, x3, y3, x4, y4);
51959 this._pInst.endShape();
51960 return this;
51961 };
51962
51963 _main.default.Renderer2D.prototype.curve = function(
51964 x1,
51965 y1,
51966 x2,
51967 y2,
51968 x3,
51969 y3,
51970 x4,
51971 y4
51972 ) {
51973 this._pInst.beginShape();
51974 this._pInst.curveVertex(x1, y1);
51975 this._pInst.curveVertex(x2, y2);
51976 this._pInst.curveVertex(x3, y3);
51977 this._pInst.curveVertex(x4, y4);
51978 this._pInst.endShape();
51979 return this;
51980 };
51981
51982 //////////////////////////////////////////////
51983 // SHAPE | Vertex
51984 //////////////////////////////////////////////
51985
51986 _main.default.Renderer2D.prototype._doFillStrokeClose = function(closeShape) {
51987 if (closeShape) {
51988 this.drawingContext.closePath();
51989 }
51990 if (this._doFill) {
51991 this.drawingContext.fill();
51992 }
51993 if (this._doStroke) {
51994 this.drawingContext.stroke();
51995 }
51996 };
51997
51998 //////////////////////////////////////////////
51999 // TRANSFORM
52000 //////////////////////////////////////////////
52001
52002 _main.default.Renderer2D.prototype.applyMatrix = function(a, b, c, d, e, f) {
52003 this.drawingContext.transform(a, b, c, d, e, f);
52004 };
52005
52006 _main.default.Renderer2D.prototype.resetMatrix = function() {
52007 this.drawingContext.setTransform(1, 0, 0, 1, 0, 0);
52008 this.drawingContext.scale(this._pInst._pixelDensity, this._pInst._pixelDensity);
52009
52010 return this;
52011 };
52012
52013 _main.default.Renderer2D.prototype.rotate = function(rad) {
52014 this.drawingContext.rotate(rad);
52015 };
52016
52017 _main.default.Renderer2D.prototype.scale = function(x, y) {
52018 this.drawingContext.scale(x, y);
52019 return this;
52020 };
52021
52022 _main.default.Renderer2D.prototype.translate = function(x, y) {
52023 // support passing a vector as the 1st parameter
52024 if (x instanceof _main.default.Vector) {
52025 y = x.y;
52026 x = x.x;
52027 }
52028 this.drawingContext.translate(x, y);
52029 return this;
52030 };
52031
52032 //////////////////////////////////////////////
52033 // TYPOGRAPHY
52034 //
52035 //////////////////////////////////////////////
52036
52037 _main.default.Renderer2D.prototype.text = function(
52038 str,
52039 x,
52040 y,
52041 maxWidth,
52042 maxHeight
52043 ) {
52044 var baselineHacked;
52045
52046 // baselineHacked: (HACK)
52047 // A temporary fix to conform to Processing's implementation
52048 // of BASELINE vertical alignment in a bounding box
52049
52050 if (typeof maxWidth !== 'undefined') {
52051 if (this.drawingContext.textBaseline === constants.BASELINE) {
52052 baselineHacked = true;
52053 this.drawingContext.textBaseline = constants.TOP;
52054 }
52055 }
52056
52057 var p = _main.default.Renderer.prototype.text.apply(this, arguments);
52058
52059 if (baselineHacked) {
52060 this.drawingContext.textBaseline = constants.BASELINE;
52061 }
52062
52063 return p;
52064 };
52065
52066 _main.default.Renderer2D.prototype._renderText = function(p, line, x, y, maxY) {
52067 if (y >= maxY) {
52068 return; // don't render lines beyond our maxY position
52069 }
52070
52071 p.push(); // fix to #803
52072
52073 if (!this._isOpenType()) {
52074 // a system/browser font
52075
52076 // no stroke unless specified by user
52077 if (this._doStroke && this._strokeSet) {
52078 this.drawingContext.strokeText(line, x, y);
52079 }
52080
52081 if (this._doFill) {
52082 // if fill hasn't been set by user, use default text fill
52083 if (!this._fillSet) {
52084 this._setFill(constants._DEFAULT_TEXT_FILL);
52085 }
52086
52087 this.drawingContext.fillText(line, x, y);
52088 }
52089 } else {
52090 // an opentype font, let it handle the rendering
52091
52092 this._textFont._renderPath(line, x, y, { renderer: this });
52093 }
52094
52095 p.pop();
52096 return p;
52097 };
52098
52099 _main.default.Renderer2D.prototype.textWidth = function(s) {
52100 if (this._isOpenType()) {
52101 return this._textFont._textWidth(s, this._textSize);
52102 }
52103
52104 return this.drawingContext.measureText(s).width;
52105 };
52106
52107 _main.default.Renderer2D.prototype._applyTextProperties = function() {
52108 var font;
52109 var p = this._pInst;
52110
52111 this._setProperty('_textAscent', null);
52112 this._setProperty('_textDescent', null);
52113
52114 font = this._textFont;
52115
52116 if (this._isOpenType()) {
52117 font = this._textFont.font.familyName;
52118 this._setProperty('_textStyle', this._textFont.font.styleName);
52119 }
52120
52121 this.drawingContext.font = ''
52122 .concat(this._textStyle || 'normal', ' ')
52123 .concat(this._textSize || 12, 'px ')
52124 .concat(font || 'sans-serif');
52125
52126 this.drawingContext.textAlign = this._textAlign;
52127 if (this._textBaseline === constants.CENTER) {
52128 this.drawingContext.textBaseline = constants._CTX_MIDDLE;
52129 } else {
52130 this.drawingContext.textBaseline = this._textBaseline;
52131 }
52132
52133 return p;
52134 };
52135
52136 //////////////////////////////////////////////
52137 // STRUCTURE
52138 //////////////////////////////////////////////
52139
52140 // a push() operation is in progress.
52141 // the renderer should return a 'style' object that it wishes to
52142 // store on the push stack.
52143 // derived renderers should call the base class' push() method
52144 // to fetch the base style object.
52145 _main.default.Renderer2D.prototype.push = function() {
52146 this.drawingContext.save();
52147
52148 // get the base renderer style
52149 return _main.default.Renderer.prototype.push.apply(this);
52150 };
52151
52152 // a pop() operation is in progress
52153 // the renderer is passed the 'style' object that it returned
52154 // from its push() method.
52155 // derived renderers should pass this object to their base
52156 // class' pop method
52157 _main.default.Renderer2D.prototype.pop = function(style) {
52158 this.drawingContext.restore();
52159 // Re-cache the fill / stroke state
52160 this._cachedFillStyle = this.drawingContext.fillStyle;
52161 this._cachedStrokeStyle = this.drawingContext.strokeStyle;
52162
52163 _main.default.Renderer.prototype.pop.call(this, style);
52164 };
52165 var _default = _main.default.Renderer2D;
52166 exports.default = _default;
52167 },
52168 { '../image/filters': 75, './constants': 43, './main': 54, './p5.Renderer': 57 }
52169 ],
52170 59: [
52171 function(_dereq_, module, exports) {
52172 'use strict';
52173
52174 var _main = _interopRequireDefault(_dereq_('./main'));
52175 function _interopRequireDefault(obj) {
52176 return obj && obj.__esModule ? obj : { default: obj };
52177 }
52178
52179 _main.default.prototype._promisePreloads = [
52180 /* Example object
52181 {
52182 target: p5.prototype, // The target object to have the method modified
52183 method: 'loadXAsync', // The name of the preload function to wrap
52184 addCallbacks: true, // Whether to automatically handle the p5 callbacks
52185 legacyPreloadSetup: { // Optional object to generate a legacy-style preload
52186 method: 'loadX', // The name of the legacy preload function to generate
52187 createBaseObject: function() {
52188 return {};
52189 } // An optional function to create the base object for the legacy preload.
52190 }
52191 }
52192 */
52193 ];
52194
52195 _main.default.prototype.registerPromisePreload = function(setup) {
52196 _main.default.prototype._promisePreloads.push(setup);
52197 };
52198
52199 var initialSetupRan = false;
52200
52201 _main.default.prototype._setupPromisePreloads = function() {
52202 var _iteratorNormalCompletion = true;
52203 var _didIteratorError = false;
52204 var _iteratorError = undefined;
52205 try {
52206 for (
52207 var _iterator = this._promisePreloads[Symbol.iterator](), _step;
52208 !(_iteratorNormalCompletion = (_step = _iterator.next()).done);
52209 _iteratorNormalCompletion = true
52210 ) {
52211 var preloadSetup = _step.value;
52212 var thisValue = this;
52213 var method = preloadSetup.method,
52214 addCallbacks = preloadSetup.addCallbacks,
52215 legacyPreloadSetup = preloadSetup.legacyPreloadSetup;
52216 // Get the target object that the preload gets assigned to by default,
52217 // that is the current object.
52218 var target = preloadSetup.target || this;
52219 var sourceFunction = target[method].bind(target);
52220 // If the target is the p5 prototype, then only set it up on the first run per page
52221 if (target === _main.default.prototype) {
52222 if (initialSetupRan) {
52223 continue;
52224 }
52225 thisValue = null;
52226 sourceFunction = target[method];
52227 }
52228
52229 // Replace the original method with a wrapped version
52230 target[method] = this._wrapPromisePreload(
52231 thisValue,
52232 sourceFunction,
52233 addCallbacks
52234 );
52235
52236 // If a legacy preload is required
52237 if (legacyPreloadSetup) {
52238 // What is the name for this legacy preload
52239 var legacyMethod = legacyPreloadSetup.method;
52240 // Wrap the already wrapped Promise-returning method with the legacy setup
52241 target[legacyMethod] = this._legacyPreloadGenerator(
52242 thisValue,
52243 legacyPreloadSetup,
52244 target[method]
52245 );
52246 }
52247 }
52248 } catch (err) {
52249 _didIteratorError = true;
52250 _iteratorError = err;
52251 } finally {
52252 try {
52253 if (!_iteratorNormalCompletion && _iterator.return != null) {
52254 _iterator.return();
52255 }
52256 } finally {
52257 if (_didIteratorError) {
52258 throw _iteratorError;
52259 }
52260 }
52261 }
52262 initialSetupRan = true;
52263 };
52264
52265 _main.default.prototype._wrapPromisePreload = function(
52266 thisValue,
52267 fn,
52268 addCallbacks
52269 ) {
52270 var replacementFunction = function replacementFunction() {
52271 var _this = this;
52272 // Uses the current preload counting mechanism for now.
52273 this._incrementPreload();
52274 // A variable for the callback function if specified
52275 var callback = null;
52276 // A variable for the errorCallback function if specified
52277 var errorCallback = null;
52278 for (
52279 var _len = arguments.length, args = new Array(_len), _key = 0;
52280 _key < _len;
52281 _key++
52282 ) {
52283 args[_key] = arguments[_key];
52284 }
52285 if (addCallbacks) {
52286 // Loop from the end of the args array, pulling up to two functions off of
52287 // the end and putting them in fns
52288 for (var i = args.length - 1; i >= 0 && !errorCallback; i--) {
52289 if (typeof args[i] !== 'function') {
52290 break;
52291 }
52292 errorCallback = callback;
52293 callback = args.pop();
52294 }
52295 }
52296 // Call the underlying funciton and pass it to Promise.resolve,
52297 // so that even if it didn't return a promise we can still
52298 // act on the result as if it did.
52299 var promise = Promise.resolve(fn.apply(this, args));
52300 // Add the optional callbacks
52301 if (callback) {
52302 promise.then(callback);
52303 }
52304 if (errorCallback) {
52305 promise.catch(errorCallback);
52306 }
52307 // Decrement the preload counter only if the promise resolved
52308 promise.then(function() {
52309 return _this._decrementPreload();
52310 });
52311 // Return the original promise so that neither callback changes the result.
52312 return promise;
52313 };
52314 if (thisValue) {
52315 replacementFunction = replacementFunction.bind(thisValue);
52316 }
52317 return replacementFunction;
52318 };
52319
52320 var objectCreator = function objectCreator() {
52321 return {};
52322 };
52323
52324 _main.default.prototype._legacyPreloadGenerator = function(
52325 thisValue,
52326 legacyPreloadSetup,
52327 fn
52328 ) {
52329 // Create a function that will generate an object before the preload is
52330 // launched. For example, if the object should be an array or be an instance
52331 // of a specific class.
52332 var baseValueGenerator = legacyPreloadSetup.createBaseObject || objectCreator;
52333 var returnedFunction = function returnedFunction() {
52334 var _this2 = this;
52335 // Our then clause needs to run before setup, so we also increment the preload counter
52336 this._incrementPreload();
52337 // Generate the return value based on the generator.
52338 var returnValue = baseValueGenerator.apply(this, arguments);
52339 // Run the original wrapper
52340 fn.apply(this, arguments).then(function(data) {
52341 // Copy each key from the resolved value into returnValue
52342 Object.assign(returnValue, data);
52343 // Decrement the preload counter, to allow setup to continue.
52344 _this2._decrementPreload();
52345 });
52346 return returnValue;
52347 };
52348 if (thisValue) {
52349 returnedFunction = returnedFunction.bind(thisValue);
52350 }
52351 return returnedFunction;
52352 };
52353 },
52354 { './main': 54 }
52355 ],
52356 60: [
52357 function(_dereq_, module, exports) {
52358 'use strict';
52359 Object.defineProperty(exports, '__esModule', { value: true });
52360 exports.default = void 0;
52361
52362 var _main = _interopRequireDefault(_dereq_('./main'));
52363 var constants = _interopRequireWildcard(_dereq_('./constants'));
52364 _dereq_('./p5.Graphics');
52365 _dereq_('./p5.Renderer2D');
52366 _dereq_('../webgl/p5.RendererGL');
52367 function _getRequireWildcardCache() {
52368 if (typeof WeakMap !== 'function') return null;
52369 var cache = new WeakMap();
52370 _getRequireWildcardCache = function _getRequireWildcardCache() {
52371 return cache;
52372 };
52373 return cache;
52374 }
52375 function _interopRequireWildcard(obj) {
52376 if (obj && obj.__esModule) {
52377 return obj;
52378 }
52379 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) {
52380 return { default: obj };
52381 }
52382 var cache = _getRequireWildcardCache();
52383 if (cache && cache.has(obj)) {
52384 return cache.get(obj);
52385 }
52386 var newObj = {};
52387 var hasPropertyDescriptor =
52388 Object.defineProperty && Object.getOwnPropertyDescriptor;
52389 for (var key in obj) {
52390 if (Object.prototype.hasOwnProperty.call(obj, key)) {
52391 var desc = hasPropertyDescriptor
52392 ? Object.getOwnPropertyDescriptor(obj, key)
52393 : null;
52394 if (desc && (desc.get || desc.set)) {
52395 Object.defineProperty(newObj, key, desc);
52396 } else {
52397 newObj[key] = obj[key];
52398 }
52399 }
52400 }
52401 newObj.default = obj;
52402 if (cache) {
52403 cache.set(obj, newObj);
52404 }
52405 return newObj;
52406 }
52407 function _interopRequireDefault(obj) {
52408 return obj && obj.__esModule ? obj : { default: obj };
52409 }
52410 function _typeof(obj) {
52411 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
52412 _typeof = function _typeof(obj) {
52413 return typeof obj;
52414 };
52415 } else {
52416 _typeof = function _typeof(obj) {
52417 return obj &&
52418 typeof Symbol === 'function' &&
52419 obj.constructor === Symbol &&
52420 obj !== Symbol.prototype
52421 ? 'symbol'
52422 : typeof obj;
52423 };
52424 }
52425 return _typeof(obj);
52426 }
52427 var defaultId = 'defaultCanvas0'; // this gets set again in createCanvas
52428 var defaultClass = 'p5Canvas';
52429
52430 /**
52431 * Creates a canvas element in the document, and sets the dimensions of it
52432 * in pixels. This method should be called only once at the start of setup.
52433 * Calling <a href="#/p5/createCanvas">createCanvas</a> more than once in a
52434 * sketch will result in very unpredictable behavior. If you want more than
52435 * one drawing canvas you could use <a href="#/p5/createGraphics">createGraphics</a>
52436 * (hidden by default but it can be shown).
52437 *
52438 * The system variables width and height are set by the parameters passed to this
52439 * function. If <a href="#/p5/createCanvas">createCanvas()</a> is not used, the
52440 * window will be given a default size of 100x100 pixels.
52441 *
52442 * For more ways to position the canvas, see the
52443 * <a href='https://github.com/processing/p5.js/wiki/Positioning-your-canvas'>
52444 * positioning the canvas</a> wiki page.
52445 *
52446 * @method createCanvas
52447 * @param {Number} w width of the canvas
52448 * @param {Number} h height of the canvas
52449 * @param {Constant} [renderer] either P2D or WEBGL
52450 * @return {p5.Renderer}
52451 * @example
52452 * <div>
52453 * <code>
52454 * function setup() {
52455 * createCanvas(100, 50);
52456 * background(153);
52457 * line(0, 0, width, height);
52458 * }
52459 * </code>
52460 * </div>
52461 *
52462 * @alt
52463 * Black line extending from top-left of canvas to bottom right.
52464 */
52465 _main.default.prototype.createCanvas = function(w, h, renderer) {
52466 _main.default._validateParameters('createCanvas', arguments);
52467 //optional: renderer, otherwise defaults to p2d
52468 var r = renderer || constants.P2D;
52469 var c;
52470
52471 if (r === constants.WEBGL) {
52472 c = document.getElementById(defaultId);
52473 if (c) {
52474 //if defaultCanvas already exists
52475 c.parentNode.removeChild(c); //replace the existing defaultCanvas
52476 var thisRenderer = this._renderer;
52477 this._elements = this._elements.filter(function(e) {
52478 return e !== thisRenderer;
52479 });
52480 }
52481 c = document.createElement('canvas');
52482 c.id = defaultId;
52483 c.classList.add(defaultClass);
52484 } else {
52485 if (!this._defaultGraphicsCreated) {
52486 c = document.createElement('canvas');
52487 var i = 0;
52488 while (document.getElementById('defaultCanvas'.concat(i))) {
52489 i++;
52490 }
52491 defaultId = 'defaultCanvas'.concat(i);
52492 c.id = defaultId;
52493 c.classList.add(defaultClass);
52494 } else {
52495 // resize the default canvas if new one is created
52496 c = this.canvas;
52497 }
52498 }
52499
52500 // set to invisible if still in setup (to prevent flashing with manipulate)
52501 if (!this._setupDone) {
52502 c.dataset.hidden = true; // tag to show later
52503 c.style.visibility = 'hidden';
52504 }
52505
52506 if (this._userNode) {
52507 // user input node case
52508 this._userNode.appendChild(c);
52509 } else {
52510 //create main element
52511 if (document.getElementsByTagName('main').length === 0) {
52512 var m = document.createElement('main');
52513 document.body.appendChild(m);
52514 }
52515 //append canvas to main
52516 document.getElementsByTagName('main')[0].appendChild(c);
52517 }
52518
52519 // Init our graphics renderer
52520 //webgl mode
52521 if (r === constants.WEBGL) {
52522 this._setProperty('_renderer', new _main.default.RendererGL(c, this, true));
52523 this._elements.push(this._renderer);
52524 } else {
52525 //P2D mode
52526 if (!this._defaultGraphicsCreated) {
52527 this._setProperty('_renderer', new _main.default.Renderer2D(c, this, true));
52528 this._defaultGraphicsCreated = true;
52529 this._elements.push(this._renderer);
52530 }
52531 }
52532 this._renderer.resize(w, h);
52533 this._renderer._applyDefaults();
52534 return this._renderer;
52535 };
52536
52537 /**
52538 * Resizes the canvas to given width and height. The canvas will be cleared
52539 * and draw will be called immediately, allowing the sketch to re-render itself
52540 * in the resized canvas.
52541 * @method resizeCanvas
52542 * @param {Number} w width of the canvas
52543 * @param {Number} h height of the canvas
52544 * @param {Boolean} [noRedraw] don't redraw the canvas immediately
52545 * @example
52546 * <div class="norender"><code>
52547 * function setup() {
52548 * createCanvas(windowWidth, windowHeight);
52549 * }
52550 *
52551 * function draw() {
52552 * background(0, 100, 200);
52553 * }
52554 *
52555 * function windowResized() {
52556 * resizeCanvas(windowWidth, windowHeight);
52557 * }
52558 * </code></div>
52559 *
52560 * @alt
52561 * No image displayed.
52562 */
52563 _main.default.prototype.resizeCanvas = function(w, h, noRedraw) {
52564 _main.default._validateParameters('resizeCanvas', arguments);
52565 if (this._renderer) {
52566 // save canvas properties
52567 var props = {};
52568 for (var key in this.drawingContext) {
52569 var val = this.drawingContext[key];
52570 if (_typeof(val) !== 'object' && typeof val !== 'function') {
52571 props[key] = val;
52572 }
52573 }
52574 this._renderer.resize(w, h);
52575 this.width = w;
52576 this.height = h;
52577 // reset canvas properties
52578 for (var savedKey in props) {
52579 try {
52580 this.drawingContext[savedKey] = props[savedKey];
52581 } catch (err) {
52582 // ignore read-only property errors
52583 }
52584 }
52585 if (!noRedraw) {
52586 this.redraw();
52587 }
52588 }
52589 };
52590
52591 /**
52592 * Removes the default canvas for a p5 sketch that doesn't require a canvas
52593 * @method noCanvas
52594 * @example
52595 * <div>
52596 * <code>
52597 * function setup() {
52598 * noCanvas();
52599 * }
52600 * </code>
52601 * </div>
52602 *
52603 * @alt
52604 * no image displayed
52605 */
52606 _main.default.prototype.noCanvas = function() {
52607 if (this.canvas) {
52608 this.canvas.parentNode.removeChild(this.canvas);
52609 }
52610 };
52611
52612 /**
52613 * Creates and returns a new p5.Renderer object. Use this class if you need
52614 * to draw into an off-screen graphics buffer. The two parameters define the
52615 * width and height in pixels.
52616 *
52617 * @method createGraphics
52618 * @param {Number} w width of the offscreen graphics buffer
52619 * @param {Number} h height of the offscreen graphics buffer
52620 * @param {Constant} [renderer] either P2D or WEBGL
52621 * undefined defaults to p2d
52622 * @return {p5.Graphics} offscreen graphics buffer
52623 * @example
52624 * <div>
52625 * <code>
52626 * let pg;
52627 * function setup() {
52628 * createCanvas(100, 100);
52629 * pg = createGraphics(100, 100);
52630 * }
52631 *
52632 * function draw() {
52633 * background(200);
52634 * pg.background(100);
52635 * pg.noStroke();
52636 * pg.ellipse(pg.width / 2, pg.height / 2, 50, 50);
52637 * image(pg, 50, 50);
52638 * image(pg, 0, 0, 50, 50);
52639 * }
52640 * </code>
52641 * </div>
52642 *
52643 * @alt
52644 * 4 grey squares alternating light and dark grey. White quarter circle mid-left.
52645 */
52646 _main.default.prototype.createGraphics = function(w, h, renderer) {
52647 _main.default._validateParameters('createGraphics', arguments);
52648 return new _main.default.Graphics(w, h, renderer, this);
52649 };
52650
52651 /**
52652 * Blends the pixels in the display window according to the defined mode.
52653 * There is a choice of the following modes to blend the source pixels (A)
52654 * with the ones of pixels already in the display window (B):
52655 * <ul>
52656 * <li><code>BLEND</code> - linear interpolation of colours: C =
52657 * A\*factor + B. <b>This is the default blending mode.</b></li>
52658 * <li><code>ADD</code> - sum of A and B</li>
52659 * <li><code>DARKEST</code> - only the darkest colour succeeds: C =
52660 * min(A\*factor, B).</li>
52661 * <li><code>LIGHTEST</code> - only the lightest colour succeeds: C =
52662 * max(A\*factor, B).</li>
52663 * <li><code>DIFFERENCE</code> - subtract colors from underlying image.</li>
52664 * <li><code>EXCLUSION</code> - similar to <code>DIFFERENCE</code>, but less
52665 * extreme.</li>
52666 * <li><code>MULTIPLY</code> - multiply the colors, result will always be
52667 * darker.</li>
52668 * <li><code>SCREEN</code> - opposite multiply, uses inverse values of the
52669 * colors.</li>
52670 * <li><code>REPLACE</code> - the pixels entirely replace the others and
52671 * don't utilize alpha (transparency) values.</li>
52672 * <li><code>REMOVE</code> - removes pixels from B with the alpha strength of A.</li>
52673 * <li><code>OVERLAY</code> - mix of <code>MULTIPLY</code> and <code>SCREEN
52674 * </code>. Multiplies dark values, and screens light values. <em>(2D)</em></li>
52675 * <li><code>HARD_LIGHT</code> - <code>SCREEN</code> when greater than 50%
52676 * gray, <code>MULTIPLY</code> when lower. <em>(2D)</em></li>
52677 * <li><code>SOFT_LIGHT</code> - mix of <code>DARKEST</code> and
52678 * <code>LIGHTEST</code>. Works like <code>OVERLAY</code>, but not as harsh. <em>(2D)</em>
52679 * </li>
52680 * <li><code>DODGE</code> - lightens light tones and increases contrast,
52681 * ignores darks. <em>(2D)</em></li>
52682 * <li><code>BURN</code> - darker areas are applied, increasing contrast,
52683 * ignores lights. <em>(2D)</em></li>
52684 * <li><code>SUBTRACT</code> - remainder of A and B <em>(3D)</em></li>
52685 * </ul>
52686 *
52687 * <em>(2D)</em> indicates that this blend mode <b>only</b> works in the 2D renderer.<br>
52688 * <em>(3D)</em> indicates that this blend mode <b>only</b> works in the WEBGL renderer.
52689 *
52690 * @method blendMode
52691 * @param {Constant} mode blend mode to set for canvas.
52692 * either BLEND, DARKEST, LIGHTEST, DIFFERENCE, MULTIPLY,
52693 * EXCLUSION, SCREEN, REPLACE, OVERLAY, HARD_LIGHT,
52694 * SOFT_LIGHT, DODGE, BURN, ADD, REMOVE or SUBTRACT
52695 * @example
52696 * <div>
52697 * <code>
52698 * blendMode(LIGHTEST);
52699 * strokeWeight(30);
52700 * stroke(80, 150, 255);
52701 * line(25, 25, 75, 75);
52702 * stroke(255, 50, 50);
52703 * line(75, 25, 25, 75);
52704 * </code>
52705 * </div>
52706 *
52707 * <div>
52708 * <code>
52709 * blendMode(MULTIPLY);
52710 * strokeWeight(30);
52711 * stroke(80, 150, 255);
52712 * line(25, 25, 75, 75);
52713 * stroke(255, 50, 50);
52714 * line(75, 25, 25, 75);
52715 * </code>
52716 * </div>
52717 *
52718 * @alt
52719 * translucent image thick red & blue diagonal rounded lines intersecting center
52720 * Thick red & blue diagonal rounded lines intersecting center. dark at overlap
52721 */
52722 _main.default.prototype.blendMode = function(mode) {
52723 _main.default._validateParameters('blendMode', arguments);
52724 if (mode === constants.NORMAL) {
52725 // Warning added 3/26/19, can be deleted in future (1.0 release?)
52726 console.warn(
52727 'NORMAL has been deprecated for use in blendMode. defaulting to BLEND instead.'
52728 );
52729
52730 mode = constants.BLEND;
52731 }
52732 this._renderer.blendMode(mode);
52733 };
52734
52735 /**
52736 * The p5.js API provides a lot of functionality for creating graphics, but there is
52737 * some native HTML5 Canvas functionality that is not exposed by p5. You can still call
52738 * it directly using the variable `drawingContext`, as in the example shown. This is
52739 * the equivalent of calling `canvas.getContext('2d');` or `canvas.getContext('webgl');`.
52740 * See this
52741 * <a href="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D">
52742 * reference for the native canvas API</a> for possible drawing functions you can call.
52743 *
52744 * @property drawingContext
52745 * @example
52746 * <div>
52747 * <code>
52748 * function setup() {
52749 * drawingContext.shadowOffsetX = 5;
52750 * drawingContext.shadowOffsetY = -5;
52751 * drawingContext.shadowBlur = 10;
52752 * drawingContext.shadowColor = 'black';
52753 * background(200);
52754 * ellipse(width / 2, height / 2, 50, 50);
52755 * }
52756 * </code>
52757 * </div>
52758 *
52759 * @alt
52760 * white ellipse with shadow blur effect around edges
52761 */ var _default = _main.default;
52762 exports.default = _default;
52763 },
52764 {
52765 '../webgl/p5.RendererGL': 108,
52766 './constants': 43,
52767 './main': 54,
52768 './p5.Graphics': 56,
52769 './p5.Renderer2D': 58
52770 }
52771 ],
52772 61: [
52773 function(_dereq_, module, exports) {
52774 'use strict';
52775 function _typeof(obj) {
52776 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
52777 _typeof = function _typeof(obj) {
52778 return typeof obj;
52779 };
52780 } else {
52781 _typeof = function _typeof(obj) {
52782 return obj &&
52783 typeof Symbol === 'function' &&
52784 obj.constructor === Symbol &&
52785 obj !== Symbol.prototype
52786 ? 'symbol'
52787 : typeof obj;
52788 };
52789 }
52790 return _typeof(obj);
52791 }
52792 Object.defineProperty(exports, '__esModule', { value: true });
52793 exports.default = void 0;
52794
52795 var _main = _interopRequireDefault(_dereq_('../main'));
52796 var constants = _interopRequireWildcard(_dereq_('../constants'));
52797 var _helpers = _interopRequireDefault(_dereq_('../helpers'));
52798 _dereq_('../friendly_errors/fes_core');
52799 _dereq_('../friendly_errors/file_errors');
52800 _dereq_('../friendly_errors/validate_params');
52801 function _getRequireWildcardCache() {
52802 if (typeof WeakMap !== 'function') return null;
52803 var cache = new WeakMap();
52804 _getRequireWildcardCache = function _getRequireWildcardCache() {
52805 return cache;
52806 };
52807 return cache;
52808 }
52809 function _interopRequireWildcard(obj) {
52810 if (obj && obj.__esModule) {
52811 return obj;
52812 }
52813 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) {
52814 return { default: obj };
52815 }
52816 var cache = _getRequireWildcardCache();
52817 if (cache && cache.has(obj)) {
52818 return cache.get(obj);
52819 }
52820 var newObj = {};
52821 var hasPropertyDescriptor =
52822 Object.defineProperty && Object.getOwnPropertyDescriptor;
52823 for (var key in obj) {
52824 if (Object.prototype.hasOwnProperty.call(obj, key)) {
52825 var desc = hasPropertyDescriptor
52826 ? Object.getOwnPropertyDescriptor(obj, key)
52827 : null;
52828 if (desc && (desc.get || desc.set)) {
52829 Object.defineProperty(newObj, key, desc);
52830 } else {
52831 newObj[key] = obj[key];
52832 }
52833 }
52834 }
52835 newObj.default = obj;
52836 if (cache) {
52837 cache.set(obj, newObj);
52838 }
52839 return newObj;
52840 }
52841 function _interopRequireDefault(obj) {
52842 return obj && obj.__esModule ? obj : { default: obj };
52843 }
52844 /**
52845 * @module Shape
52846 * @submodule 2D Primitives
52847 * @for p5
52848 * @requires core
52849 * @requires constants
52850 */ /**
52851 * This function does 3 things:
52852 *
52853 * 1. Bounds the desired start/stop angles for an arc (in radians) so that:
52854 *
52855 * 0 <= start < TWO_PI ; start <= stop < start + TWO_PI
52856 *
52857 * This means that the arc rendering functions don't have to be concerned
52858 * with what happens if stop is smaller than start, or if the arc 'goes
52859 * round more than once', etc.: they can just start at start and increase
52860 * until stop and the correct arc will be drawn.
52861 *
52862 * 2. Optionally adjusts the angles within each quadrant to counter the naive
52863 * scaling of the underlying ellipse up from the unit circle. Without
52864 * this, the angles become arbitrary when width != height: 45 degrees
52865 * might be drawn at 5 degrees on a 'wide' ellipse, or at 85 degrees on
52866 * a 'tall' ellipse.
52867 *
52868 * 3. Flags up when start and stop correspond to the same place on the
52869 * underlying ellipse. This is useful if you want to do something special
52870 * there (like rendering a whole ellipse instead).
52871 */ _main.default.prototype._normalizeArcAngles = function(
52872 start,
52873 stop,
52874 width,
52875 height,
52876 correctForScaling
52877 ) {
52878 var epsilon = 0.00001; // Smallest visible angle on displays up to 4K.
52879 var separation;
52880
52881 // The order of the steps is important here: each one builds upon the
52882 // adjustments made in the steps that precede it.
52883
52884 // Constrain both start and stop to [0,TWO_PI).
52885 start = start - constants.TWO_PI * Math.floor(start / constants.TWO_PI);
52886 stop = stop - constants.TWO_PI * Math.floor(stop / constants.TWO_PI);
52887
52888 // Get the angular separation between the requested start and stop points.
52889 //
52890 // Technically this separation only matches what gets drawn if
52891 // correctForScaling is enabled. We could add a more complicated calculation
52892 // for when the scaling is uncorrected (in which case the drawn points could
52893 // end up pushed together or pulled apart quite dramatically relative to what
52894 // was requested), but it would make things more opaque for little practical
52895 // benefit.
52896 //
52897 // (If you do disable correctForScaling and find that correspondToSamePoint
52898 // is set too aggressively, the easiest thing to do is probably to just make
52899 // epsilon smaller...)
52900 separation = Math.min(
52901 Math.abs(start - stop),
52902 constants.TWO_PI - Math.abs(start - stop)
52903 );
52904
52905 // Optionally adjust the angles to counter linear scaling.
52906 if (correctForScaling) {
52907 if (start <= constants.HALF_PI) {
52908 start = Math.atan(width / height * Math.tan(start));
52909 } else if (start > constants.HALF_PI && start <= 3 * constants.HALF_PI) {
52910 start = Math.atan(width / height * Math.tan(start)) + constants.PI;
52911 } else {
52912 start = Math.atan(width / height * Math.tan(start)) + constants.TWO_PI;
52913 }
52914 if (stop <= constants.HALF_PI) {
52915 stop = Math.atan(width / height * Math.tan(stop));
52916 } else if (stop > constants.HALF_PI && stop <= 3 * constants.HALF_PI) {
52917 stop = Math.atan(width / height * Math.tan(stop)) + constants.PI;
52918 } else {
52919 stop = Math.atan(width / height * Math.tan(stop)) + constants.TWO_PI;
52920 }
52921 }
52922
52923 // Ensure that start <= stop < start + TWO_PI.
52924 if (start > stop) {
52925 stop += constants.TWO_PI;
52926 }
52927
52928 return {
52929 start: start,
52930 stop: stop,
52931 correspondToSamePoint: separation < epsilon
52932 };
52933 };
52934
52935 /**
52936 * Draw an arc to the screen. If called with only x, y, w, h, start and stop,
52937 * the arc will be drawn and filled as an open pie segment. If a mode parameter
52938 * is provided, the arc will be filled like an open semi-circle (OPEN), a closed
52939 * semi-circle (CHORD), or as a closed pie segment (PIE). The origin may be changed
52940 * with the <a href="#/p5/ellipseMode">ellipseMode()</a> function.
52941 *
52942 * The arc is always drawn clockwise from wherever start falls to wherever stop
52943 * falls on the ellipse.Adding or subtracting TWO_PI to either angle does not
52944 * change where they fall. If both start and stop fall at the same place, a full
52945 * ellipse will be drawn. Be aware that the y-axis increases in the downward
52946 * direction, therefore angles are measured clockwise from the positive
52947 * x-direction ("3 o'clock").
52948 *
52949 * @method arc
52950 * @param {Number} x x-coordinate of the arc's ellipse
52951 * @param {Number} y y-coordinate of the arc's ellipse
52952 * @param {Number} w width of the arc's ellipse by default
52953 * @param {Number} h height of the arc's ellipse by default
52954 * @param {Number} start angle to start the arc, specified in radians
52955 * @param {Number} stop angle to stop the arc, specified in radians
52956 * @param {Constant} [mode] optional parameter to determine the way of drawing
52957 * the arc. either CHORD, PIE or OPEN
52958 * @param {Number} [detail] optional parameter for WebGL mode only. This is to
52959 * specify the number of vertices that makes up the
52960 * perimeter of the arc. Default value is 25.
52961 * @chainable
52962 *
52963 * @example
52964 * <div>
52965 * <code>
52966 * arc(50, 55, 50, 50, 0, HALF_PI);
52967 * noFill();
52968 * arc(50, 55, 60, 60, HALF_PI, PI);
52969 * arc(50, 55, 70, 70, PI, PI + QUARTER_PI);
52970 * arc(50, 55, 80, 80, PI + QUARTER_PI, TWO_PI);
52971 * </code>
52972 * </div>
52973 *
52974 * <div>
52975 * <code>
52976 * arc(50, 50, 80, 80, 0, PI + QUARTER_PI);
52977 * </code>
52978 * </div>
52979 *
52980 * <div>
52981 * <code>
52982 * arc(50, 50, 80, 80, 0, PI + QUARTER_PI, OPEN);
52983 * </code>
52984 * </div>
52985 *
52986 * <div>
52987 * <code>
52988 * arc(50, 50, 80, 80, 0, PI + QUARTER_PI, CHORD);
52989 * </code>
52990 * </div>
52991 *
52992 * <div>
52993 * <code>
52994 * arc(50, 50, 80, 80, 0, PI + QUARTER_PI, PIE);
52995 * </code>
52996 * </div>
52997 *
52998 * @alt
52999 *shattered outline of an ellipse with a quarter of a white circle bottom-right.
53000 *white ellipse with top right quarter missing.
53001 *white ellipse with black outline with top right missing.
53002 *white ellipse with top right missing with black outline around shape.
53003 *white ellipse with top right quarter missing with black outline around the shape.
53004 */
53005 _main.default.prototype.arc = function(x, y, w, h, start, stop, mode, detail) {
53006 _main.default._validateParameters('arc', arguments);
53007
53008 // if the current stroke and fill settings wouldn't result in something
53009 // visible, exit immediately
53010 if (!this._renderer._doStroke && !this._renderer._doFill) {
53011 return this;
53012 }
53013
53014 if (start === stop) {
53015 return this;
53016 }
53017
53018 start = this._toRadians(start);
53019 stop = this._toRadians(stop);
53020
53021 // p5 supports negative width and heights for ellipses
53022 w = Math.abs(w);
53023 h = Math.abs(h);
53024
53025 var vals = _helpers.default.modeAdjust(x, y, w, h, this._renderer._ellipseMode);
53026 var angles = this._normalizeArcAngles(start, stop, vals.w, vals.h, true);
53027
53028 if (angles.correspondToSamePoint) {
53029 // If the arc starts and ends at (near enough) the same place, we choose to
53030 // draw an ellipse instead. This is preferable to faking an ellipse (by
53031 // making stop ever-so-slightly less than start + TWO_PI) because the ends
53032 // join up to each other rather than at a vertex at the centre (leaving
53033 // an unwanted spike in the stroke/fill).
53034 this._renderer.ellipse([vals.x, vals.y, vals.w, vals.h, detail]);
53035 } else {
53036 this._renderer.arc(
53037 vals.x,
53038 vals.y,
53039 vals.w,
53040 vals.h,
53041 angles.start, // [0, TWO_PI)
53042 angles.stop, // [start, start + TWO_PI)
53043 mode,
53044 detail
53045 );
53046 }
53047
53048 return this;
53049 };
53050
53051 /**
53052 * Draws an ellipse (oval) to the screen. By default, the first two parameters
53053 * set the location of the center of the ellipse, and the third and fourth
53054 * parameters set the shape's width and height. If no height is specified, the
53055 * value of width is used for both the width and height. If a negative height or
53056 * width is specified, the absolute value is taken.
53057 *
53058 * An ellipse with equal width and height is a circle.The origin may be changed
53059 * with the <a href="#/p5/ellipseMode">ellipseMode()</a> function.
53060 *
53061 * @method ellipse
53062 * @param {Number} x x-coordinate of the center of ellipse.
53063 * @param {Number} y y-coordinate of the center of ellipse.
53064 * @param {Number} w width of the ellipse.
53065 * @param {Number} [h] height of the ellipse.
53066 * @chainable
53067 * @example
53068 * <div>
53069 * <code>
53070 * ellipse(56, 46, 55, 55);
53071 * </code>
53072 * </div>
53073 *
53074 * @alt
53075 *white ellipse with black outline in middle-right of canvas that is 55x55
53076 */
53077
53078 /**
53079 * @method ellipse
53080 * @param {Number} x
53081 * @param {Number} y
53082 * @param {Number} w
53083 * @param {Number} h
53084 * @param {Integer} detail number of radial sectors to draw (for WebGL mode)
53085 */
53086 _main.default.prototype.ellipse = function(x, y, w, h, detailX) {
53087 _main.default._validateParameters('ellipse', arguments);
53088 return this._renderEllipse.apply(this, arguments);
53089 };
53090
53091 /**
53092 * Draws a circle to the screen. A circle is a simple closed shape.It is the set
53093 * of all points in a plane that are at a given distance from a given point,
53094 * the centre.This function is a special case of the ellipse() function, where
53095 * the width and height of the ellipse are the same. Height and width of the
53096 * ellipse correspond to the diameter of the circle. By default, the first two
53097 * parameters set the location of the centre of the circle, the third sets the
53098 * diameter of the circle.
53099 *
53100 * @method circle
53101 * @param {Number} x x-coordinate of the centre of the circle.
53102 * @param {Number} y y-coordinate of the centre of the circle.
53103 * @param {Number} d diameter of the circle.
53104 * @chainable
53105 * @example
53106 * <div>
53107 * <code>
53108 * // Draw a circle at location (30, 30) with a diameter of 20.
53109 * circle(30, 30, 20);
53110 * </code>
53111 * </div>
53112 *
53113 * @alt
53114 * white circle with black outline in mid of canvas that is 55x55.
53115 */
53116 _main.default.prototype.circle = function() {
53117 _main.default._validateParameters('circle', arguments);
53118 var args = Array.prototype.slice.call(arguments, 0, 2);
53119 args.push(arguments[2]);
53120 args.push(arguments[2]);
53121 return this._renderEllipse.apply(this, args);
53122 };
53123
53124 // internal method for drawing ellipses (without parameter validation)
53125 _main.default.prototype._renderEllipse = function(x, y, w, h, detailX) {
53126 // if the current stroke and fill settings wouldn't result in something
53127 // visible, exit immediately
53128 if (!this._renderer._doStroke && !this._renderer._doFill) {
53129 return this;
53130 }
53131
53132 // p5 supports negative width and heights for rects
53133 if (w < 0) {
53134 w = Math.abs(w);
53135 }
53136
53137 if (typeof h === 'undefined') {
53138 // Duplicate 3rd argument if only 3 given.
53139 h = w;
53140 } else if (h < 0) {
53141 h = Math.abs(h);
53142 }
53143
53144 var vals = _helpers.default.modeAdjust(x, y, w, h, this._renderer._ellipseMode);
53145 this._renderer.ellipse([vals.x, vals.y, vals.w, vals.h, detailX]);
53146
53147 return this;
53148 };
53149
53150 /**
53151 * Draws a line (a direct path between two points) to the screen. If called with
53152 * only 4 parameters, it will draw a line in 2D with a default width of 1 pixel.
53153 * This width can be modified by using the <a href="#/p5/strokeWeight">
53154 * strokeWeight()</a> function. A line cannot be filled, therefore the <a
53155 * href="#/p5/fill">fill()</a> function will not affect the color of a line. So to
53156 * color a line, use the <a href="#/p5/stroke">stroke()</a> function.
53157 *
53158 * @method line
53159 * @param {Number} x1 the x-coordinate of the first point
53160 * @param {Number} y1 the y-coordinate of the first point
53161 * @param {Number} x2 the x-coordinate of the second point
53162 * @param {Number} y2 the y-coordinate of the second point
53163 * @chainable
53164 * @example
53165 * <div>
53166 * <code>
53167 * line(30, 20, 85, 75);
53168 * </code>
53169 * </div>
53170 *
53171 * <div>
53172 * <code>
53173 * line(30, 20, 85, 20);
53174 * stroke(126);
53175 * line(85, 20, 85, 75);
53176 * stroke(255);
53177 * line(85, 75, 30, 75);
53178 * </code>
53179 * </div>
53180 *
53181 * @alt
53182 * An example showing a line 78 pixels long running from mid-top to bottom-right of canvas.
53183 * An example showing 3 lines of various stroke sizes. Form top, bottom and right sides of a square.
53184 */
53185
53186 /**
53187 * @method line
53188 * @param {Number} x1
53189 * @param {Number} y1
53190 * @param {Number} z1 the z-coordinate of the first point
53191 * @param {Number} x2
53192 * @param {Number} y2
53193 * @param {Number} z2 the z-coordinate of the second point
53194 * @chainable
53195 */
53196 _main.default.prototype.line = function() {
53197 for (
53198 var _len = arguments.length, args = new Array(_len), _key = 0;
53199 _key < _len;
53200 _key++
53201 ) {
53202 args[_key] = arguments[_key];
53203 }
53204 _main.default._validateParameters('line', args);
53205
53206 if (this._renderer._doStroke) {
53207 var _this$_renderer;
53208 (_this$_renderer = this._renderer).line.apply(_this$_renderer, args);
53209 }
53210
53211 return this;
53212 };
53213
53214 /**
53215 * Draws a point, a coordinate in space at the dimension of one pixel.
53216 * The first parameter is the horizontal value for the point, the second
53217 * param is the vertical value for the point. The color of the point is
53218 * changed with the <a href="#/p5/stroke">stroke()</a> function. The size of the point
53219 * can be changed with the <a href="#/p5/strokeWeight">strokeWeight()</a> function.
53220 *
53221 * @method point
53222 * @param {Number} x the x-coordinate
53223 * @param {Number} y the y-coordinate
53224 * @param {Number} [z] the z-coordinate (for WebGL mode)
53225 * @chainable
53226 * @example
53227 * <div>
53228 * <code>
53229 * point(30, 20);
53230 * point(85, 20);
53231 * point(85, 75);
53232 * point(30, 75);
53233 * </code>
53234 * </div>
53235 *
53236 * <div>
53237 * <code>
53238 * point(30, 20);
53239 * point(85, 20);
53240 * stroke('purple'); // Change the color
53241 * strokeWeight(10); // Make the points 10 pixels in size
53242 * point(85, 75);
53243 * point(30, 75);
53244 * </code>
53245 * </div>
53246 *
53247 * <div>
53248 * <code>
53249 * let a = createVector(10, 10);
53250 * point(a);
53251 * let b = createVector(10, 20);
53252 * point(b);
53253 * point(createVector(20, 10));
53254 * point(createVector(20, 20));
53255 * </code>
53256 * </div>
53257 *
53258 * @alt
53259 * 4 points centered in the middle-right of the canvas.
53260 * 2 large points and 2 large purple points centered in the middle-right of the canvas.
53261 * Vertices of a square of length 10 pixels towards the top-left of the canvas.
53262 */
53263
53264 /**
53265 * @method point
53266 * @param {p5.Vector} coordinate_vector the coordinate vector
53267 * @chainable
53268 */
53269 _main.default.prototype.point = function() {
53270 for (
53271 var _len2 = arguments.length, args = new Array(_len2), _key2 = 0;
53272 _key2 < _len2;
53273 _key2++
53274 ) {
53275 args[_key2] = arguments[_key2];
53276 }
53277 _main.default._validateParameters('point', args);
53278
53279 if (this._renderer._doStroke) {
53280 if (args.length === 1 && args[0] instanceof _main.default.Vector) {
53281 this._renderer.point.call(this._renderer, args[0].x, args[0].y, args[0].z);
53282 } else {
53283 var _this$_renderer2;
53284 (_this$_renderer2 = this._renderer).point.apply(_this$_renderer2, args);
53285 }
53286 }
53287
53288 return this;
53289 };
53290
53291 /**
53292 * Draws a quad on the canvas. A quad is a quadrilateral, a four sided polygon. It is
53293 * similar to a rectangle, but the angles between its edges are not
53294 * constrained to ninety degrees. The first pair of parameters (x1,y1)
53295 * sets the first vertex and the subsequent pairs should proceed
53296 * clockwise or counter-clockwise around the defined shape.
53297 * z-arguments only work when quad() is used in WEBGL mode.
53298 *
53299 * @method quad
53300 * @param {Number} x1 the x-coordinate of the first point
53301 * @param {Number} y1 the y-coordinate of the first point
53302 * @param {Number} x2 the x-coordinate of the second point
53303 * @param {Number} y2 the y-coordinate of the second point
53304 * @param {Number} x3 the x-coordinate of the third point
53305 * @param {Number} y3 the y-coordinate of the third point
53306 * @param {Number} x4 the x-coordinate of the fourth point
53307 * @param {Number} y4 the y-coordinate of the fourth point
53308 * @chainable
53309 * @example
53310 * <div>
53311 * <code>
53312 * quad(38, 31, 86, 20, 69, 63, 30, 76);
53313 * </code>
53314 * </div>
53315 *
53316 * @alt
53317 *irregular white quadrilateral shape with black outline mid-right of canvas.
53318 */
53319 /**
53320 * @method quad
53321 * @param {Number} x1
53322 * @param {Number} y1
53323 * @param {Number} z1 the z-coordinate of the first point
53324 * @param {Number} x2
53325 * @param {Number} y2
53326 * @param {Number} z2 the z-coordinate of the second point
53327 * @param {Number} x3
53328 * @param {Number} y3
53329 * @param {Number} z3 the z-coordinate of the third point
53330 * @param {Number} x4
53331 * @param {Number} y4
53332 * @param {Number} z4 the z-coordinate of the fourth point
53333 * @chainable
53334 */
53335 _main.default.prototype.quad = function() {
53336 for (
53337 var _len3 = arguments.length, args = new Array(_len3), _key3 = 0;
53338 _key3 < _len3;
53339 _key3++
53340 ) {
53341 args[_key3] = arguments[_key3];
53342 }
53343 _main.default._validateParameters('quad', args);
53344
53345 if (this._renderer._doStroke || this._renderer._doFill) {
53346 if (this._renderer.isP3D && args.length !== 12) {
53347 // if 3D and we weren't passed 12 args, assume Z is 0
53348 // prettier-ignore
53349 this._renderer.quad.call(
53350 this._renderer,
53351 args[0], args[1], 0,
53352 args[2], args[3], 0,
53353 args[4], args[5], 0,
53354 args[6], args[7], 0);
53355 } else {
53356 var _this$_renderer3;
53357 (_this$_renderer3 = this._renderer).quad.apply(_this$_renderer3, args);
53358 }
53359 }
53360
53361 return this;
53362 };
53363
53364 /**
53365 * Draws a rectangle on the canvas. A rectangle is a four-sided closed shape with
53366 * every angle at ninety degrees. By default, the first two parameters set
53367 * the location of the upper-left corner, the third sets the width, and the
53368 * fourth sets the height. The way these parameters are interpreted, may be
53369 * changed with the <a href="#/p5/rectMode">rectMode()</a> function.
53370 *
53371 * The fifth, sixth, seventh and eighth parameters, if specified,
53372 * determine corner radius for the top-left, top-right, lower-right and
53373 * lower-left corners, respectively. An omitted corner radius parameter is set
53374 * to the value of the previously specified radius value in the parameter list.
53375 *
53376 * @method rect
53377 * @param {Number} x x-coordinate of the rectangle.
53378 * @param {Number} y y-coordinate of the rectangle.
53379 * @param {Number} w width of the rectangle.
53380 * @param {Number} [h] height of the rectangle.
53381 * @param {Number} [tl] optional radius of top-left corner.
53382 * @param {Number} [tr] optional radius of top-right corner.
53383 * @param {Number} [br] optional radius of bottom-right corner.
53384 * @param {Number} [bl] optional radius of bottom-left corner.
53385 * @chainable
53386 * @example
53387 * <div>
53388 * <code>
53389 * // Draw a rectangle at location (30, 20) with a width and height of 55.
53390 * rect(30, 20, 55, 55);
53391 * </code>
53392 * </div>
53393 *
53394 * <div>
53395 * <code>
53396 * // Draw a rectangle with rounded corners, each having a radius of 20.
53397 * rect(30, 20, 55, 55, 20);
53398 * </code>
53399 * </div>
53400 *
53401 * <div>
53402 * <code>
53403 * // Draw a rectangle with rounded corners having the following radii:
53404 * // top-left = 20, top-right = 15, bottom-right = 10, bottom-left = 5.
53405 * rect(30, 20, 55, 55, 20, 15, 10, 5);
53406 * </code>
53407 * </div>
53408 *
53409 * @alt
53410 * 55x55 white rect with black outline in mid-right of canvas.
53411 * 55x55 white rect with black outline and rounded edges in mid-right of canvas.
53412 * 55x55 white rect with black outline and rounded edges of different radii.
53413 */
53414
53415 /**
53416 * @method rect
53417 * @param {Number} x
53418 * @param {Number} y
53419 * @param {Number} w
53420 * @param {Number} h
53421 * @param {Integer} [detailX] number of segments in the x-direction (for WebGL mode)
53422 * @param {Integer} [detailY] number of segments in the y-direction (for WebGL mode)
53423 * @chainable
53424 */
53425 _main.default.prototype.rect = function() {
53426 _main.default._validateParameters('rect', arguments);
53427 return this._renderRect.apply(this, arguments);
53428 };
53429
53430 /**
53431 * Draws a square to the screen. A square is a four-sided shape with every angle
53432 * at ninety degrees, and equal side size. This function is a special case of the
53433 * rect() function, where the width and height are the same, and the parameter
53434 * is called "s" for side size. By default, the first two parameters set the
53435 * location of the upper-left corner, the third sets the side size of the square.
53436 * The way these parameters are interpreted, may be changed with the <a
53437 * href="#/p5/rectMode">rectMode()</a> function.
53438 *
53439 * The fourth, fifth, sixth and seventh parameters, if specified,
53440 * determine corner radius for the top-left, top-right, lower-right and
53441 * lower-left corners, respectively. An omitted corner radius parameter is set
53442 * to the value of the previously specified radius value in the parameter list.
53443 *
53444 * @method square
53445 * @param {Number} x x-coordinate of the square.
53446 * @param {Number} y y-coordinate of the square.
53447 * @param {Number} s side size of the square.
53448 * @param {Number} [tl] optional radius of top-left corner.
53449 * @param {Number} [tr] optional radius of top-right corner.
53450 * @param {Number} [br] optional radius of bottom-right corner.
53451 * @param {Number} [bl] optional radius of bottom-left corner.
53452 * @chainable
53453 * @example
53454 * <div>
53455 * <code>
53456 * // Draw a square at location (30, 20) with a side size of 55.
53457 * square(30, 20, 55);
53458 * </code>
53459 * </div>
53460 *
53461 * <div>
53462 * <code>
53463 * // Draw a square with rounded corners, each having a radius of 20.
53464 * square(30, 20, 55, 20);
53465 * </code>
53466 * </div>
53467 *
53468 * <div>
53469 * <code>
53470 * // Draw a square with rounded corners having the following radii:
53471 * // top-left = 20, top-right = 15, bottom-right = 10, bottom-left = 5.
53472 * square(30, 20, 55, 20, 15, 10, 5);
53473 * </code>
53474 * </div>
53475 *
53476 * @alt
53477 * 55x55 white square with black outline in mid-right of canvas.
53478 * 55x55 white square with black outline and rounded edges in mid-right of canvas.
53479 * 55x55 white square with black outline and rounded edges of different radii.
53480 */
53481 _main.default.prototype.square = function(x, y, s, tl, tr, br, bl) {
53482 _main.default._validateParameters('square', arguments);
53483 // duplicate width for height in case of square
53484 return this._renderRect.call(this, x, y, s, s, tl, tr, br, bl);
53485 };
53486
53487 // internal method to have renderer draw a rectangle
53488 _main.default.prototype._renderRect = function() {
53489 if (this._renderer._doStroke || this._renderer._doFill) {
53490 // duplicate width for height in case only 3 arguments is provided
53491 if (arguments.length === 3) {
53492 arguments[3] = arguments[2];
53493 }
53494 var vals = _helpers.default.modeAdjust(
53495 arguments[0],
53496 arguments[1],
53497 arguments[2],
53498 arguments[3],
53499 this._renderer._rectMode
53500 );
53501
53502 var args = [vals.x, vals.y, vals.w, vals.h];
53503 // append the additional arguments (either cornder radii, or
53504 // segment details) to the argument list
53505 for (var i = 4; i < arguments.length; i++) {
53506 args[i] = arguments[i];
53507 }
53508 this._renderer.rect(args);
53509 }
53510
53511 return this;
53512 };
53513
53514 /**
53515 * Draws a trangle to the canvas. A triangle is a plane created by connecting
53516 * three points. The first two arguments specify the first point, the middle two
53517 * arguments specify the second point, and the last two arguments specify the
53518 * third point.
53519 *
53520 * @method triangle
53521 * @param {Number} x1 x-coordinate of the first point
53522 * @param {Number} y1 y-coordinate of the first point
53523 * @param {Number} x2 x-coordinate of the second point
53524 * @param {Number} y2 y-coordinate of the second point
53525 * @param {Number} x3 x-coordinate of the third point
53526 * @param {Number} y3 y-coordinate of the third point
53527 * @chainable
53528 * @example
53529 * <div>
53530 * <code>
53531 * triangle(30, 75, 58, 20, 86, 75);
53532 * </code>
53533 * </div>
53534 *
53535 *@alt
53536 * white triangle with black outline in mid-right of canvas.
53537 */
53538 _main.default.prototype.triangle = function() {
53539 for (
53540 var _len4 = arguments.length, args = new Array(_len4), _key4 = 0;
53541 _key4 < _len4;
53542 _key4++
53543 ) {
53544 args[_key4] = arguments[_key4];
53545 }
53546 _main.default._validateParameters('triangle', args);
53547
53548 if (this._renderer._doStroke || this._renderer._doFill) {
53549 this._renderer.triangle(args);
53550 }
53551
53552 return this;
53553 };
53554 var _default = _main.default;
53555 exports.default = _default;
53556 },
53557 {
53558 '../constants': 43,
53559 '../friendly_errors/fes_core': 46,
53560 '../friendly_errors/file_errors': 47,
53561 '../friendly_errors/validate_params': 49,
53562 '../helpers': 50,
53563 '../main': 54
53564 }
53565 ],
53566 62: [
53567 function(_dereq_, module, exports) {
53568 'use strict';
53569 function _typeof(obj) {
53570 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
53571 _typeof = function _typeof(obj) {
53572 return typeof obj;
53573 };
53574 } else {
53575 _typeof = function _typeof(obj) {
53576 return obj &&
53577 typeof Symbol === 'function' &&
53578 obj.constructor === Symbol &&
53579 obj !== Symbol.prototype
53580 ? 'symbol'
53581 : typeof obj;
53582 };
53583 }
53584 return _typeof(obj);
53585 }
53586 Object.defineProperty(exports, '__esModule', { value: true });
53587 exports.default = void 0;
53588
53589 var _main = _interopRequireDefault(_dereq_('../main'));
53590 var constants = _interopRequireWildcard(_dereq_('../constants'));
53591 function _getRequireWildcardCache() {
53592 if (typeof WeakMap !== 'function') return null;
53593 var cache = new WeakMap();
53594 _getRequireWildcardCache = function _getRequireWildcardCache() {
53595 return cache;
53596 };
53597 return cache;
53598 }
53599 function _interopRequireWildcard(obj) {
53600 if (obj && obj.__esModule) {
53601 return obj;
53602 }
53603 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) {
53604 return { default: obj };
53605 }
53606 var cache = _getRequireWildcardCache();
53607 if (cache && cache.has(obj)) {
53608 return cache.get(obj);
53609 }
53610 var newObj = {};
53611 var hasPropertyDescriptor =
53612 Object.defineProperty && Object.getOwnPropertyDescriptor;
53613 for (var key in obj) {
53614 if (Object.prototype.hasOwnProperty.call(obj, key)) {
53615 var desc = hasPropertyDescriptor
53616 ? Object.getOwnPropertyDescriptor(obj, key)
53617 : null;
53618 if (desc && (desc.get || desc.set)) {
53619 Object.defineProperty(newObj, key, desc);
53620 } else {
53621 newObj[key] = obj[key];
53622 }
53623 }
53624 }
53625 newObj.default = obj;
53626 if (cache) {
53627 cache.set(obj, newObj);
53628 }
53629 return newObj;
53630 }
53631 function _interopRequireDefault(obj) {
53632 return obj && obj.__esModule ? obj : { default: obj };
53633 }
53634 /**
53635 * @module Shape
53636 * @submodule Attributes
53637 * @for p5
53638 * @requires core
53639 * @requires constants
53640 */ /**
53641 * Modifies the location from which ellipses are drawn by changing the way in
53642 * which parameters given to <a href="#/p5/ellipse">ellipse()</a>,
53643 * <a href="#/p5/circle">circle()</a> and <a href="#/p5/arc">arc()</a> are interpreted.
53644 *
53645 * The default mode is CENTER, in which the first two parameters are interpreted
53646 * as the shape's center point's x and y coordinates respectively, while the third
53647 * and fourth parameters are its width and height.
53648 *
53649 * ellipseMode(RADIUS) also uses the first two parameters as the shape's center
53650 * point's x and y coordinates, but uses the third and fourth parameters to
53651 * specify half of the shapes's width and height.
53652 *
53653 * ellipseMode(CORNER) interprets the first two parameters as the upper-left
53654 * corner of the shape, while the third and fourth parameters are its width
53655 * and height.
53656 *
53657 * ellipseMode(CORNERS) interprets the first two parameters as the location of
53658 * one corner of the ellipse's bounding box, and the third and fourth parameters
53659 * as the location of the opposite corner.
53660 *
53661 * The parameter to this method must be written in ALL CAPS because they are
53662 * predefined as constants in ALL CAPS and Javascript is a case-sensitive language.
53663 *
53664 * @method ellipseMode
53665 * @param {Constant} mode either CENTER, RADIUS, CORNER, or CORNERS
53666 * @chainable
53667 * @example
53668 * <div>
53669 * <code>
53670 * // Example showing RADIUS and CENTER ellipsemode with 2 overlaying ellipses
53671 * ellipseMode(RADIUS);
53672 * fill(255);
53673 * ellipse(50, 50, 30, 30); // Outer white ellipse
53674 * ellipseMode(CENTER);
53675 * fill(100);
53676 * ellipse(50, 50, 30, 30); // Inner gray ellipse
53677 * </code>
53678 * </div>
53679 *
53680 * <div>
53681 * <code>
53682 * // Example showing CORNER and CORNERS ellipseMode with 2 overlaying ellipses
53683 * ellipseMode(CORNER);
53684 * fill(255);
53685 * ellipse(25, 25, 50, 50); // Outer white ellipse
53686 * ellipseMode(CORNERS);
53687 * fill(100);
53688 * ellipse(25, 25, 50, 50); // Inner gray ellipse
53689 * </code>
53690 * </div>
53691 *
53692 * @alt
53693 * 60x60 white ellipse and 30x30 grey ellipse with black outlines at center.
53694 * 60x60 white ellipse and 30x30 grey ellipse top-right with black outlines.
53695 */ _main.default.prototype.ellipseMode = function(m) {
53696 _main.default._validateParameters('ellipseMode', arguments);
53697 if (
53698 m === constants.CORNER ||
53699 m === constants.CORNERS ||
53700 m === constants.RADIUS ||
53701 m === constants.CENTER
53702 ) {
53703 this._renderer._ellipseMode = m;
53704 }
53705 return this;
53706 };
53707
53708 /**
53709 * Draws all geometry with jagged (aliased) edges. Note that <a href="#/p5/smooth">smooth()</a> is
53710 * active by default in 2D mode, so it is necessary to call <a href="#/p5/noSmooth">noSmooth()</a> to disable
53711 * smoothing of geometry, images, and fonts. In 3D mode, <a href="#/p5/noSmooth">noSmooth()</a> is enabled
53712 * by default, so it is necessary to call <a href="#/p5/smooth">smooth()</a> if you would like
53713 * smooth (antialiased) edges on your geometry.
53714 *
53715 * @method noSmooth
53716 * @chainable
53717 * @example
53718 * <div>
53719 * <code>
53720 * background(0);
53721 * noStroke();
53722 * smooth();
53723 * ellipse(30, 48, 36, 36);
53724 * noSmooth();
53725 * ellipse(70, 48, 36, 36);
53726 * </code>
53727 * </div>
53728 *
53729 * @alt
53730 * 2 pixelated 36x36 white ellipses to left & right of center, black background
53731 */
53732 _main.default.prototype.noSmooth = function() {
53733 this.setAttributes('antialias', false);
53734 if (!this._renderer.isP3D) {
53735 if ('imageSmoothingEnabled' in this.drawingContext) {
53736 this.drawingContext.imageSmoothingEnabled = false;
53737 }
53738 }
53739 return this;
53740 };
53741
53742 /**
53743 * Modifies the location from which rectangles are drawn by changing the way
53744 * in which parameters given to <a href="#/p5/rect">rect()</a> are interpreted.
53745 *
53746 * The default mode is CORNER, which interprets the first two parameters as the
53747 * upper-left corner of the shape, while the third and fourth parameters are its
53748 * width and height.
53749 *
53750 * rectMode(CORNERS) interprets the first two parameters as the location of
53751 * one of the corner, and the third and fourth parameters as the location of
53752 * the diagonally opposite corner. Note, the rectangle is drawn between the
53753 * coordinates, so it is not neccesary that the first corner be the upper left
53754 * corner.
53755 *
53756 * rectMode(CENTER) interprets the first two parameters as the shape's center
53757 * point, while the third and fourth parameters are its width and height.
53758 *
53759 * rectMode(RADIUS) also uses the first two parameters as the shape's center
53760 * point, but uses the third and fourth parameters to specify half of the shapes's
53761 * width and height respectively.
53762 *
53763 * The parameter to this method must be written in ALL CAPS because they are
53764 * predefined as constants in ALL CAPS and Javascript is a case-sensitive language.
53765 *
53766 * @method rectMode
53767 * @param {Constant} mode either CORNER, CORNERS, CENTER, or RADIUS
53768 * @chainable
53769 * @example
53770 * <div>
53771 * <code>
53772 * rectMode(CORNER);
53773 * fill(255);
53774 * rect(25, 25, 50, 50); // Draw white rectangle using CORNER mode
53775 *
53776 * rectMode(CORNERS);
53777 * fill(100);
53778 * rect(25, 25, 50, 50); // Draw gray rectanle using CORNERS mode
53779 * </code>
53780 * </div>
53781 *
53782 * <div>
53783 * <code>
53784 * rectMode(RADIUS);
53785 * fill(255);
53786 * rect(50, 50, 30, 30); // Draw white rectangle using RADIUS mode
53787 *
53788 * rectMode(CENTER);
53789 * fill(100);
53790 * rect(50, 50, 30, 30); // Draw gray rectangle using CENTER mode
53791 * </code>
53792 * </div>
53793 *
53794 * @alt
53795 * 50x50 white rect at center and 25x25 grey rect in the top left of the other.
53796 * 50x50 white rect at center and 25x25 grey rect in the center of the other.
53797 */
53798 _main.default.prototype.rectMode = function(m) {
53799 _main.default._validateParameters('rectMode', arguments);
53800 if (
53801 m === constants.CORNER ||
53802 m === constants.CORNERS ||
53803 m === constants.RADIUS ||
53804 m === constants.CENTER
53805 ) {
53806 this._renderer._rectMode = m;
53807 }
53808 return this;
53809 };
53810
53811 /**
53812 * Draws all geometry with smooth (anti-aliased) edges. <a href="#/p5/smooth">smooth()</a> will also
53813 * improve image quality of resized images. Note that <a href="#/p5/smooth">smooth()</a> is active by
53814 * default in 2D mode; <a href="#/p5/noSmooth">noSmooth()</a> can be used to disable smoothing of geometry,
53815 * images, and fonts. In 3D mode, <a href="#/p5/noSmooth">noSmooth()</a> is enabled
53816 * by default, so it is necessary to call <a href="#/p5/smooth">smooth()</a> if you would like
53817 * smooth (antialiased) edges on your geometry.
53818 *
53819 * @method smooth
53820 * @chainable
53821 * @example
53822 * <div>
53823 * <code>
53824 * background(0);
53825 * noStroke();
53826 * smooth();
53827 * ellipse(30, 48, 36, 36);
53828 * noSmooth();
53829 * ellipse(70, 48, 36, 36);
53830 * </code>
53831 * </div>
53832 *
53833 * @alt
53834 * 2 pixelated 36x36 white ellipses one left one right of center. On black.
53835 */
53836 _main.default.prototype.smooth = function() {
53837 this.setAttributes('antialias', true);
53838 if (!this._renderer.isP3D) {
53839 if ('imageSmoothingEnabled' in this.drawingContext) {
53840 this.drawingContext.imageSmoothingEnabled = true;
53841 }
53842 }
53843 return this;
53844 };
53845
53846 /**
53847 * Sets the style for rendering line endings. These ends are either rounded,
53848 * squared or extended, each of which specified with the corresponding
53849 * parameters: ROUND, SQUARE and PROJECT. The default cap is ROUND.
53850 *
53851 * The parameter to this method must be written in ALL CAPS because they are
53852 * predefined as constants in ALL CAPS and Javascript is a case-sensitive language.
53853 *
53854 * @method strokeCap
53855 * @param {Constant} cap either ROUND, SQUARE or PROJECT
53856 * @chainable
53857 * @example
53858 * <div>
53859 * <code>
53860 * // Example of different strokeCaps
53861 * strokeWeight(12.0);
53862 * strokeCap(ROUND);
53863 * line(20, 30, 80, 30);
53864 * strokeCap(SQUARE);
53865 * line(20, 50, 80, 50);
53866 * strokeCap(PROJECT);
53867 * line(20, 70, 80, 70);
53868 * </code>
53869 * </div>
53870 *
53871 * @alt
53872 * 3 lines. Top line: rounded ends, mid: squared, bottom:longer squared ends.
53873 */
53874 _main.default.prototype.strokeCap = function(cap) {
53875 _main.default._validateParameters('strokeCap', arguments);
53876 if (
53877 cap === constants.ROUND ||
53878 cap === constants.SQUARE ||
53879 cap === constants.PROJECT
53880 ) {
53881 this._renderer.strokeCap(cap);
53882 }
53883 return this;
53884 };
53885
53886 /**
53887 * Sets the style of the joints which connect line segments. These joints
53888 * are either mitered, beveled or rounded and specified with the
53889 * corresponding parameters MITER, BEVEL and ROUND. The default joint is
53890 * MITER.
53891 *
53892 * The parameter to this method must be written in ALL CAPS because they are
53893 * predefined as constants in ALL CAPS and Javascript is a case-sensitive language.
53894 *
53895 * @method strokeJoin
53896 * @param {Constant} join either MITER, BEVEL, ROUND
53897 * @chainable
53898 * @example
53899 * <div>
53900 * <code>
53901 * // Example of MITER type of joints
53902 * noFill();
53903 * strokeWeight(10.0);
53904 * strokeJoin(MITER);
53905 * beginShape();
53906 * vertex(35, 20);
53907 * vertex(65, 50);
53908 * vertex(35, 80);
53909 * endShape();
53910 * </code>
53911 * </div>
53912 *
53913 * <div>
53914 * <code>
53915 * // Example of BEVEL type of joints
53916 * noFill();
53917 * strokeWeight(10.0);
53918 * strokeJoin(BEVEL);
53919 * beginShape();
53920 * vertex(35, 20);
53921 * vertex(65, 50);
53922 * vertex(35, 80);
53923 * endShape();
53924 * </code>
53925 * </div>
53926 *
53927 * <div>
53928 * <code>
53929 * // Example of ROUND type of joints
53930 * noFill();
53931 * strokeWeight(10.0);
53932 * strokeJoin(ROUND);
53933 * beginShape();
53934 * vertex(35, 20);
53935 * vertex(65, 50);
53936 * vertex(35, 80);
53937 * endShape();
53938 * </code>
53939 * </div>
53940 *
53941 * @alt
53942 * Right-facing arrowhead shape with pointed tip in center of canvas.
53943 * Right-facing arrowhead shape with flat tip in center of canvas.
53944 * Right-facing arrowhead shape with rounded tip in center of canvas.
53945 */
53946 _main.default.prototype.strokeJoin = function(join) {
53947 _main.default._validateParameters('strokeJoin', arguments);
53948 if (
53949 join === constants.ROUND ||
53950 join === constants.BEVEL ||
53951 join === constants.MITER
53952 ) {
53953 this._renderer.strokeJoin(join);
53954 }
53955 return this;
53956 };
53957
53958 /**
53959 * Sets the width of the stroke used for lines, points and the border around
53960 * shapes. All widths are set in units of pixels.
53961 *
53962 * @method strokeWeight
53963 * @param {Number} weight the weight of the stroke (in pixels)
53964 * @chainable
53965 * @example
53966 * <div>
53967 * <code>
53968 * // Example of different stroke weights
53969 * strokeWeight(1); // Default
53970 * line(20, 20, 80, 20);
53971 * strokeWeight(4); // Thicker
53972 * line(20, 40, 80, 40);
53973 * strokeWeight(10); // Beastly
53974 * line(20, 70, 80, 70);
53975 * </code>
53976 * </div>
53977 *
53978 * @alt
53979 * 3 horizontal black lines. Top line: thin, mid: medium, bottom:thick.
53980 */
53981 _main.default.prototype.strokeWeight = function(w) {
53982 _main.default._validateParameters('strokeWeight', arguments);
53983 this._renderer.strokeWeight(w);
53984 return this;
53985 };
53986 var _default = _main.default;
53987 exports.default = _default;
53988 },
53989 { '../constants': 43, '../main': 54 }
53990 ],
53991 63: [
53992 function(_dereq_, module, exports) {
53993 'use strict';
53994 Object.defineProperty(exports, '__esModule', { value: true });
53995 exports.default = void 0;
53996
53997 var _main = _interopRequireDefault(_dereq_('../main'));
53998 _dereq_('../friendly_errors/fes_core');
53999 _dereq_('../friendly_errors/file_errors');
54000 _dereq_('../friendly_errors/validate_params');
54001 function _interopRequireDefault(obj) {
54002 return obj && obj.__esModule ? obj : { default: obj };
54003 }
54004 /**
54005 * @module Shape
54006 * @submodule Curves
54007 * @for p5
54008 * @requires core
54009 */ /**
54010 * Draws a cubic Bezier curve on the screen. These curves are defined by a
54011 * series of anchor and control points. The first two parameters specify
54012 * the first anchor point and the last two parameters specify the other
54013 * anchor point, which become the first and last points on the curve. The
54014 * middle parameters specify the two control points which define the shape
54015 * of the curve. Approximately speaking, control points "pull" the curve
54016 * towards them.
54017 *
54018 * Bezier curves were developed by French automotive engineer Pierre Bezier,
54019 * and are commonly used in computer graphics to define gently sloping curves.
54020 * See also <a href="#/p5/curve">curve()</a>.
54021 *
54022 * @method bezier
54023 * @param {Number} x1 x-coordinate for the first anchor point
54024 * @param {Number} y1 y-coordinate for the first anchor point
54025 * @param {Number} x2 x-coordinate for the first control point
54026 * @param {Number} y2 y-coordinate for the first control point
54027 * @param {Number} x3 x-coordinate for the second control point
54028 * @param {Number} y3 y-coordinate for the second control point
54029 * @param {Number} x4 x-coordinate for the second anchor point
54030 * @param {Number} y4 y-coordinate for the second anchor point
54031 * @chainable
54032 * @example
54033 * <div>
54034 * <code>
54035 * noFill();
54036 * stroke(255, 102, 0);
54037 * line(85, 20, 10, 10);
54038 * line(90, 90, 15, 80);
54039 * stroke(0, 0, 0);
54040 * bezier(85, 20, 10, 10, 90, 90, 15, 80);
54041 * </code>
54042 * </div>
54043 *
54044 * <div>
54045 * <code>
54046 * background(0, 0, 0);
54047 * noFill();
54048 * stroke(255);
54049 * bezier(250, 250, 0, 100, 100, 0, 100, 0, 0, 0, 100, 0);
54050 * </code>
54051 * </div>
54052 *
54053 * @alt
54054 * stretched black s-shape in center with orange lines extending from end points.
54055 * a white colored curve on black background from the upper-right corner to the lower right corner.
54056 */ /**
54057 * @method bezier
54058 * @param {Number} x1
54059 * @param {Number} y1
54060 * @param {Number} z1 z-coordinate for the first anchor point
54061 * @param {Number} x2
54062 * @param {Number} y2
54063 * @param {Number} z2 z-coordinate for the first control point
54064 * @param {Number} x3
54065 * @param {Number} y3
54066 * @param {Number} z3 z-coordinate for the second control point
54067 * @param {Number} x4
54068 * @param {Number} y4
54069 * @param {Number} z4 z-coordinate for the second anchor point
54070 * @chainable
54071 */ _main.default.prototype.bezier = function() {
54072 var _this$_renderer;
54073 for (
54074 var _len = arguments.length, args = new Array(_len), _key = 0;
54075 _key < _len;
54076 _key++
54077 ) {
54078 args[_key] = arguments[_key];
54079 }
54080 _main.default._validateParameters('bezier', args);
54081
54082 // if the current stroke and fill settings wouldn't result in something
54083 // visible, exit immediately
54084 if (!this._renderer._doStroke && !this._renderer._doFill) {
54085 return this;
54086 }
54087
54088 (_this$_renderer = this._renderer).bezier.apply(_this$_renderer, args);
54089
54090 return this;
54091 };
54092
54093 /**
54094 * Sets the resolution at which Bezier's curve is displayed. The default value is 20.
54095 *
54096 * Note, This function is only useful when using the WEBGL renderer
54097 * as the default canvas renderer does not use this information.
54098 *
54099 * @method bezierDetail
54100 * @param {Number} detail resolution of the curves
54101 * @chainable
54102 * @example
54103 * <div modernizr='webgl'>
54104 * <code>
54105 * function setup() {
54106 * createCanvas(100, 100, WEBGL);
54107 * noFill();
54108 * bezierDetail(5);
54109 * }
54110 *
54111 * function draw() {
54112 * background(200);
54113 * // prettier-ignore
54114 * bezier(-40, -40, 0,
54115 * 90, -40, 0,
54116 * -90, 40, 0,
54117 * 40, 40, 0);
54118 * }
54119 * </code>
54120 * </div>
54121 *
54122 * @alt
54123 * stretched black s-shape with a low level of bezier detail
54124 */
54125 _main.default.prototype.bezierDetail = function(d) {
54126 _main.default._validateParameters('bezierDetail', arguments);
54127 this._bezierDetail = d;
54128 return this;
54129 };
54130
54131 /**
54132 * Given the x or y co-ordinate values of control and anchor points of a bezier
54133 * curve, it evaluates the x or y coordinate of the bezier at position t. The
54134 * parameters a and d are the x or y coordinates of first and last points on the
54135 * curve while b and c are of the control points.The final parameter t is the
54136 * position of the resultant point which is given between 0 and 1.
54137 * This can be done once with the x coordinates and a second time
54138 * with the y coordinates to get the location of a bezier curve at t.
54139 *
54140 * @method bezierPoint
54141 * @param {Number} a coordinate of first point on the curve
54142 * @param {Number} b coordinate of first control point
54143 * @param {Number} c coordinate of second control point
54144 * @param {Number} d coordinate of second point on the curve
54145 * @param {Number} t value between 0 and 1
54146 * @return {Number} the value of the Bezier at position t
54147 * @example
54148 * <div>
54149 * <code>
54150 * noFill();
54151 * let x1 = 85,
54152 x2 = 10,
54153 x3 = 90,
54154 x4 = 15;
54155 * let y1 = 20,
54156 y2 = 10,
54157 y3 = 90,
54158 y4 = 80;
54159 * bezier(x1, y1, x2, y2, x3, y3, x4, y4);
54160 * fill(255);
54161 * let steps = 10;
54162 * for (let i = 0; i <= steps; i++) {
54163 * let t = i / steps;
54164 * let x = bezierPoint(x1, x2, x3, x4, t);
54165 * let y = bezierPoint(y1, y2, y3, y4, t);
54166 * circle(x, y, 5);
54167 * }
54168 * </code>
54169 * </div>
54170 *
54171 * @alt
54172 * 10 points plotted on a given bezier at equal distances.
54173 */
54174 _main.default.prototype.bezierPoint = function(a, b, c, d, t) {
54175 _main.default._validateParameters('bezierPoint', arguments);
54176
54177 var adjustedT = 1 - t;
54178 return (
54179 Math.pow(adjustedT, 3) * a +
54180 3 * Math.pow(adjustedT, 2) * t * b +
54181 3 * adjustedT * Math.pow(t, 2) * c +
54182 Math.pow(t, 3) * d
54183 );
54184 };
54185
54186 /**
54187 * Evaluates the tangent to the Bezier at position t for points a, b, c, d.
54188 * The parameters a and d are the first and last points
54189 * on the curve, and b and c are the control points.
54190 * The final parameter t varies between 0 and 1.
54191 *
54192 * @method bezierTangent
54193 * @param {Number} a coordinate of first point on the curve
54194 * @param {Number} b coordinate of first control point
54195 * @param {Number} c coordinate of second control point
54196 * @param {Number} d coordinate of second point on the curve
54197 * @param {Number} t value between 0 and 1
54198 * @return {Number} the tangent at position t
54199 * @example
54200 * <div>
54201 * <code>
54202 * noFill();
54203 * bezier(85, 20, 10, 10, 90, 90, 15, 80);
54204 * let steps = 6;
54205 * fill(255);
54206 * for (let i = 0; i <= steps; i++) {
54207 * let t = i / steps;
54208 * // Get the location of the point
54209 * let x = bezierPoint(85, 10, 90, 15, t);
54210 * let y = bezierPoint(20, 10, 90, 80, t);
54211 * // Get the tangent points
54212 * let tx = bezierTangent(85, 10, 90, 15, t);
54213 * let ty = bezierTangent(20, 10, 90, 80, t);
54214 * // Calculate an angle from the tangent points
54215 * let a = atan2(ty, tx);
54216 * a += PI;
54217 * stroke(255, 102, 0);
54218 * line(x, y, cos(a) * 30 + x, sin(a) * 30 + y);
54219 * // The following line of code makes a line
54220 * // inverse of the above line
54221 * //line(x, y, cos(a)*-30 + x, sin(a)*-30 + y);
54222 * stroke(0);
54223 * ellipse(x, y, 5, 5);
54224 * }
54225 * </code>
54226 * </div>
54227 *
54228 * <div>
54229 * <code>
54230 * noFill();
54231 * bezier(85, 20, 10, 10, 90, 90, 15, 80);
54232 * stroke(255, 102, 0);
54233 * let steps = 16;
54234 * for (let i = 0; i <= steps; i++) {
54235 * let t = i / steps;
54236 * let x = bezierPoint(85, 10, 90, 15, t);
54237 * let y = bezierPoint(20, 10, 90, 80, t);
54238 * let tx = bezierTangent(85, 10, 90, 15, t);
54239 * let ty = bezierTangent(20, 10, 90, 80, t);
54240 * let a = atan2(ty, tx);
54241 * a -= HALF_PI;
54242 * line(x, y, cos(a) * 8 + x, sin(a) * 8 + y);
54243 * }
54244 * </code>
54245 * </div>
54246 *
54247 * @alt
54248 * s-shaped line with 6 short orange lines showing the tangents at those points.
54249 * s-shaped line with 6 short orange lines showing lines coming out the underside of the bezier.
54250 */
54251 _main.default.prototype.bezierTangent = function(a, b, c, d, t) {
54252 _main.default._validateParameters('bezierTangent', arguments);
54253
54254 var adjustedT = 1 - t;
54255 return (
54256 3 * d * Math.pow(t, 2) -
54257 3 * c * Math.pow(t, 2) +
54258 6 * c * adjustedT * t -
54259 6 * b * adjustedT * t +
54260 3 * b * Math.pow(adjustedT, 2) -
54261 3 * a * Math.pow(adjustedT, 2)
54262 );
54263 };
54264
54265 /**
54266 * Draws a curved line on the screen between two points, given as the
54267 * middle four parameters. The first two parameters are a control point, as
54268 * if the curve came from this point even though it's not drawn. The last
54269 * two parameters similarly describe the other control point. <br /><br />
54270 * Longer curves can be created by putting a series of <a href="#/p5/curve">curve()</a> functions
54271 * together or using <a href="#/p5/curveVertex">curveVertex()</a>. An additional function called
54272 * <a href="#/p5/curveTightness">curveTightness()</a> provides control for the visual quality of the curve.
54273 * The <a href="#/p5/curve">curve()</a> function is an implementation of Catmull-Rom splines.
54274 *
54275 * @method curve
54276 * @param {Number} x1 x-coordinate for the beginning control point
54277 * @param {Number} y1 y-coordinate for the beginning control point
54278 * @param {Number} x2 x-coordinate for the first point
54279 * @param {Number} y2 y-coordinate for the first point
54280 * @param {Number} x3 x-coordinate for the second point
54281 * @param {Number} y3 y-coordinate for the second point
54282 * @param {Number} x4 x-coordinate for the ending control point
54283 * @param {Number} y4 y-coordinate for the ending control point
54284 * @chainable
54285 * @example
54286 * <div>
54287 * <code>
54288 * noFill();
54289 * stroke(255, 102, 0);
54290 * curve(5, 26, 5, 26, 73, 24, 73, 61);
54291 * stroke(0);
54292 * curve(5, 26, 73, 24, 73, 61, 15, 65);
54293 * stroke(255, 102, 0);
54294 * curve(73, 24, 73, 61, 15, 65, 15, 65);
54295 * </code>
54296 * </div>
54297 *
54298 * <div>
54299 * <code>
54300 * // Define the curve points as JavaScript objects
54301 * let p1 = { x: 5, y: 26 };
54302 * let p2 = { x: 73, y: 24 };
54303 * let p3 = { x: 73, y: 61 };
54304 * let p4 = { x: 15, y: 65 };
54305 * noFill();
54306 * stroke(255, 102, 0);
54307 * curve(p1.x, p1.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y);
54308 * stroke(0);
54309 * curve(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y);
54310 * stroke(255, 102, 0);
54311 * curve(p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, p4.x, p4.y);
54312 * </code>
54313 * </div>
54314 *
54315 * <div>
54316 * <code>
54317 * noFill();
54318 * stroke(255, 102, 0);
54319 * curve(5, 26, 0, 5, 26, 0, 73, 24, 0, 73, 61, 0);
54320 * stroke(0);
54321 * curve(5, 26, 0, 73, 24, 0, 73, 61, 0, 15, 65, 0);
54322 * stroke(255, 102, 0);
54323 * curve(73, 24, 0, 73, 61, 0, 15, 65, 0, 15, 65, 0);
54324 * </code>
54325 * </div>
54326 *
54327 * @alt
54328 * horseshoe shape with orange ends facing left and black curved center.
54329 * horseshoe shape with orange ends facing left and black curved center.
54330 * curving black and orange lines.
54331 */
54332
54333 /**
54334 * @method curve
54335 * @param {Number} x1
54336 * @param {Number} y1
54337 * @param {Number} z1 z-coordinate for the beginning control point
54338 * @param {Number} x2
54339 * @param {Number} y2
54340 * @param {Number} z2 z-coordinate for the first point
54341 * @param {Number} x3
54342 * @param {Number} y3
54343 * @param {Number} z3 z-coordinate for the second point
54344 * @param {Number} x4
54345 * @param {Number} y4
54346 * @param {Number} z4 z-coordinate for the ending control point
54347 * @chainable
54348 */
54349 _main.default.prototype.curve = function() {
54350 for (
54351 var _len2 = arguments.length, args = new Array(_len2), _key2 = 0;
54352 _key2 < _len2;
54353 _key2++
54354 ) {
54355 args[_key2] = arguments[_key2];
54356 }
54357 _main.default._validateParameters('curve', args);
54358
54359 if (this._renderer._doStroke) {
54360 var _this$_renderer2;
54361 (_this$_renderer2 = this._renderer).curve.apply(_this$_renderer2, args);
54362 }
54363
54364 return this;
54365 };
54366
54367 /**
54368 * Sets the resolution at which curves display. The default value is 20 while
54369 * the minimum value is 3.
54370 *
54371 * This function is only useful when using the WEBGL renderer
54372 * as the default canvas renderer does not use this
54373 * information.
54374 *
54375 * @method curveDetail
54376 * @param {Number} resolution resolution of the curves
54377 * @chainable
54378 * @example
54379 * <div modernizr='webgl'>
54380 * <code>
54381 * function setup() {
54382 * createCanvas(100, 100, WEBGL);
54383 *
54384 * curveDetail(5);
54385 * }
54386 * function draw() {
54387 * background(200);
54388 *
54389 * curve(250, 600, 0, -30, 40, 0, 30, 30, 0, -250, 600, 0);
54390 * }
54391 * </code>
54392 * </div>
54393 *
54394 * @alt
54395 * white arch shape with a low level of curve detail.
54396 */
54397 _main.default.prototype.curveDetail = function(d) {
54398 _main.default._validateParameters('curveDetail', arguments);
54399 if (d < 3) {
54400 this._curveDetail = 3;
54401 } else {
54402 this._curveDetail = d;
54403 }
54404 return this;
54405 };
54406
54407 /**
54408 * Modifies the quality of forms created with <a href="#/p5/curve">curve()</a>
54409 * and <a href="#/p5/curveVertex">curveVertex()</a>.The parameter tightness
54410 * determines how the curve fits to the vertex points. The value 0.0 is the
54411 * default value for tightness (this value defines the curves to be Catmull-Rom
54412 * splines) and the value 1.0 connects all the points with straight lines.
54413 * Values within the range -5.0 and 5.0 will deform the curves but will leave
54414 * them recognizable and as values increase in magnitude, they will continue to deform.
54415 *
54416 * @method curveTightness
54417 * @param {Number} amount amount of deformation from the original vertices
54418 * @chainable
54419 * @example
54420 * <div>
54421 * <code>
54422 * // Move the mouse left and right to see the curve change
54423 * function setup() {
54424 * createCanvas(100, 100);
54425 * noFill();
54426 * }
54427 *
54428 * function draw() {
54429 * background(204);
54430 * let t = map(mouseX, 0, width, -5, 5);
54431 * curveTightness(t);
54432 * beginShape();
54433 * curveVertex(10, 26);
54434 * curveVertex(10, 26);
54435 * curveVertex(83, 24);
54436 * curveVertex(83, 61);
54437 * curveVertex(25, 65);
54438 * curveVertex(25, 65);
54439 * endShape();
54440 * }
54441 * </code>
54442 * </div>
54443 *
54444 * @alt
54445 * Line shaped like right-facing arrow,points move with mouse-x and warp shape.
54446 */
54447 _main.default.prototype.curveTightness = function(t) {
54448 _main.default._validateParameters('curveTightness', arguments);
54449 this._renderer._curveTightness = t;
54450 return this;
54451 };
54452
54453 /**
54454 * Evaluates the curve at position t for points a, b, c, d.
54455 * The parameter t varies between 0 and 1, a and d are control points
54456 * of the curve, and b and c are the start and end points of the curve.
54457 * This can be done once with the x coordinates and a second time
54458 * with the y coordinates to get the location of a curve at t.
54459 *
54460 * @method curvePoint
54461 * @param {Number} a coordinate of first control point of the curve
54462 * @param {Number} b coordinate of first point
54463 * @param {Number} c coordinate of second point
54464 * @param {Number} d coordinate of second control point
54465 * @param {Number} t value between 0 and 1
54466 * @return {Number} bezier value at position t
54467 * @example
54468 * <div>
54469 * <code>
54470 * noFill();
54471 * curve(5, 26, 5, 26, 73, 24, 73, 61);
54472 * curve(5, 26, 73, 24, 73, 61, 15, 65);
54473 * fill(255);
54474 * ellipseMode(CENTER);
54475 * let steps = 6;
54476 * for (let i = 0; i <= steps; i++) {
54477 * let t = i / steps;
54478 * let x = curvePoint(5, 5, 73, 73, t);
54479 * let y = curvePoint(26, 26, 24, 61, t);
54480 * ellipse(x, y, 5, 5);
54481 * x = curvePoint(5, 73, 73, 15, t);
54482 * y = curvePoint(26, 24, 61, 65, t);
54483 * ellipse(x, y, 5, 5);
54484 * }
54485 * </code>
54486 * </div>
54487 *
54488 *line hooking down to right-bottom with 13 5x5 white ellipse points
54489 */
54490 _main.default.prototype.curvePoint = function(a, b, c, d, t) {
54491 _main.default._validateParameters('curvePoint', arguments);
54492
54493 var t3 = t * t * t,
54494 t2 = t * t,
54495 f1 = -0.5 * t3 + t2 - 0.5 * t,
54496 f2 = 1.5 * t3 - 2.5 * t2 + 1.0,
54497 f3 = -1.5 * t3 + 2.0 * t2 + 0.5 * t,
54498 f4 = 0.5 * t3 - 0.5 * t2;
54499 return a * f1 + b * f2 + c * f3 + d * f4;
54500 };
54501
54502 /**
54503 * Evaluates the tangent to the curve at position t for points a, b, c, d.
54504 * The parameter t varies between 0 and 1, a and d are points on the curve,
54505 * and b and c are the control points.
54506 *
54507 * @method curveTangent
54508 * @param {Number} a coordinate of first control point
54509 * @param {Number} b coordinate of first point on the curve
54510 * @param {Number} c coordinate of second point on the curve
54511 * @param {Number} d coordinate of second conrol point
54512 * @param {Number} t value between 0 and 1
54513 * @return {Number} the tangent at position t
54514 * @example
54515 * <div>
54516 * <code>
54517 * noFill();
54518 * curve(5, 26, 73, 24, 73, 61, 15, 65);
54519 * let steps = 6;
54520 * for (let i = 0; i <= steps; i++) {
54521 * let t = i / steps;
54522 * let x = curvePoint(5, 73, 73, 15, t);
54523 * let y = curvePoint(26, 24, 61, 65, t);
54524 * //ellipse(x, y, 5, 5);
54525 * let tx = curveTangent(5, 73, 73, 15, t);
54526 * let ty = curveTangent(26, 24, 61, 65, t);
54527 * let a = atan2(ty, tx);
54528 * a -= PI / 2.0;
54529 * line(x, y, cos(a) * 8 + x, sin(a) * 8 + y);
54530 * }
54531 * </code>
54532 * </div>
54533 *
54534 * @alt
54535 * right curving line mid-right of canvas with 7 short lines radiating from it.
54536 */
54537 _main.default.prototype.curveTangent = function(a, b, c, d, t) {
54538 _main.default._validateParameters('curveTangent', arguments);
54539
54540 var t2 = t * t,
54541 f1 = -3 * t2 / 2 + 2 * t - 0.5,
54542 f2 = 9 * t2 / 2 - 5 * t,
54543 f3 = -9 * t2 / 2 + 4 * t + 0.5,
54544 f4 = 3 * t2 / 2 - t;
54545 return a * f1 + b * f2 + c * f3 + d * f4;
54546 };
54547 var _default = _main.default;
54548 exports.default = _default;
54549 },
54550 {
54551 '../friendly_errors/fes_core': 46,
54552 '../friendly_errors/file_errors': 47,
54553 '../friendly_errors/validate_params': 49,
54554 '../main': 54
54555 }
54556 ],
54557 64: [
54558 function(_dereq_, module, exports) {
54559 'use strict';
54560 function _typeof(obj) {
54561 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
54562 _typeof = function _typeof(obj) {
54563 return typeof obj;
54564 };
54565 } else {
54566 _typeof = function _typeof(obj) {
54567 return obj &&
54568 typeof Symbol === 'function' &&
54569 obj.constructor === Symbol &&
54570 obj !== Symbol.prototype
54571 ? 'symbol'
54572 : typeof obj;
54573 };
54574 }
54575 return _typeof(obj);
54576 }
54577 Object.defineProperty(exports, '__esModule', { value: true });
54578 exports.default = void 0;
54579
54580 var _main = _interopRequireDefault(_dereq_('../main'));
54581 var constants = _interopRequireWildcard(_dereq_('../constants'));
54582 function _getRequireWildcardCache() {
54583 if (typeof WeakMap !== 'function') return null;
54584 var cache = new WeakMap();
54585 _getRequireWildcardCache = function _getRequireWildcardCache() {
54586 return cache;
54587 };
54588 return cache;
54589 }
54590 function _interopRequireWildcard(obj) {
54591 if (obj && obj.__esModule) {
54592 return obj;
54593 }
54594 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) {
54595 return { default: obj };
54596 }
54597 var cache = _getRequireWildcardCache();
54598 if (cache && cache.has(obj)) {
54599 return cache.get(obj);
54600 }
54601 var newObj = {};
54602 var hasPropertyDescriptor =
54603 Object.defineProperty && Object.getOwnPropertyDescriptor;
54604 for (var key in obj) {
54605 if (Object.prototype.hasOwnProperty.call(obj, key)) {
54606 var desc = hasPropertyDescriptor
54607 ? Object.getOwnPropertyDescriptor(obj, key)
54608 : null;
54609 if (desc && (desc.get || desc.set)) {
54610 Object.defineProperty(newObj, key, desc);
54611 } else {
54612 newObj[key] = obj[key];
54613 }
54614 }
54615 }
54616 newObj.default = obj;
54617 if (cache) {
54618 cache.set(obj, newObj);
54619 }
54620 return newObj;
54621 }
54622 function _interopRequireDefault(obj) {
54623 return obj && obj.__esModule ? obj : { default: obj };
54624 }
54625 /**
54626 * @module Shape
54627 * @submodule Vertex
54628 * @for p5
54629 * @requires core
54630 * @requires constants
54631 */ var shapeKind = null;
54632 var vertices = [];
54633 var contourVertices = [];
54634 var isBezier = false;
54635 var isCurve = false;
54636 var isQuadratic = false;
54637 var isContour = false;
54638 var isFirstContour = true;
54639
54640 /**
54641 * Use the <a href="#/p5/beginContour">beginContour()</a> and
54642 * <a href="#/p5/endContour">endContour()</a> functions to create negative shapes
54643 * within shapes such as the center of the letter 'O'. <a href="#/p5/beginContour">beginContour()</a>
54644 * begins recording vertices for the shape and <a href="#/p5/endContour">endContour()</a> stops recording.
54645 * The vertices that define a negative shape must "wind" in the opposite direction
54646 * from the exterior shape. First draw vertices for the exterior clockwise order, then for internal shapes, draw vertices
54647 * shape in counter-clockwise.
54648 *
54649 * These functions can only be used within a <a href="#/p5/beginShape">beginShape()</a>/<a href="#/p5/endShape">endShape()</a> pair and
54650 * transformations such as <a href="#/p5/translate">translate()</a>, <a href="#/p5/rotate">rotate()</a>, and <a href="#/p5/scale">scale()</a> do not work
54651 * within a <a href="#/p5/beginContour">beginContour()</a>/<a href="#/p5/endContour">endContour()</a> pair. It is also not possible to use
54652 * other shapes, such as <a href="#/p5/ellipse">ellipse()</a> or <a href="#/p5/rect">rect()</a> within.
54653 *
54654 * @method beginContour
54655 * @chainable
54656 * @example
54657 * <div>
54658 * <code>
54659 * translate(50, 50);
54660 * stroke(255, 0, 0);
54661 * beginShape();
54662 * // Exterior part of shape, clockwise winding
54663 * vertex(-40, -40);
54664 * vertex(40, -40);
54665 * vertex(40, 40);
54666 * vertex(-40, 40);
54667 * // Interior part of shape, counter-clockwise winding
54668 * beginContour();
54669 * vertex(-20, -20);
54670 * vertex(-20, 20);
54671 * vertex(20, 20);
54672 * vertex(20, -20);
54673 * endContour();
54674 * endShape(CLOSE);
54675 * </code>
54676 * </div>
54677 *
54678 * @alt
54679 * white rect and smaller grey rect with red outlines in center of canvas.
54680 */
54681 _main.default.prototype.beginContour = function() {
54682 contourVertices = [];
54683 isContour = true;
54684 return this;
54685 };
54686
54687 /**
54688 * Using the <a href="#/p5/beginShape">beginShape()</a> and <a href="#/p5/endShape">endShape()</a> functions allow creating more
54689 * complex forms. <a href="#/p5/beginShape">beginShape()</a> begins recording vertices for a shape and
54690 * <a href="#/p5/endShape">endShape()</a> stops recording. The value of the kind parameter tells it which
54691 * types of shapes to create from the provided vertices. With no mode
54692 * specified, the shape can be any irregular polygon.
54693 *
54694 * The parameters available for <a href="#/p5/beginShape">beginShape()</a> are POINTS, LINES, TRIANGLES,
54695 * TRIANGLE_FAN, TRIANGLE_STRIP, QUADS, QUAD_STRIP, and TESS (WebGL only). After calling the
54696 * <a href="#/p5/beginShape">beginShape()</a> function, a series of <a href="#/p5/vertex">vertex()</a> commands must follow. To stop
54697 * drawing the shape, call <a href="#/p5/endShape">endShape()</a>. Each shape will be outlined with the
54698 * current stroke color and filled with the fill color.
54699 *
54700 * Transformations such as <a href="#/p5/translate">translate()</a>, <a href="#/p5/rotate">rotate()</a>, and <a href="#/p5/scale">scale()</a> do not work
54701 * within <a href="#/p5/beginShape">beginShape()</a>. It is also not possible to use other shapes, such as
54702 * <a href="#/p5/ellipse">ellipse()</a> or <a href="#/p5/rect">rect()</a> within <a href="#/p5/beginShape">beginShape()</a>.
54703 *
54704 * @method beginShape
54705 * @param {Constant} [kind] either POINTS, LINES, TRIANGLES, TRIANGLE_FAN
54706 * TRIANGLE_STRIP, QUADS, QUAD_STRIP or TESS
54707 * @chainable
54708 * @example
54709 * <div>
54710 * <code>
54711 * beginShape();
54712 * vertex(30, 20);
54713 * vertex(85, 20);
54714 * vertex(85, 75);
54715 * vertex(30, 75);
54716 * endShape(CLOSE);
54717 * </code>
54718 * </div>
54719 *
54720 * <div>
54721 * <code>
54722 * beginShape(POINTS);
54723 * vertex(30, 20);
54724 * vertex(85, 20);
54725 * vertex(85, 75);
54726 * vertex(30, 75);
54727 * endShape();
54728 * </code>
54729 * </div>
54730 *
54731 * <div>
54732 * <code>
54733 * beginShape(LINES);
54734 * vertex(30, 20);
54735 * vertex(85, 20);
54736 * vertex(85, 75);
54737 * vertex(30, 75);
54738 * endShape();
54739 * </code>
54740 * </div>
54741 *
54742 * <div>
54743 * <code>
54744 * noFill();
54745 * beginShape();
54746 * vertex(30, 20);
54747 * vertex(85, 20);
54748 * vertex(85, 75);
54749 * vertex(30, 75);
54750 * endShape();
54751 * </code>
54752 * </div>
54753 *
54754 * <div>
54755 * <code>
54756 * noFill();
54757 * beginShape();
54758 * vertex(30, 20);
54759 * vertex(85, 20);
54760 * vertex(85, 75);
54761 * vertex(30, 75);
54762 * endShape(CLOSE);
54763 * </code>
54764 * </div>
54765 *
54766 * <div>
54767 * <code>
54768 * beginShape(TRIANGLES);
54769 * vertex(30, 75);
54770 * vertex(40, 20);
54771 * vertex(50, 75);
54772 * vertex(60, 20);
54773 * vertex(70, 75);
54774 * vertex(80, 20);
54775 * endShape();
54776 * </code>
54777 * </div>
54778 *
54779 * <div>
54780 * <code>
54781 * beginShape(TRIANGLE_STRIP);
54782 * vertex(30, 75);
54783 * vertex(40, 20);
54784 * vertex(50, 75);
54785 * vertex(60, 20);
54786 * vertex(70, 75);
54787 * vertex(80, 20);
54788 * vertex(90, 75);
54789 * endShape();
54790 * </code>
54791 * </div>
54792 *
54793 * <div>
54794 * <code>
54795 * beginShape(TRIANGLE_FAN);
54796 * vertex(57.5, 50);
54797 * vertex(57.5, 15);
54798 * vertex(92, 50);
54799 * vertex(57.5, 85);
54800 * vertex(22, 50);
54801 * vertex(57.5, 15);
54802 * endShape();
54803 * </code>
54804 * </div>
54805 *
54806 * <div>
54807 * <code>
54808 * beginShape(QUADS);
54809 * vertex(30, 20);
54810 * vertex(30, 75);
54811 * vertex(50, 75);
54812 * vertex(50, 20);
54813 * vertex(65, 20);
54814 * vertex(65, 75);
54815 * vertex(85, 75);
54816 * vertex(85, 20);
54817 * endShape();
54818 * </code>
54819 * </div>
54820 *
54821 * <div>
54822 * <code>
54823 * beginShape(QUAD_STRIP);
54824 * vertex(30, 20);
54825 * vertex(30, 75);
54826 * vertex(50, 20);
54827 * vertex(50, 75);
54828 * vertex(65, 20);
54829 * vertex(65, 75);
54830 * vertex(85, 20);
54831 * vertex(85, 75);
54832 * endShape();
54833 * </code>
54834 * </div>
54835 *
54836 * <div>
54837 * <code>
54838 * beginShape();
54839 * vertex(20, 20);
54840 * vertex(40, 20);
54841 * vertex(40, 40);
54842 * vertex(60, 40);
54843 * vertex(60, 60);
54844 * vertex(20, 60);
54845 * endShape(CLOSE);
54846 * </code>
54847 * </div>
54848 *
54849 * @alt
54850 * white square-shape with black outline in middle-right of canvas.
54851 * 4 black points in a square shape in middle-right of canvas.
54852 * 2 horizontal black lines. In the top-right and bottom-right of canvas.
54853 * 3 line shape with horizontal on top, vertical in middle and horizontal bottom.
54854 * square line shape in middle-right of canvas.
54855 * 2 white triangle shapes mid-right canvas. left one pointing up and right down.
54856 * 5 horizontal interlocking and alternating white triangles in mid-right canvas.
54857 * 4 interlocking white triangles in 45 degree rotated square-shape.
54858 * 2 white rectangle shapes in mid-right canvas. Both 20x55.
54859 * 3 side-by-side white rectangles center rect is smaller in mid-right canvas.
54860 * Thick white l-shape with black outline mid-top-left of canvas.
54861 */
54862 _main.default.prototype.beginShape = function(kind) {
54863 _main.default._validateParameters('beginShape', arguments);
54864 if (this._renderer.isP3D) {
54865 var _this$_renderer;
54866 (_this$_renderer = this._renderer).beginShape.apply(
54867 _this$_renderer,
54868 arguments
54869 );
54870 } else {
54871 if (
54872 kind === constants.POINTS ||
54873 kind === constants.LINES ||
54874 kind === constants.TRIANGLES ||
54875 kind === constants.TRIANGLE_FAN ||
54876 kind === constants.TRIANGLE_STRIP ||
54877 kind === constants.QUADS ||
54878 kind === constants.QUAD_STRIP
54879 ) {
54880 shapeKind = kind;
54881 } else {
54882 shapeKind = null;
54883 }
54884
54885 vertices = [];
54886 contourVertices = [];
54887 }
54888 return this;
54889 };
54890
54891 /**
54892 * Specifies vertex coordinates for Bezier curves. Each call to
54893 * bezierVertex() defines the position of two control points and
54894 * one anchor point of a Bezier curve, adding a new segment to a
54895 * line or shape. For WebGL mode bezierVertex() can be used in 2D
54896 * as well as 3D mode. 2D mode expects 6 parameters, while 3D mode
54897 * expects 9 parameters (including z coordinates).
54898 *
54899 * The first time bezierVertex() is used within a <a href="#/p5/beginShape">beginShape()</a>
54900 * call, it must be prefaced with a call to <a href="#/p5/vertex">vertex()</a> to set the first anchor
54901 * point. This function must be used between <a href="#/p5/beginShape">beginShape()</a> and <a href="#/p5/endShape">endShape()</a>
54902 * and only when there is no MODE or POINTS parameter specified to
54903 * <a href="#/p5/beginShape">beginShape()</a>.
54904 *
54905 * @method bezierVertex
54906 * @param {Number} x2 x-coordinate for the first control point
54907 * @param {Number} y2 y-coordinate for the first control point
54908 * @param {Number} x3 x-coordinate for the second control point
54909 * @param {Number} y3 y-coordinate for the second control point
54910 * @param {Number} x4 x-coordinate for the anchor point
54911 * @param {Number} y4 y-coordinate for the anchor point
54912 * @chainable
54913 *
54914 * @example
54915 * <div>
54916 * <code>
54917 * noFill();
54918 * beginShape();
54919 * vertex(30, 20);
54920 * bezierVertex(80, 0, 80, 75, 30, 75);
54921 * endShape();
54922 * </code>
54923 * </div>
54924 *
54925 * <div>
54926 * <code>
54927 * beginShape();
54928 * vertex(30, 20);
54929 * bezierVertex(80, 0, 80, 75, 30, 75);
54930 * bezierVertex(50, 80, 60, 25, 30, 20);
54931 * endShape();
54932 * </code>
54933 * </div>
54934 *
54935 * <div>
54936 * <code>
54937 * function setup() {
54938 * createCanvas(100, 100, WEBGL);
54939 * setAttributes('antialias', true);
54940 * }
54941 * function draw() {
54942 * orbitControl();
54943 * background(50);
54944 * strokeWeight(4);
54945 * stroke(255);
54946 * point(-25, 30);
54947 * point(25, 30);
54948 * point(25, -30);
54949 * point(-25, -30);
54950 *
54951 * strokeWeight(1);
54952 * noFill();
54953 *
54954 * beginShape();
54955 * vertex(-25, 30);
54956 * bezierVertex(25, 30, 25, -30, -25, -30);
54957 * endShape();
54958 *
54959 * beginShape();
54960 * vertex(-25, 30, 20);
54961 * bezierVertex(25, 30, 20, 25, -30, 20, -25, -30, 20);
54962 * endShape();
54963 * }
54964 * </code>
54965 * </div>
54966 *
54967 * @alt
54968 * crescent-shaped line in middle of canvas. Points facing left.
54969 * white crescent shape in middle of canvas. Points facing left.
54970 * crescent shape in middle of canvas with another crescent shape on positive z-axis.
54971 */
54972
54973 /**
54974 * @method bezierVertex
54975 * @param {Number} x2
54976 * @param {Number} y2
54977 * @param {Number} z2 z-coordinate for the first control point (for WebGL mode)
54978 * @param {Number} x3
54979 * @param {Number} y3
54980 * @param {Number} z3 z-coordinate for the second control point (for WebGL mode)
54981 * @param {Number} x4
54982 * @param {Number} y4
54983 * @param {Number} z4 z-coordinate for the anchor point (for WebGL mode)
54984 * @chainable
54985 */
54986 _main.default.prototype.bezierVertex = function() {
54987 for (
54988 var _len = arguments.length, args = new Array(_len), _key = 0;
54989 _key < _len;
54990 _key++
54991 ) {
54992 args[_key] = arguments[_key];
54993 }
54994 _main.default._validateParameters('bezierVertex', args);
54995 if (this._renderer.isP3D) {
54996 var _this$_renderer2;
54997 (_this$_renderer2 = this._renderer).bezierVertex.apply(
54998 _this$_renderer2,
54999 args
55000 );
55001 } else {
55002 if (vertices.length === 0) {
55003 _main.default._friendlyError(
55004 'vertex() must be used once before calling bezierVertex()',
55005 'bezierVertex'
55006 );
55007 } else {
55008 isBezier = true;
55009 var vert = [];
55010 for (var i = 0; i < args.length; i++) {
55011 vert[i] = args[i];
55012 }
55013 vert.isVert = false;
55014 if (isContour) {
55015 contourVertices.push(vert);
55016 } else {
55017 vertices.push(vert);
55018 }
55019 }
55020 }
55021 return this;
55022 };
55023
55024 /**
55025 * Specifies vertex coordinates for curves. This function may only
55026 * be used between <a href="#/p5/beginShape">beginShape()</a> and <a href="#/p5/endShape">endShape()</a> and only when there
55027 * is no MODE parameter specified to <a href="#/p5/beginShape">beginShape()</a>.
55028 * For WebGL mode curveVertex() can be used in 2D as well as 3D mode.
55029 * 2D mode expects 2 parameters, while 3D mode expects 3 parameters.
55030 *
55031 * The first and last points in a series of curveVertex() lines will be used to
55032 * guide the beginning and end of a the curve. A minimum of four
55033 * points is required to draw a tiny curve between the second and
55034 * third points. Adding a fifth point with curveVertex() will draw
55035 * the curve between the second, third, and fourth points. The
55036 * curveVertex() function is an implementation of Catmull-Rom
55037 * splines.
55038 *
55039 * @method curveVertex
55040 * @param {Number} x x-coordinate of the vertex
55041 * @param {Number} y y-coordinate of the vertex
55042 * @chainable
55043 * @example
55044 * <div>
55045 * <code>
55046 * strokeWeight(5);
55047 * point(84, 91);
55048 * point(68, 19);
55049 * point(21, 17);
55050 * point(32, 91);
55051 * strokeWeight(1);
55052 *
55053 * noFill();
55054 * beginShape();
55055 * curveVertex(84, 91);
55056 * curveVertex(84, 91);
55057 * curveVertex(68, 19);
55058 * curveVertex(21, 17);
55059 * curveVertex(32, 91);
55060 * curveVertex(32, 91);
55061 * endShape();
55062 * </code>
55063 * </div>
55064 *
55065 * @alt
55066 * Upside-down u-shape line, mid canvas. left point extends beyond canvas view.
55067 */
55068
55069 /**
55070 * @method curveVertex
55071 * @param {Number} x
55072 * @param {Number} y
55073 * @param {Number} [z] z-coordinate of the vertex (for WebGL mode)
55074 * @chainable
55075 * @example
55076 * <div>
55077 * <code>
55078 * function setup() {
55079 * createCanvas(100, 100, WEBGL);
55080 * setAttributes('antialias', true);
55081 * }
55082 * function draw() {
55083 * orbitControl();
55084 * background(50);
55085 * strokeWeight(4);
55086 * stroke(255);
55087 *
55088 * point(-25, 25);
55089 * point(-25, 25);
55090 * point(-25, -25);
55091 * point(25, -25);
55092 * point(25, 25);
55093 * point(25, 25);
55094 *
55095 * strokeWeight(1);
55096 * noFill();
55097 *
55098 * beginShape();
55099 * curveVertex(-25, 25);
55100 * curveVertex(-25, 25);
55101 * curveVertex(-25, -25);
55102 * curveVertex(25, -25);
55103 * curveVertex(25, 25);
55104 * curveVertex(25, 25);
55105 * endShape();
55106 *
55107 * beginShape();
55108 * curveVertex(-25, 25, 20);
55109 * curveVertex(-25, 25, 20);
55110 * curveVertex(-25, -25, 20);
55111 * curveVertex(25, -25, 20);
55112 * curveVertex(25, 25, 20);
55113 * curveVertex(25, 25, 20);
55114 * endShape();
55115 * }
55116 * </code>
55117 * </div>
55118 *
55119 * @alt
55120 * Upside-down u-shape line, mid canvas with the same shape in positive z-axis.
55121 */
55122 _main.default.prototype.curveVertex = function() {
55123 for (
55124 var _len2 = arguments.length, args = new Array(_len2), _key2 = 0;
55125 _key2 < _len2;
55126 _key2++
55127 ) {
55128 args[_key2] = arguments[_key2];
55129 }
55130 _main.default._validateParameters('curveVertex', args);
55131 if (this._renderer.isP3D) {
55132 var _this$_renderer3;
55133 (_this$_renderer3 = this._renderer).curveVertex.apply(_this$_renderer3, args);
55134 } else {
55135 isCurve = true;
55136 this.vertex(args[0], args[1]);
55137 }
55138 return this;
55139 };
55140
55141 /**
55142 * Use the <a href="#/p5/beginContour">beginContour()</a> and <a href="#/p5/endContour">endContour()</a> functions to create negative
55143 * shapes within shapes such as the center of the letter 'O'. <a href="#/p5/beginContour">beginContour()</a>
55144 * begins recording vertices for the shape and <a href="#/p5/endContour">endContour()</a> stops recording.
55145 * The vertices that define a negative shape must "wind" in the opposite
55146 * direction from the exterior shape. First draw vertices for the exterior
55147 * clockwise order, then for internal shapes, draw vertices
55148 * shape in counter-clockwise.
55149 *
55150 * These functions can only be used within a <a href="#/p5/beginShape">beginShape()</a>/<a href="#/p5/endShape">endShape()</a> pair and
55151 * transformations such as <a href="#/p5/translate">translate()</a>, <a href="#/p5/rotate">rotate()</a>, and <a href="#/p5/scale">scale()</a> do not work
55152 * within a <a href="#/p5/beginContour">beginContour()</a>/<a href="#/p5/endContour">endContour()</a> pair. It is also not possible to use
55153 * other shapes, such as <a href="#/p5/ellipse">ellipse()</a> or <a href="#/p5/rect">rect()</a> within.
55154 *
55155 * @method endContour
55156 * @chainable
55157 * @example
55158 * <div>
55159 * <code>
55160 * translate(50, 50);
55161 * stroke(255, 0, 0);
55162 * beginShape();
55163 * // Exterior part of shape, clockwise winding
55164 * vertex(-40, -40);
55165 * vertex(40, -40);
55166 * vertex(40, 40);
55167 * vertex(-40, 40);
55168 * // Interior part of shape, counter-clockwise winding
55169 * beginContour();
55170 * vertex(-20, -20);
55171 * vertex(-20, 20);
55172 * vertex(20, 20);
55173 * vertex(20, -20);
55174 * endContour();
55175 * endShape(CLOSE);
55176 * </code>
55177 * </div>
55178 *
55179 * @alt
55180 * white rect and smaller grey rect with red outlines in center of canvas.
55181 */
55182 _main.default.prototype.endContour = function() {
55183 var vert = contourVertices[0].slice(); // copy all data
55184 vert.isVert = contourVertices[0].isVert;
55185 vert.moveTo = false;
55186 contourVertices.push(vert);
55187
55188 // prevent stray lines with multiple contours
55189 if (isFirstContour) {
55190 vertices.push(vertices[0]);
55191 isFirstContour = false;
55192 }
55193
55194 for (var i = 0; i < contourVertices.length; i++) {
55195 vertices.push(contourVertices[i]);
55196 }
55197 return this;
55198 };
55199
55200 /**
55201 * The <a href="#/p5/endShape">endShape()</a> function is the companion to <a href="#/p5/beginShape">beginShape()</a> and may only be
55202 * called after <a href="#/p5/beginShape">beginShape()</a>. When <a href="#/p5/endshape">endShape()</a> is called, all of image data
55203 * defined since the previous call to <a href="#/p5/beginShape">beginShape()</a> is written into the image
55204 * buffer. The constant CLOSE as the value for the MODE parameter to close
55205 * the shape (to connect the beginning and the end).
55206 *
55207 * @method endShape
55208 * @param {Constant} [mode] use CLOSE to close the shape
55209 * @chainable
55210 * @example
55211 * <div>
55212 * <code>
55213 * noFill();
55214 *
55215 * beginShape();
55216 * vertex(20, 20);
55217 * vertex(45, 20);
55218 * vertex(45, 80);
55219 * endShape(CLOSE);
55220 *
55221 * beginShape();
55222 * vertex(50, 20);
55223 * vertex(75, 20);
55224 * vertex(75, 80);
55225 * endShape();
55226 * </code>
55227 * </div>
55228 *
55229 * @alt
55230 * Triangle line shape with smallest interior angle on bottom and upside-down L.
55231 */
55232 _main.default.prototype.endShape = function(mode) {
55233 _main.default._validateParameters('endShape', arguments);
55234 if (this._renderer.isP3D) {
55235 this._renderer.endShape(
55236 mode,
55237 isCurve,
55238 isBezier,
55239 isQuadratic,
55240 isContour,
55241 shapeKind
55242 );
55243 } else {
55244 if (vertices.length === 0) {
55245 return this;
55246 }
55247 if (!this._renderer._doStroke && !this._renderer._doFill) {
55248 return this;
55249 }
55250
55251 var closeShape = mode === constants.CLOSE;
55252
55253 // if the shape is closed, the first element is also the last element
55254 if (closeShape && !isContour) {
55255 vertices.push(vertices[0]);
55256 }
55257
55258 this._renderer.endShape(
55259 mode,
55260 vertices,
55261 isCurve,
55262 isBezier,
55263 isQuadratic,
55264 isContour,
55265 shapeKind
55266 );
55267
55268 // Reset some settings
55269 isCurve = false;
55270 isBezier = false;
55271 isQuadratic = false;
55272 isContour = false;
55273 isFirstContour = true;
55274
55275 // If the shape is closed, the first element was added as last element.
55276 // We must remove it again to prevent the list of vertices from growing
55277 // over successive calls to endShape(CLOSE)
55278 if (closeShape) {
55279 vertices.pop();
55280 }
55281 }
55282 return this;
55283 };
55284
55285 /**
55286 * Specifies vertex coordinates for quadratic Bezier curves. Each call to
55287 * quadraticVertex() defines the position of one control points and one
55288 * anchor point of a Bezier curve, adding a new segment to a line or shape.
55289 * The first time quadraticVertex() is used within a <a href="#/p5/beginShape">beginShape()</a> call, it
55290 * must be prefaced with a call to <a href="#/p5/vertex">vertex()</a> to set the first anchor point.
55291 * For WebGL mode quadraticVertex() can be used in 2D as well as 3D mode.
55292 * 2D mode expects 4 parameters, while 3D mode expects 6 parameters
55293 * (including z coordinates).
55294 *
55295 * This function must be used between <a href="#/p5/beginShape">beginShape()</a> and <a href="#/p5/endShape">endShape()</a>
55296 * and only when there is no MODE or POINTS parameter specified to
55297 * <a href="#/p5/beginShape">beginShape()</a>.
55298 *
55299 * @method quadraticVertex
55300 * @param {Number} cx x-coordinate for the control point
55301 * @param {Number} cy y-coordinate for the control point
55302 * @param {Number} x3 x-coordinate for the anchor point
55303 * @param {Number} y3 y-coordinate for the anchor point
55304 * @chainable
55305 *
55306 * @example
55307 * <div>
55308 * <code>
55309 * strokeWeight(5);
55310 * point(20, 20);
55311 * point(80, 20);
55312 * point(50, 50);
55313 *
55314 * noFill();
55315 * strokeWeight(1);
55316 * beginShape();
55317 * vertex(20, 20);
55318 * quadraticVertex(80, 20, 50, 50);
55319 * endShape();
55320 * </code>
55321 * </div>
55322 *
55323 * <div>
55324 * <code>
55325 * strokeWeight(5);
55326 * point(20, 20);
55327 * point(80, 20);
55328 * point(50, 50);
55329 *
55330 * point(20, 80);
55331 * point(80, 80);
55332 * point(80, 60);
55333 *
55334 * noFill();
55335 * strokeWeight(1);
55336 * beginShape();
55337 * vertex(20, 20);
55338 * quadraticVertex(80, 20, 50, 50);
55339 * quadraticVertex(20, 80, 80, 80);
55340 * vertex(80, 60);
55341 * endShape();
55342 * </code>
55343 * </div>
55344 *
55345 * @alt
55346 * arched-shaped black line with 4 pixel thick stroke weight.
55347 * backwards s-shaped black line with 4 pixel thick stroke weight.
55348 */
55349
55350 /**
55351 * @method quadraticVertex
55352 * @param {Number} cx
55353 * @param {Number} cy
55354 * @param {Number} cz z-coordinate for the control point (for WebGL mode)
55355 * @param {Number} x3
55356 * @param {Number} y3
55357 * @param {Number} z3 z-coordinate for the anchor point (for WebGL mode)
55358 * @chainable
55359 *
55360 * @example
55361 * <div>
55362 * <code>
55363 * function setup() {
55364 * createCanvas(100, 100, WEBGL);
55365 * setAttributes('antialias', true);
55366 * }
55367 * function draw() {
55368 * orbitControl();
55369 * background(50);
55370 * strokeWeight(4);
55371 * stroke(255);
55372 *
55373 * point(-35, -35);
55374 * point(35, -35);
55375 * point(0, 0);
55376 * point(-35, 35);
55377 * point(35, 35);
55378 * point(35, 10);
55379 *
55380 * strokeWeight(1);
55381 * noFill();
55382 *
55383 * beginShape();
55384 * vertex(-35, -35);
55385 * quadraticVertex(35, -35, 0, 0);
55386 * quadraticVertex(-35, 35, 35, 35);
55387 * vertex(35, 10);
55388 * endShape();
55389 *
55390 * beginShape();
55391 * vertex(-35, -35, 20);
55392 * quadraticVertex(35, -35, 20, 0, 0, 20);
55393 * quadraticVertex(-35, 35, 20, 35, 35, 20);
55394 * vertex(35, 10, 20);
55395 * endShape();
55396 * }
55397 * </code>
55398 * </div>
55399 *
55400 * @alt
55401 * backwards s-shaped black line with the same s-shaped line in postive z-axis.
55402 */
55403 _main.default.prototype.quadraticVertex = function() {
55404 for (
55405 var _len3 = arguments.length, args = new Array(_len3), _key3 = 0;
55406 _key3 < _len3;
55407 _key3++
55408 ) {
55409 args[_key3] = arguments[_key3];
55410 }
55411 _main.default._validateParameters('quadraticVertex', args);
55412 if (this._renderer.isP3D) {
55413 var _this$_renderer4;
55414 (_this$_renderer4 = this._renderer).quadraticVertex.apply(
55415 _this$_renderer4,
55416 args
55417 );
55418 } else {
55419 //if we're drawing a contour, put the points into an
55420 // array for inside drawing
55421 if (this._contourInited) {
55422 var pt = {};
55423 pt.x = args[0];
55424 pt.y = args[1];
55425 pt.x3 = args[2];
55426 pt.y3 = args[3];
55427 pt.type = constants.QUADRATIC;
55428 this._contourVertices.push(pt);
55429
55430 return this;
55431 }
55432 if (vertices.length > 0) {
55433 isQuadratic = true;
55434 var vert = [];
55435 for (var i = 0; i < args.length; i++) {
55436 vert[i] = args[i];
55437 }
55438 vert.isVert = false;
55439 if (isContour) {
55440 contourVertices.push(vert);
55441 } else {
55442 vertices.push(vert);
55443 }
55444 } else {
55445 _main.default._friendlyError(
55446 'vertex() must be used once before calling quadraticVertex()',
55447 'quadraticVertex'
55448 );
55449 }
55450 }
55451 return this;
55452 };
55453
55454 /**
55455 * All shapes are constructed by connecting a series of vertices. <a href="#/p5/vertex">vertex()</a>
55456 * is used to specify the vertex coordinates for points, lines, triangles,
55457 * quads, and polygons. It is used exclusively within the <a href="#/p5/beginShape">beginShape()</a> and
55458 * <a href="#/p5/endShape">endShape()</a> functions.
55459 *
55460 * @method vertex
55461 * @param {Number} x x-coordinate of the vertex
55462 * @param {Number} y y-coordinate of the vertex
55463 * @chainable
55464 * @example
55465 * <div>
55466 * <code>
55467 * strokeWeight(3);
55468 * beginShape(POINTS);
55469 * vertex(30, 20);
55470 * vertex(85, 20);
55471 * vertex(85, 75);
55472 * vertex(30, 75);
55473 * endShape();
55474 * </code>
55475 * </div>
55476 *
55477 * <div>
55478 * <code>
55479 * createCanvas(100, 100, WEBGL);
55480 * background(240, 240, 240);
55481 * fill(237, 34, 93);
55482 * noStroke();
55483 * beginShape();
55484 * vertex(0, 35);
55485 * vertex(35, 0);
55486 * vertex(0, -35);
55487 * vertex(-35, 0);
55488 * endShape();
55489 * </code>
55490 * </div>
55491 *
55492 * <div>
55493 * <code>
55494 * createCanvas(100, 100, WEBGL);
55495 * background(240, 240, 240);
55496 * fill(237, 34, 93);
55497 * noStroke();
55498 * beginShape();
55499 * vertex(-10, 10);
55500 * vertex(0, 35);
55501 * vertex(10, 10);
55502 * vertex(35, 0);
55503 * vertex(10, -8);
55504 * vertex(0, -35);
55505 * vertex(-10, -8);
55506 * vertex(-35, 0);
55507 * endShape();
55508 * </code>
55509 * </div>
55510 *
55511 * <div>
55512 * <code>
55513 * strokeWeight(3);
55514 * stroke(237, 34, 93);
55515 * beginShape(LINES);
55516 * vertex(10, 35);
55517 * vertex(90, 35);
55518 * vertex(10, 65);
55519 * vertex(90, 65);
55520 * vertex(35, 10);
55521 * vertex(35, 90);
55522 * vertex(65, 10);
55523 * vertex(65, 90);
55524 * endShape();
55525 * </code>
55526 * </div>
55527 *
55528 * <div>
55529 * <code>
55530 * // Click to change the number of sides.
55531 * // In WebGL mode, custom shapes will only
55532 * // display hollow fill sections when
55533 * // all calls to vertex() use the same z-value.
55534 *
55535 * let sides = 3;
55536 * let angle, px, py;
55537 *
55538 * function setup() {
55539 * createCanvas(100, 100, WEBGL);
55540 * setAttributes('antialias', true);
55541 * fill(237, 34, 93);
55542 * strokeWeight(3);
55543 * }
55544 *
55545 * function draw() {
55546 * background(200);
55547 * rotateX(frameCount * 0.01);
55548 * rotateZ(frameCount * 0.01);
55549 * ngon(sides, 0, 0, 80);
55550 * }
55551 *
55552 * function mouseClicked() {
55553 * if (sides > 6) {
55554 * sides = 3;
55555 * } else {
55556 * sides++;
55557 * }
55558 * }
55559 *
55560 * function ngon(n, x, y, d) {
55561 * beginShape(TESS);
55562 * for (let i = 0; i < n + 1; i++) {
55563 * angle = TWO_PI / n * i;
55564 * px = x + sin(angle) * d / 2;
55565 * py = y - cos(angle) * d / 2;
55566 * vertex(px, py, 0);
55567 * }
55568 * for (let i = 0; i < n + 1; i++) {
55569 * angle = TWO_PI / n * i;
55570 * px = x + sin(angle) * d / 4;
55571 * py = y - cos(angle) * d / 4;
55572 * vertex(px, py, 0);
55573 * }
55574 * endShape();
55575 * }
55576 * </code>
55577 * </div>
55578 * @alt
55579 * 4 black points in a square shape in middle-right of canvas.
55580 * 4 points making a diamond shape.
55581 * 8 points making a star.
55582 * 8 points making 4 lines.
55583 * A rotating 3D shape with a hollow section in the middle.
55584 */
55585 /**
55586 * @method vertex
55587 * @param {Number} x
55588 * @param {Number} y
55589 * @param {Number} z z-coordinate of the vertex
55590 * @param {Number} [u] the vertex's texture u-coordinate
55591 * @param {Number} [v] the vertex's texture v-coordinate
55592 * @chainable
55593 */
55594 _main.default.prototype.vertex = function(x, y, moveTo, u, v) {
55595 if (this._renderer.isP3D) {
55596 var _this$_renderer5;
55597 (_this$_renderer5 = this._renderer).vertex.apply(_this$_renderer5, arguments);
55598 } else {
55599 var vert = [];
55600 vert.isVert = true;
55601 vert[0] = x;
55602 vert[1] = y;
55603 vert[2] = 0;
55604 vert[3] = 0;
55605 vert[4] = 0;
55606 vert[5] = this._renderer._getFill();
55607 vert[6] = this._renderer._getStroke();
55608
55609 if (moveTo) {
55610 vert.moveTo = moveTo;
55611 }
55612 if (isContour) {
55613 if (contourVertices.length === 0) {
55614 vert.moveTo = true;
55615 }
55616 contourVertices.push(vert);
55617 } else {
55618 vertices.push(vert);
55619 }
55620 }
55621 return this;
55622 };
55623 var _default = _main.default;
55624 exports.default = _default;
55625 },
55626 { '../constants': 43, '../main': 54 }
55627 ],
55628 65: [
55629 function(_dereq_, module, exports) {
55630 'use strict';
55631 function _typeof(obj) {
55632 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
55633 _typeof = function _typeof(obj) {
55634 return typeof obj;
55635 };
55636 } else {
55637 _typeof = function _typeof(obj) {
55638 return obj &&
55639 typeof Symbol === 'function' &&
55640 obj.constructor === Symbol &&
55641 obj !== Symbol.prototype
55642 ? 'symbol'
55643 : typeof obj;
55644 };
55645 }
55646 return _typeof(obj);
55647 } // requestAnim shim layer by Paul Irish
55648 // http://paulirish.com/2011/requestanimationframe-for-smart-animating/
55649 // http://my.opera.com/emoller/blog/2011/12/20/
55650 // requestanimationframe-for-smart-er-animating
55651 // requestAnimationFrame polyfill by Erik Möller
55652 // fixes from Paul Irish and Tino Zijdel
55653 window.requestAnimationFrame = (function() {
55654 return (
55655 window.requestAnimationFrame ||
55656 window.webkitRequestAnimationFrame ||
55657 window.mozRequestAnimationFrame ||
55658 window.oRequestAnimationFrame ||
55659 window.msRequestAnimationFrame ||
55660 function(callback, element) {
55661 // should '60' here be framerate?
55662 window.setTimeout(callback, 1000 / 60);
55663 }
55664 );
55665 })();
55666
55667 /**
55668 * shim for Uint8ClampedArray.slice
55669 * (allows arrayCopy to work with pixels[])
55670 * with thanks to http://halfpapstudios.com/blog/tag/html5-canvas/
55671 * Enumerable set to false to protect for...in from
55672 * Uint8ClampedArray.prototype pollution.
55673 */
55674 (function() {
55675 if (
55676 typeof Uint8ClampedArray !== 'undefined' &&
55677 !Uint8ClampedArray.prototype.slice
55678 ) {
55679 Object.defineProperty(Uint8ClampedArray.prototype, 'slice', {
55680 value: Array.prototype.slice,
55681 writable: true,
55682 configurable: true,
55683 enumerable: false
55684 });
55685 }
55686 })();
55687
55688 /**
55689 * this is implementation of Object.assign() which is unavailable in
55690 * IE11 and (non-Chrome) Android browsers.
55691 * The assign() method is used to copy the values of all enumerable
55692 * own properties from one or more source objects to a target object.
55693 * It will return the target object.
55694 * Modified from https://github.com/ljharb/object.assign
55695 */
55696 (function() {
55697 if (!Object.assign) {
55698 var keys = Object.keys;
55699 var defineProperty = Object.defineProperty;
55700 var canBeObject = function canBeObject(obj) {
55701 return typeof obj !== 'undefined' && obj !== null;
55702 };
55703 var hasSymbols =
55704 typeof Symbol === 'function' && _typeof(Symbol()) === 'symbol';
55705 var propIsEnumerable = Object.prototype.propertyIsEnumerable;
55706 var isEnumerableOn = function isEnumerableOn(obj) {
55707 return function isEnumerable(prop) {
55708 return propIsEnumerable.call(obj, prop);
55709 };
55710 };
55711
55712 // per ES6 spec, this function has to have a length of 2
55713 var assignShim = function assign(target, source1) {
55714 if (!canBeObject(target)) {
55715 throw new TypeError('target must be an object');
55716 }
55717 var objTarget = Object(target);
55718 var s, source, i, props;
55719 for (s = 1; s < arguments.length; ++s) {
55720 source = Object(arguments[s]);
55721 props = keys(source);
55722 if (hasSymbols && Object.getOwnPropertySymbols) {
55723 props.push.apply(
55724 props,
55725 Object.getOwnPropertySymbols(source).filter(isEnumerableOn(source))
55726 );
55727 }
55728 for (i = 0; i < props.length; ++i) {
55729 objTarget[props[i]] = source[props[i]];
55730 }
55731 }
55732 return objTarget;
55733 };
55734
55735 defineProperty(Object, 'assign', {
55736 value: assignShim,
55737 configurable: true,
55738 enumerable: false,
55739 writable: true
55740 });
55741 }
55742 })();
55743 },
55744 {}
55745 ],
55746 66: [
55747 function(_dereq_, module, exports) {
55748 'use strict';
55749 Object.defineProperty(exports, '__esModule', { value: true });
55750 exports.default = void 0;
55751
55752 var _main = _interopRequireDefault(_dereq_('./main'));
55753 function _interopRequireDefault(obj) {
55754 return obj && obj.__esModule ? obj : { default: obj };
55755 }
55756 /**
55757 * @module Structure
55758 * @submodule Structure
55759 * @for p5
55760 * @requires core
55761 */ /**
55762 * Stops p5.js from continuously executing the code within <a href="#/p5/draw">draw()</a>.
55763 * If <a href="#/p5/loop">loop()</a> is called, the code in <a href="#/p5/draw">draw()</a>
55764 * begins to run continuously again. If using <a href="#/p5/noLoop">noLoop()</a>
55765 * in <a href="#/p5/setup">setup()</a>, it should be the last line inside the block.
55766 *
55767 * When <a href="#/p5/noLoop">noLoop()</a> is used, it's not possible to manipulate
55768 * or access the screen inside event handling functions such as
55769 * <a href="#/p5/mousePressed">mousePressed()</a> or
55770 * <a href="#/p5/keyPressed">keyPressed()</a>. Instead, use those functions to
55771 * call <a href="#/p5/redraw">redraw()</a> or <a href="#/p5/loop">loop()</a>,
55772 * which will run <a href="#/p5/draw">draw()</a>, which can update the screen
55773 * properly. This means that when <a href="#/p5/noLoop">noLoop()</a> has been
55774 * called, no drawing can happen, and functions like <a href="#/p5/saveFrame">saveFrame()</a>
55775 * or <a href="#/p5/loadPixels">loadPixels()</a> may not be used.
55776 *
55777 * Note that if the sketch is resized, <a href="#/p5/redraw">redraw()</a> will
55778 * be called to update the sketch, even after <a href="#/p5/noLoop">noLoop()</a>
55779 * has been specified. Otherwise, the sketch would enter an odd state until
55780 * <a href="#/p5/loop">loop()</a> was called.
55781 *
55782 * Use <a href="#/p5/isLooping">isLooping()</a> to check current state of loop().
55783 *
55784 * @method noLoop
55785 * @example
55786 * <div>
55787 * <code>
55788 * function setup() {
55789 * createCanvas(100, 100);
55790 * background(200);
55791 * noLoop();
55792 * }
55793
55794 * function draw() {
55795 * line(10, 10, 90, 90);
55796 * }
55797 * </code>
55798 * </div>
55799 *
55800 * <div>
55801 * <code>
55802 * let x = 0;
55803 * function setup() {
55804 * createCanvas(100, 100);
55805 * }
55806 *
55807 * function draw() {
55808 * background(204);
55809 * x = x + 0.1;
55810 * if (x > width) {
55811 * x = 0;
55812 * }
55813 * line(x, 0, x, height);
55814 * }
55815 *
55816 * function mousePressed() {
55817 * noLoop();
55818 * }
55819 *
55820 * function mouseReleased() {
55821 * loop();
55822 * }
55823 * </code>
55824 * </div>
55825 *
55826 * @alt
55827 * 113 pixel long line extending from top-left to bottom right of canvas.
55828 * horizontal line moves slowly from left. Loops but stops on mouse press.
55829 */ _main.default.prototype.noLoop = function() {
55830 this._loop = false;
55831 };
55832
55833 /**
55834 * By default, p5.js loops through draw() continuously, executing the code within
55835 * it. However, the <a href="#/p5/draw">draw()</a> loop may be stopped by calling
55836 * <a href="#/p5/noLoop">noLoop()</a>. In that case, the <a href="#/p5/draw">draw()</a>
55837 * loop can be resumed with loop().
55838 *
55839 * Avoid calling loop() from inside setup().
55840 *
55841 * Use <a href="#/p5/isLooping">isLooping()</a> to check current state of loop().
55842 *
55843 * @method loop
55844 * @example
55845 * <div>
55846 * <code>
55847 * let x = 0;
55848 * function setup() {
55849 * createCanvas(100, 100);
55850 * noLoop();
55851 * }
55852 *
55853 * function draw() {
55854 * background(204);
55855 * x = x + 0.1;
55856 * if (x > width) {
55857 * x = 0;
55858 * }
55859 * line(x, 0, x, height);
55860 * }
55861 *
55862 * function mousePressed() {
55863 * loop();
55864 * }
55865 *
55866 * function mouseReleased() {
55867 * noLoop();
55868 * }
55869 * </code>
55870 * </div>
55871 *
55872 * @alt
55873 * horizontal line moves slowly from left. Loops but stops on mouse press.
55874 */
55875 _main.default.prototype.loop = function() {
55876 if (!this._loop) {
55877 this._loop = true;
55878 if (this._setupDone) {
55879 this._draw();
55880 }
55881 }
55882 };
55883
55884 /**
55885 * By default, p5.js loops through <a href="#/p5/draw">draw()</a> continuously,
55886 * executing the code within it. If the sketch is stopped with
55887 * <a href="#/p5/noLoop">noLoop()</a> or resumed with <a href="#/p5/loop">loop()</a>,
55888 * isLooping() returns the current state for use within custom event handlers.
55889 *
55890 * @method isLooping
55891 * @example
55892 * <div>
55893 * <code>
55894 * let checkbox, button, colBG, colFill;
55895 *
55896 * function setup() {
55897 * createCanvas(100, 100);
55898 *
55899 * button = createButton('Colorize if loop()');
55900 * button.position(0, 120);
55901 * button.mousePressed(changeBG);
55902 *
55903 * checkbox = createCheckbox('loop()', true);
55904 * checkbox.changed(checkLoop);
55905 *
55906 * colBG = color(0);
55907 * colFill = color(255);
55908 * }
55909 *
55910 * function changeBG() {
55911 * if (isLooping()) {
55912 * colBG = color(random(255), random(255), random(255));
55913 * colFill = color(random(255), random(255), random(255));
55914 * }
55915 * }
55916 *
55917 * function checkLoop() {
55918 * if (this.checked()) {
55919 * loop();
55920 * } else {
55921 * noLoop();
55922 * }
55923 * }
55924 *
55925 * function draw() {
55926 * background(colBG);
55927 * fill(colFill);
55928 * ellipse(frameCount % width, height / 2, 50);
55929 * }
55930 * </code>
55931 * </div>
55932 *
55933 * @alt
55934 * Ellipse moves slowly from left. Checkbox toggles loop()/noLoop().
55935 * Button colorizes sketch if isLooping().
55936 *
55937 */
55938 _main.default.prototype.isLooping = function() {
55939 return this._loop;
55940 };
55941
55942 /**
55943 * The <a href="#/p5/push">push()</a> function saves the current drawing style
55944 * settings and transformations, while <a href="#/p5/pop">pop()</a> restores these
55945 * settings. Note that these functions are always used together. They allow you to
55946 * change the style and transformation settings and later return to what you had.
55947 * When a new state is started with <a href="#/p5/push">push()</a>, it builds on
55948 * the current style and transform information. The <a href="#/p5/push">push()</a>
55949 * and <a href="#/p5/pop">pop()</a> functions can be embedded to provide more
55950 * control. (See the second example for a demonstration.)
55951 *
55952 * <a href="#/p5/push">push()</a> stores information related to the current transformation state
55953 * and style settings controlled by the following functions:
55954 * <a href="#/p5/fill">fill()</a>,
55955 * <a href="#/p5/noFill">noFill()</a>,
55956 * <a href="#/p5/noStroke">noStroke()</a>,
55957 * <a href="#/p5/stroke">stroke()</a>,
55958 * <a href="#/p5/tint">tint()</a>,
55959 * <a href="#/p5/noTint">noTint()</a>,
55960 * <a href="#/p5/strokeWeight">strokeWeight()</a>,
55961 * <a href="#/p5/strokeCap">strokeCap()</a>,
55962 * <a href="#/p5/strokeJoin">strokeJoin()</a>,
55963 * <a href="#/p5/imageMode">imageMode()</a>,
55964 * <a href="#/p5/rectMode">rectMode()</a>,
55965 * <a href="#/p5/ellipseMode">ellipseMode()</a>,
55966 * <a href="#/p5/colorMode">colorMode()</a>,
55967 * <a href="#/p5/textAlign">textAlign()</a>,
55968 * <a href="#/p5/textFont">textFont()</a>,
55969 * <a href="#/p5/textSize">textSize()</a>,
55970 * <a href="#/p5/textLeading">textLeading()</a>,
55971 * <a href="#/p5/applyMatrix">applyMatrix()</a>,
55972 * <a href="#/p5/resetMatrix">resetMatrix()</a>,
55973 * <a href="#/p5/rotate">rotate()</a>,
55974 * <a href="#/p5/scale">scale()</a>,
55975 * <a href="#/p5/shearX">shearX()</a>,
55976 * <a href="#/p5/shearY">shearY()</a>,
55977 * <a href="#/p5/translate">translate()</a>,
55978 * <a href="#/p5/noiseSeed">noiseSeed()</a>.
55979 *
55980 * In WEBGL mode additional style settings are stored. These are controlled by the
55981 * following functions: <a href="#/p5/setCamera">setCamera()</a>,
55982 * <a href="#/p5/ambientLight">ambientLight()</a>,
55983 * <a href="#/p5/directionalLight">directionalLight()</a>,
55984 * <a href="#/p5/pointLight">pointLight()</a>, <a href="#/p5/texture">texture()</a>,
55985 * <a href="#/p5/specularMaterial">specularMaterial()</a>,
55986 * <a href="#/p5/shininess">shininess()</a>,
55987 * <a href="#/p5/normalMaterial">normalMaterial()</a>
55988 * and <a href="#/p5/shader">shader()</a>.
55989 *
55990 * @method push
55991 * @example
55992 * <div>
55993 * <code>
55994 * ellipse(0, 50, 33, 33); // Left circle
55995 *
55996 * push(); // Start a new drawing state
55997 * strokeWeight(10);
55998 * fill(204, 153, 0);
55999 * translate(50, 0);
56000 * ellipse(0, 50, 33, 33); // Middle circle
56001 * pop(); // Restore original state
56002 *
56003 * ellipse(100, 50, 33, 33); // Right circle
56004 * </code>
56005 * </div>
56006 *
56007 * <div>
56008 * <code>
56009 * ellipse(0, 50, 33, 33); // Left circle
56010 *
56011 * push(); // Start a new drawing state
56012 * strokeWeight(10);
56013 * fill(204, 153, 0);
56014 * ellipse(33, 50, 33, 33); // Left-middle circle
56015 *
56016 * push(); // Start another new drawing state
56017 * stroke(0, 102, 153);
56018 * ellipse(66, 50, 33, 33); // Right-middle circle
56019 * pop(); // Restore previous state
56020 *
56021 * pop(); // Restore original state
56022 *
56023 * ellipse(100, 50, 33, 33); // Right circle
56024 * </code>
56025 * </div>
56026 *
56027 * @alt
56028 * Gold ellipse + thick black outline @center 2 white ellipses on left and right.
56029 * 2 Gold ellipses left black right blue stroke. 2 white ellipses on left+right.
56030 */
56031 _main.default.prototype.push = function() {
56032 this._styles.push({
56033 props: {
56034 _colorMode: this._colorMode
56035 },
56036
56037 renderer: this._renderer.push()
56038 });
56039 };
56040
56041 /**
56042 * The <a href="#/p5/push">push()</a> function saves the current drawing style
56043 * settings and transformations, while <a href="#/p5/pop">pop()</a> restores
56044 * these settings. Note that these functions are always used together. They allow
56045 * you to change the style and transformation settings and later return to what
56046 * you had. When a new state is started with <a href="#/p5/push">push()</a>, it
56047 * builds on the current style and transform information. The <a href="#/p5/push">push()</a>
56048 * and <a href="#/p5/pop">pop()</a> functions can be embedded to provide more
56049 * control. (See the second example for a demonstration.)
56050 *
56051 * <a href="#/p5/push">push()</a> stores information related to the current transformation state
56052 * and style settings controlled by the following functions:
56053 * <a href="#/p5/fill">fill()</a>,
56054 * <a href="#/p5/noFill">noFill()</a>,
56055 * <a href="#/p5/noStroke">noStroke()</a>,
56056 * <a href="#/p5/stroke">stroke()</a>,
56057 * <a href="#/p5/tint">tint()</a>,
56058 * <a href="#/p5/noTint">noTint()</a>,
56059 * <a href="#/p5/strokeWeight">strokeWeight()</a>,
56060 * <a href="#/p5/strokeCap">strokeCap()</a>,
56061 * <a href="#/p5/strokeJoin">strokeJoin()</a>,
56062 * <a href="#/p5/imageMode">imageMode()</a>,
56063 * <a href="#/p5/rectMode">rectMode()</a>,
56064 * <a href="#/p5/ellipseMode">ellipseMode()</a>,
56065 * <a href="#/p5/colorMode">colorMode()</a>,
56066 * <a href="#/p5/textAlign">textAlign()</a>,
56067 * <a href="#/p5/textFont">textFont()</a>,
56068 * <a href="#/p5/textSize">textSize()</a>,
56069 * <a href="#/p5/textLeading">textLeading()</a>,
56070 * <a href="#/p5/applyMatrix">applyMatrix()</a>,
56071 * <a href="#/p5/resetMatrix">resetMatrix()</a>,
56072 * <a href="#/p5/rotate">rotate()</a>,
56073 * <a href="#/p5/scale">scale()</a>,
56074 * <a href="#/p5/shearX">shearX()</a>,
56075 * <a href="#/p5/shearY">shearY()</a>,
56076 * <a href="#/p5/translate">translate()</a>,
56077 * <a href="#/p5/noiseSeed">noiseSeed()</a>.
56078 *
56079 * In WEBGL mode additional style settings are stored. These are controlled by
56080 * the following functions:
56081 * <a href="#/p5/setCamera">setCamera()</a>,
56082 * <a href="#/p5/ambientLight">ambientLight()</a>,
56083 * <a href="#/p5/directionalLight">directionalLight()</a>,
56084 * <a href="#/p5/pointLight">pointLight()</a>,
56085 * <a href="#/p5/texture">texture()</a>,
56086 * <a href="#/p5/specularMaterial">specularMaterial()</a>,
56087 * <a href="#/p5/shininess">shininess()</a>,
56088 * <a href="#/p5/normalMaterial">normalMaterial()</a> and
56089 * <a href="#/p5/shader">shader()</a>.
56090 *
56091 * @method pop
56092 * @example
56093 * <div>
56094 * <code>
56095 * ellipse(0, 50, 33, 33); // Left circle
56096 *
56097 * push(); // Start a new drawing state
56098 * translate(50, 0);
56099 * strokeWeight(10);
56100 * fill(204, 153, 0);
56101 * ellipse(0, 50, 33, 33); // Middle circle
56102 * pop(); // Restore original state
56103 *
56104 * ellipse(100, 50, 33, 33); // Right circle
56105 * </code>
56106 * </div>
56107 *
56108 * <div>
56109 * <code>
56110 * ellipse(0, 50, 33, 33); // Left circle
56111 *
56112 * push(); // Start a new drawing state
56113 * strokeWeight(10);
56114 * fill(204, 153, 0);
56115 * ellipse(33, 50, 33, 33); // Left-middle circle
56116 *
56117 * push(); // Start another new drawing state
56118 * stroke(0, 102, 153);
56119 * ellipse(66, 50, 33, 33); // Right-middle circle
56120 * pop(); // Restore previous state
56121 *
56122 * pop(); // Restore original state
56123 *
56124 * ellipse(100, 50, 33, 33); // Right circle
56125 * </code>
56126 * </div>
56127 *
56128 * @alt
56129 * Gold ellipse + thick black outline @center 2 white ellipses on left and right.
56130 * 2 Gold ellipses left black right blue stroke. 2 white ellipses on left+right.
56131 */
56132 _main.default.prototype.pop = function() {
56133 var style = this._styles.pop();
56134 if (style) {
56135 this._renderer.pop(style.renderer);
56136 Object.assign(this, style.props);
56137 } else {
56138 console.warn('pop() was called without matching push()');
56139 }
56140 };
56141
56142 /**
56143 * Executes the code within <a href="#/p5/draw">draw()</a> one time. This
56144 * function allows the program to update the display window only when necessary,
56145 * for example when an event registered by <a href="#/p5/mousePressed">mousePressed()</a>
56146 * or <a href="#/p5/keyPressed">keyPressed()</a> occurs.
56147 *
56148 * In structuring a program, it only makes sense to call <a href="#/p5/redraw">redraw()</a>
56149 * within events such as <a href="#/p5/mousePressed">mousePressed()</a>. This
56150 * is because <a href="#/p5/redraw">redraw()</a> does not run
56151 * <a href="#/p5/draw">draw()</a> immediately (it only sets a flag that indicates
56152 * an update is needed).
56153 *
56154 * The <a href="#/p5/redraw">redraw()</a> function does not work properly when
56155 * called inside <a href="#/p5/draw">draw()</a>.To enable/disable animations,
56156 * use <a href="#/p5/loop">loop()</a> and <a href="#/p5/noLoop">noLoop()</a>.
56157 *
56158 * In addition you can set the number of redraws per method call. Just
56159 * add an integer as single parameter for the number of redraws.
56160 *
56161 * @method redraw
56162 * @param {Integer} [n] Redraw for n-times. The default value is 1.
56163 * @example
56164 * <div><code>
56165 * let x = 0;
56166 *
56167 * function setup() {
56168 * createCanvas(100, 100);
56169 * noLoop();
56170 * }
56171 *
56172 * function draw() {
56173 * background(204);
56174 * line(x, 0, x, height);
56175 * }
56176 *
56177 * function mousePressed() {
56178 * x += 1;
56179 * redraw();
56180 * }
56181 * </code>
56182 * </div>
56183 *
56184 * <div class='norender'>
56185 * <code>
56186 * let x = 0;
56187 *
56188 * function setup() {
56189 * createCanvas(100, 100);
56190 * noLoop();
56191 * }
56192 *
56193 * function draw() {
56194 * background(204);
56195 * x += 1;
56196 * line(x, 0, x, height);
56197 * }
56198 *
56199 * function mousePressed() {
56200 * redraw(5);
56201 * }
56202 * </code>
56203 * </div>
56204 *
56205 * @alt
56206 * black line on far left of canvas
56207 * black line on far left of canvas
56208 */
56209 _main.default.prototype.redraw = function(n) {
56210 if (this._inUserDraw || !this._setupDone) {
56211 return;
56212 }
56213
56214 var numberOfRedraws = parseInt(n);
56215 if (isNaN(numberOfRedraws) || numberOfRedraws < 1) {
56216 numberOfRedraws = 1;
56217 }
56218
56219 var context = this._isGlobal ? window : this;
56220 var userSetup = context.setup;
56221 var userDraw = context.draw;
56222 if (typeof userDraw === 'function') {
56223 if (typeof userSetup === 'undefined') {
56224 context.scale(context._pixelDensity, context._pixelDensity);
56225 }
56226 var callMethod = function callMethod(f) {
56227 f.call(context);
56228 };
56229 for (var idxRedraw = 0; idxRedraw < numberOfRedraws; idxRedraw++) {
56230 context.resetMatrix();
56231 if (context._renderer.isP3D) {
56232 context._renderer._update();
56233 }
56234 context._setProperty('frameCount', context.frameCount + 1);
56235 context._registeredMethods.pre.forEach(callMethod);
56236 this._inUserDraw = true;
56237 try {
56238 userDraw();
56239 } finally {
56240 this._inUserDraw = false;
56241 }
56242 context._registeredMethods.post.forEach(callMethod);
56243 }
56244 }
56245 };
56246
56247 /**
56248 * The `p5()` constructor enables you to activate "instance mode" instead of normal
56249 * "global mode". This is an advanced topic. A short description and example is
56250 * included below. Please see
56251 * <a target="blank" href="https://www.youtube.com/watch?v=Su792jEauZg&feature=youtu.be">
56252 * Dan Shiffman's Coding Train video tutorial</a> or this
56253 * <a target="blank" href="https://github.com/processing/p5.js/wiki/p5.js-overview#instantiation--namespace">tutorial page</a>
56254 * for more info.
56255 *
56256 * By default, all p5.js functions are in the global namespace (i.e. bound to the window
56257 * object), meaning you can call them simply `ellipse()`, `fill()`, etc. However, this
56258 * might be inconvenient if you are mixing with other JS libraries (synchronously or
56259 * asynchronously) or writing long programs of your own. p5.js currently supports a
56260 * way around this problem called "instance mode". In instance mode, all p5 functions
56261 * are bound up in a single variable instead of polluting your global namespace.
56262 *
56263 * Optionally, you can specify a default container for the canvas and any other elements
56264 * to append to with a second argument. You can give the ID of an element in your html,
56265 * or an html node itself.
56266 *
56267 * Note that creating instances like this also allows you to have more than one p5 sketch on
56268 * a single web page, as they will each be wrapped up with their own set up variables. Of
56269 * course, you could also use iframes to have multiple sketches in global mode.
56270 *
56271 * @method p5
56272 * @param {Object} sketch a function containing a p5.js sketch
56273 * @param {String|Object} node ID or pointer to HTML DOM node to contain sketch in
56274 * @example
56275 * <div class='norender'><code>
56276 * const s = p => {
56277 * let x = 100;
56278 * let y = 100;
56279 *
56280 * p.setup = function() {
56281 * p.createCanvas(700, 410);
56282 * };
56283 *
56284 * p.draw = function() {
56285 * p.background(0);
56286 * p.fill(255);
56287 * p.rect(x, y, 50, 50);
56288 * };
56289 * };
56290 *
56291 * new p5(s); // invoke p5
56292 * </code></div>
56293 *
56294 * @alt
56295 * white rectangle on black background
56296 */ var _default = _main.default;
56297 exports.default = _default;
56298 },
56299 { './main': 54 }
56300 ],
56301 67: [
56302 function(_dereq_, module, exports) {
56303 'use strict';
56304 Object.defineProperty(exports, '__esModule', { value: true });
56305 exports.default = void 0;
56306
56307 var _main = _interopRequireDefault(_dereq_('./main'));
56308 function _interopRequireDefault(obj) {
56309 return obj && obj.__esModule ? obj : { default: obj };
56310 }
56311 /**
56312 * @module Transform
56313 * @submodule Transform
56314 * @for p5
56315 * @requires core
56316 * @requires constants
56317 */ /**
56318 * Multiplies the current matrix by the one specified through the parameters.
56319 * This is a powerful operation that can perform the equivalent of translate,
56320 * scale, shear and rotate all at once. You can learn more about transformation
56321 * matrices on <a href="https://en.wikipedia.org/wiki/Transformation_matrix">
56322 * Wikipedia</a>.
56323 *
56324 * The naming of the arguments here follows the naming of the <a href=
56325 * "https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-transform">
56326 * WHATWG specification</a> and corresponds to a
56327 * transformation matrix of the
56328 * form:
56329 *
56330 * > <img style="max-width: 150px" src="assets/transformation-matrix.png"
56331 * alt="The transformation matrix used when applyMatrix is called"/>
56332 *
56333 * @method applyMatrix
56334 * @param {Number} a numbers which define the 2x3 matrix to be multiplied
56335 * @param {Number} b numbers which define the 2x3 matrix to be multiplied
56336 * @param {Number} c numbers which define the 2x3 matrix to be multiplied
56337 * @param {Number} d numbers which define the 2x3 matrix to be multiplied
56338 * @param {Number} e numbers which define the 2x3 matrix to be multiplied
56339 * @param {Number} f numbers which define the 2x3 matrix to be multiplied
56340 * @chainable
56341 * @example
56342 * <div>
56343 * <code>
56344 * function setup() {
56345 * frameRate(10);
56346 * rectMode(CENTER);
56347 * }
56348 *
56349 * function draw() {
56350 * let step = frameCount % 20;
56351 * background(200);
56352 * // Equivalent to translate(x, y);
56353 * applyMatrix(1, 0, 0, 1, 40 + step, 50);
56354 * rect(0, 0, 50, 50);
56355 * }
56356 * </code>
56357 * </div>
56358 *
56359 * <div>
56360 * <code>
56361 * function setup() {
56362 * frameRate(10);
56363 * rectMode(CENTER);
56364 * }
56365 *
56366 * function draw() {
56367 * let step = frameCount % 20;
56368 * background(200);
56369 * translate(50, 50);
56370 * // Equivalent to scale(x, y);
56371 * applyMatrix(1 / step, 0, 0, 1 / step, 0, 0);
56372 * rect(0, 0, 50, 50);
56373 * }
56374 * </code>
56375 * </div>
56376 *
56377 * <div>
56378 * <code>
56379 * function setup() {
56380 * frameRate(10);
56381 * rectMode(CENTER);
56382 * }
56383 *
56384 * function draw() {
56385 * let step = frameCount % 20;
56386 * let angle = map(step, 0, 20, 0, TWO_PI);
56387 * let cos_a = cos(angle);
56388 * let sin_a = sin(angle);
56389 * background(200);
56390 * translate(50, 50);
56391 * // Equivalent to rotate(angle);
56392 * applyMatrix(cos_a, sin_a, -sin_a, cos_a, 0, 0);
56393 * rect(0, 0, 50, 50);
56394 * }
56395 * </code>
56396 * </div>
56397 *
56398 * <div>
56399 * <code>
56400 * function setup() {
56401 * frameRate(10);
56402 * rectMode(CENTER);
56403 * }
56404 *
56405 * function draw() {
56406 * let step = frameCount % 20;
56407 * let angle = map(step, 0, 20, -PI / 4, PI / 4);
56408 * background(200);
56409 * translate(50, 50);
56410 * // equivalent to shearX(angle);
56411 * let shear_factor = 1 / tan(PI / 2 - angle);
56412 * applyMatrix(1, 0, shear_factor, 1, 0, 0);
56413 * rect(0, 0, 50, 50);
56414 * }
56415 * </code>
56416 * </div>
56417 *
56418 * <div modernizr='webgl'>
56419 * <code>
56420 * function setup() {
56421 * createCanvas(100, 100, WEBGL);
56422 * noFill();
56423 * }
56424 *
56425 * function draw() {
56426 * background(200);
56427 * rotateY(PI / 6);
56428 * stroke(153);
56429 * box(35);
56430 * let rad = millis() / 1000;
56431 * // Set rotation angles
56432 * let ct = cos(rad);
56433 * let st = sin(rad);
56434 * // Matrix for rotation around the Y axis
56435 * // prettier-ignore
56436 * applyMatrix( ct, 0.0, st, 0.0,
56437 * 0.0, 1.0, 0.0, 0.0,
56438 * -st, 0.0, ct, 0.0,
56439 * 0.0, 0.0, 0.0, 1.0);
56440 * stroke(255);
56441 * box(50);
56442 * }
56443 * </code>
56444 * </div>
56445 *
56446 * @alt
56447 * A rectangle translating to the right
56448 * A rectangle shrinking to the center
56449 * A rectangle rotating clockwise about the center
56450 * A rectangle shearing
56451 */ _main.default.prototype.applyMatrix = function(a, b, c, d, e, f) {
56452 var _this$_renderer;
56453 (_this$_renderer = this._renderer).applyMatrix.apply(
56454 _this$_renderer,
56455 arguments
56456 );
56457 return this;
56458 };
56459
56460 /**
56461 * Replaces the current matrix with the identity matrix.
56462 *
56463 * @method resetMatrix
56464 * @chainable
56465 * @example
56466 * <div>
56467 * <code>
56468 * translate(50, 50);
56469 * applyMatrix(0.5, 0.5, -0.5, 0.5, 0, 0);
56470 * rect(0, 0, 20, 20);
56471 * // Note that the translate is also reset.
56472 * resetMatrix();
56473 * rect(0, 0, 20, 20);
56474 * </code>
56475 * </div>
56476 *
56477 * @alt
56478 * A rotated retangle in the center with another at the top left corner
56479 */
56480 _main.default.prototype.resetMatrix = function() {
56481 this._renderer.resetMatrix();
56482 return this;
56483 };
56484
56485 /**
56486 * Rotates a shape by the amount specified by the angle parameter. This
56487 * function accounts for <a href="#/p5/angleMode">angleMode</a>, so angles
56488 * can be entered in either RADIANS or DEGREES.
56489 *
56490 * Objects are always rotated around their relative position to the
56491 * origin and positive numbers rotate objects in a clockwise direction.
56492 * Transformations apply to everything that happens after and subsequent
56493 * calls to the function accumulates the effect. For example, calling
56494 * rotate(HALF_PI) and then rotate(HALF_PI) is the same as rotate(PI).
56495 * All tranformations are reset when <a href="#/p5/draw">draw()</a> begins again.
56496 *
56497 * Technically, <a href="#/p5/rotate">rotate()</a> multiplies the current transformation matrix
56498 * by a rotation matrix. This function can be further controlled by
56499 * the <a href="#/p5/push">push()</a> and <a href="#/p5/pop">pop()</a>.
56500 *
56501 * @method rotate
56502 * @param {Number} angle the angle of rotation, specified in radians
56503 * or degrees, depending on current angleMode
56504 * @param {p5.Vector|Number[]} [axis] (in 3d) the axis to rotate around
56505 * @chainable
56506 * @example
56507 * <div>
56508 * <code>
56509 * translate(width / 2, height / 2);
56510 * rotate(PI / 3.0);
56511 * rect(-26, -26, 52, 52);
56512 * </code>
56513 * </div>
56514 *
56515 * @alt
56516 * white 52x52 rect with black outline at center rotated counter 45 degrees
56517 */
56518 _main.default.prototype.rotate = function(angle, axis) {
56519 _main.default._validateParameters('rotate', arguments);
56520 this._renderer.rotate(this._toRadians(angle), axis);
56521 return this;
56522 };
56523
56524 /**
56525 * Rotates a shape around X axis by the amount specified in angle parameter.
56526 * The angles can be entered in either RADIANS or DEGREES.
56527 *
56528 * Objects are always rotated around their relative position to the
56529 * origin and positive numbers rotate objects in a clockwise direction.
56530 * All tranformations are reset when <a href="#/p5/draw">draw()</a> begins again.
56531 *
56532 * @method rotateX
56533 * @param {Number} angle the angle of rotation, specified in radians
56534 * or degrees, depending on current angleMode
56535 * @chainable
56536 * @example
56537 * <div modernizr='webgl'>
56538 * <code>
56539 * function setup() {
56540 * createCanvas(100, 100, WEBGL);
56541 * }
56542 * function draw() {
56543 * background(255);
56544 * rotateX(millis() / 1000);
56545 * box();
56546 * }
56547 * </code>
56548 * </div>
56549 *
56550 * @alt
56551 * 3d box rotating around the x axis.
56552 */
56553 _main.default.prototype.rotateX = function(angle) {
56554 this._assert3d('rotateX');
56555 _main.default._validateParameters('rotateX', arguments);
56556 this._renderer.rotateX(this._toRadians(angle));
56557 return this;
56558 };
56559
56560 /**
56561 * Rotates a shape around Y axis by the amount specified in angle parameter.
56562 * The angles can be entered in either RADIANS or DEGREES.
56563 *
56564 * Objects are always rotated around their relative position to the
56565 * origin and positive numbers rotate objects in a clockwise direction.
56566 * All tranformations are reset when <a href="#/p5/draw">draw()</a> begins again.
56567 *
56568 * @method rotateY
56569 * @param {Number} angle the angle of rotation, specified in radians
56570 * or degrees, depending on current angleMode
56571 * @chainable
56572 * @example
56573 * <div modernizr='webgl'>
56574 * <code>
56575 * function setup() {
56576 * createCanvas(100, 100, WEBGL);
56577 * }
56578 * function draw() {
56579 * background(255);
56580 * rotateY(millis() / 1000);
56581 * box();
56582 * }
56583 * </code>
56584 * </div>
56585 *
56586 * @alt
56587 * 3d box rotating around the y axis.
56588 */
56589 _main.default.prototype.rotateY = function(angle) {
56590 this._assert3d('rotateY');
56591 _main.default._validateParameters('rotateY', arguments);
56592 this._renderer.rotateY(this._toRadians(angle));
56593 return this;
56594 };
56595
56596 /**
56597 * Rotates a shape around Z axis by the amount specified in angle parameter.
56598 * The angles can be entered in either RADIANS or DEGREES.
56599 *
56600 * This method works in WEBGL mode only.
56601 *
56602 * Objects are always rotated around their relative position to the
56603 * origin and positive numbers rotate objects in a clockwise direction.
56604 * All tranformations are reset when <a href="#/p5/draw">draw()</a> begins again.
56605 *
56606 * @method rotateZ
56607 * @param {Number} angle the angle of rotation, specified in radians
56608 * or degrees, depending on current angleMode
56609 * @chainable
56610 * @example
56611 * <div modernizr='webgl'>
56612 * <code>
56613 * function setup() {
56614 * createCanvas(100, 100, WEBGL);
56615 * }
56616 * function draw() {
56617 * background(255);
56618 * rotateZ(millis() / 1000);
56619 * box();
56620 * }
56621 * </code>
56622 * </div>
56623 *
56624 * @alt
56625 * 3d box rotating around the z axis.
56626 */
56627 _main.default.prototype.rotateZ = function(angle) {
56628 this._assert3d('rotateZ');
56629 _main.default._validateParameters('rotateZ', arguments);
56630 this._renderer.rotateZ(this._toRadians(angle));
56631 return this;
56632 };
56633
56634 /**
56635 * Increases or decreases the size of a shape by expanding or contracting
56636 * vertices. Objects always scale from their relative origin to the
56637 * coordinate system. Scale values are specified as decimal percentages.
56638 * For example, the function call scale(2.0) increases the dimension of a
56639 * shape by 200%.
56640 *
56641 * Transformations apply to everything that happens after and subsequent
56642 * calls to the function multiply the effect. For example, calling scale(2.0)
56643 * and then scale(1.5) is the same as scale(3.0). If <a href="#/p5/scale">scale()</a> is called
56644 * within <a href="#/p5/draw">draw()</a>, the transformation is reset when the loop begins again.
56645 *
56646 * Using this function with the z parameter is only available in WEBGL mode.
56647 * This function can be further controlled with <a href="#/p5/push">push()</a> and <a href="#/p5/pop">pop()</a>.
56648 *
56649 * @method scale
56650 * @param {Number|p5.Vector|Number[]} s
56651 * percent to scale the object, or percentage to
56652 * scale the object in the x-axis if multiple arguments
56653 * are given
56654 * @param {Number} [y] percent to scale the object in the y-axis
56655 * @param {Number} [z] percent to scale the object in the z-axis (webgl only)
56656 * @chainable
56657 * @example
56658 * <div>
56659 * <code>
56660 * rect(30, 20, 50, 50);
56661 * scale(0.5);
56662 * rect(30, 20, 50, 50);
56663 * </code>
56664 * </div>
56665 *
56666 * <div>
56667 * <code>
56668 * rect(30, 20, 50, 50);
56669 * scale(0.5, 1.3);
56670 * rect(30, 20, 50, 50);
56671 * </code>
56672 * </div>
56673 *
56674 * @alt
56675 * white 52x52 rect with black outline at center rotated counter 45 degrees
56676 * 2 white rects with black outline- 1 50x50 at center. other 25x65 bottom left
56677 */
56678 /**
56679 * @method scale
56680 * @param {p5.Vector|Number[]} scales per-axis percents to scale the object
56681 * @chainable
56682 */
56683 _main.default.prototype.scale = function(x, y, z) {
56684 _main.default._validateParameters('scale', arguments);
56685 // Only check for Vector argument type if Vector is available
56686 if (x instanceof _main.default.Vector) {
56687 var v = x;
56688 x = v.x;
56689 y = v.y;
56690 z = v.z;
56691 } else if (x instanceof Array) {
56692 var rg = x;
56693 x = rg[0];
56694 y = rg[1];
56695 z = rg[2] || 1;
56696 }
56697 if (isNaN(y)) {
56698 y = z = x;
56699 } else if (isNaN(z)) {
56700 z = 1;
56701 }
56702
56703 this._renderer.scale.call(this._renderer, x, y, z);
56704
56705 return this;
56706 };
56707
56708 /**
56709 * Shears a shape around the x-axis by the amount specified by the angle
56710 * parameter. Angles should be specified in the current angleMode.
56711 * Objects are always sheared around their relative position to the origin
56712 * and positive numbers shear objects in a clockwise direction.
56713 *
56714 * Transformations apply to everything that happens after and subsequent
56715 * calls to the function accumulates the effect. For example, calling
56716 * shearX(PI/2) and then shearX(PI/2) is the same as shearX(PI).
56717 * If <a href="#/p5/shearX">shearX()</a> is called within the <a href="#/p5/draw">draw()</a>,
56718 * the transformation is reset when the loop begins again.
56719 *
56720 * Technically, <a href="#/p5/shearX">shearX()</a> multiplies the current
56721 * transformation matrix by a rotation matrix. This function can be further
56722 * controlled by the <a href="#/p5/push">push()</a> and <a href="#/p5/pop">pop()</a> functions.
56723 *
56724 * @method shearX
56725 * @param {Number} angle angle of shear specified in radians or degrees,
56726 * depending on current angleMode
56727 * @chainable
56728 * @example
56729 * <div>
56730 * <code>
56731 * translate(width / 4, height / 4);
56732 * shearX(PI / 4.0);
56733 * rect(0, 0, 30, 30);
56734 * </code>
56735 * </div>
56736 *
56737 * @alt
56738 * white irregular quadrilateral with black outline at top middle.
56739 */
56740 _main.default.prototype.shearX = function(angle) {
56741 _main.default._validateParameters('shearX', arguments);
56742 var rad = this._toRadians(angle);
56743 this._renderer.applyMatrix(1, 0, Math.tan(rad), 1, 0, 0);
56744 return this;
56745 };
56746
56747 /**
56748 * Shears a shape around the y-axis the amount specified by the angle
56749 * parameter. Angles should be specified in the current angleMode. Objects
56750 * are always sheared around their relative position to the origin and
56751 * positive numbers shear objects in a clockwise direction.
56752 *
56753 * Transformations apply to everything that happens after and subsequent
56754 * calls to the function accumulates the effect. For example, calling
56755 * shearY(PI/2) and then shearY(PI/2) is the same as shearY(PI). If
56756 * <a href="#/p5/shearY">shearY()</a> is called within the <a href="#/p5/draw">draw()</a>, the transformation is reset when
56757 * the loop begins again.
56758 *
56759 * Technically, <a href="#/p5/shearY">shearY()</a> multiplies the current transformation matrix by a
56760 * rotation matrix. This function can be further controlled by the
56761 * <a href="#/p5/push">push()</a> and <a href="#/p5/pop">pop()</a> functions.
56762 *
56763 * @method shearY
56764 * @param {Number} angle angle of shear specified in radians or degrees,
56765 * depending on current angleMode
56766 * @chainable
56767 * @example
56768 * <div>
56769 * <code>
56770 * translate(width / 4, height / 4);
56771 * shearY(PI / 4.0);
56772 * rect(0, 0, 30, 30);
56773 * </code>
56774 * </div>
56775 *
56776 * @alt
56777 * white irregular quadrilateral with black outline at middle bottom.
56778 */
56779 _main.default.prototype.shearY = function(angle) {
56780 _main.default._validateParameters('shearY', arguments);
56781 var rad = this._toRadians(angle);
56782 this._renderer.applyMatrix(1, Math.tan(rad), 0, 1, 0, 0);
56783 return this;
56784 };
56785
56786 /**
56787 * Specifies an amount to displace objects within the display window.
56788 * The x parameter specifies left/right translation, the y parameter
56789 * specifies up/down translation.
56790 *
56791 * Transformations are cumulative and apply to everything that happens after
56792 * and subsequent calls to the function accumulates the effect. For example,
56793 * calling translate(50, 0) and then translate(20, 0) is the same as
56794 * translate(70, 0). If <a href="#/p5/translate">translate()</a> is called within <a href="#/p5/draw">draw()</a>, the
56795 * transformation is reset when the loop begins again. This function can be
56796 * further controlled by using <a href="#/p5/push">push()</a> and <a href="#/p5/pop">pop()</a>.
56797 *
56798 * @method translate
56799 * @param {Number} x left/right translation
56800 * @param {Number} y up/down translation
56801 * @param {Number} [z] forward/backward translation (webgl only)
56802 * @chainable
56803 * @example
56804 * <div>
56805 * <code>
56806 * translate(30, 20);
56807 * rect(0, 0, 55, 55);
56808 * </code>
56809 * </div>
56810 *
56811 * <div>
56812 * <code>
56813 * rect(0, 0, 55, 55); // Draw rect at original 0,0
56814 * translate(30, 20);
56815 * rect(0, 0, 55, 55); // Draw rect at new 0,0
56816 * translate(14, 14);
56817 * rect(0, 0, 55, 55); // Draw rect at new 0,0
56818 * </code>
56819 * </div>
56820 *
56821
56822 * <div>
56823 * <code>
56824 * function draw() {
56825 * background(200);
56826 * rectMode(CENTER);
56827 * translate(width / 2, height / 2);
56828 * translate(p5.Vector.fromAngle(millis() / 1000, 40));
56829 * rect(0, 0, 20, 20);
56830 * }
56831 * </code>
56832 * </div>
56833 *
56834 * @alt
56835 * white 55x55 rect with black outline at center right.
56836 * 3 white 55x55 rects with black outlines at top-l, center-r and bottom-r.
56837 * a 20x20 white rect moving in a circle around the canvas
56838 */
56839 /**
56840 * @method translate
56841 * @param {p5.Vector} vector the vector to translate by
56842 * @chainable
56843 */
56844 _main.default.prototype.translate = function(x, y, z) {
56845 _main.default._validateParameters('translate', arguments);
56846 if (this._renderer.isP3D) {
56847 this._renderer.translate(x, y, z);
56848 } else {
56849 this._renderer.translate(x, y);
56850 }
56851 return this;
56852 };
56853 var _default = _main.default;
56854 exports.default = _default;
56855 },
56856 { './main': 54 }
56857 ],
56858 68: [
56859 function(_dereq_, module, exports) {
56860 'use strict';
56861
56862 var _main = _interopRequireDefault(_dereq_('../core/main'));
56863 function _interopRequireDefault(obj) {
56864 return obj && obj.__esModule ? obj : { default: obj };
56865 }
56866 function _toConsumableArray(arr) {
56867 return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread();
56868 }
56869 function _nonIterableSpread() {
56870 throw new TypeError('Invalid attempt to spread non-iterable instance');
56871 }
56872 function _iterableToArray(iter) {
56873 if (
56874 Symbol.iterator in Object(iter) ||
56875 Object.prototype.toString.call(iter) === '[object Arguments]'
56876 )
56877 return Array.from(iter);
56878 }
56879 function _arrayWithoutHoles(arr) {
56880 if (Array.isArray(arr)) {
56881 for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) {
56882 arr2[i] = arr[i];
56883 }
56884 return arr2;
56885 }
56886 }
56887 function _typeof(obj) {
56888 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
56889 _typeof = function _typeof(obj) {
56890 return typeof obj;
56891 };
56892 } else {
56893 _typeof = function _typeof(obj) {
56894 return obj &&
56895 typeof Symbol === 'function' &&
56896 obj.constructor === Symbol &&
56897 obj !== Symbol.prototype
56898 ? 'symbol'
56899 : typeof obj;
56900 };
56901 }
56902 return _typeof(obj);
56903 }
56904 /**
56905 *
56906 * Stores a value in local storage under the key name.
56907 * Local storage is saved in the browser and persists
56908 * between browsing sessions and page reloads.
56909 * The key can be the name of the variable but doesn't
56910 * have to be. To retrieve stored items
56911 * see <a href="#/p5/getItem">getItem</a>.
56912 *
56913 * Sensitive data such as passwords or personal information
56914 * should not be stored in local storage.
56915 *
56916 * @method storeItem
56917 * @for p5
56918 * @param {String} key
56919 * @param {String|Number|Object|Boolean|p5.Color|p5.Vector} value
56920 *
56921 * @example
56922 * <div><code>
56923 * // Type to change the letter in the
56924 * // center of the canvas.
56925 * // If you reload the page, it will
56926 * // still display the last key you entered
56927 *
56928 * let myText;
56929 *
56930 * function setup() {
56931 * createCanvas(100, 100);
56932 * myText = getItem('myText');
56933 * if (myText === null) {
56934 * myText = '';
56935 * }
56936 * }
56937 *
56938 * function draw() {
56939 * textSize(40);
56940 * background(255);
56941 * text(myText, width / 2, height / 2);
56942 * }
56943 *
56944 * function keyPressed() {
56945 * myText = key;
56946 * storeItem('myText', myText);
56947 * }
56948 * </code></div>
56949 *
56950 * @alt
56951 * When you type the key name is displayed as black text on white background.
56952 * If you reload the page, the last letter typed is still displaying.
56953 */
56954 _main.default.prototype.storeItem = function(key, value) {
56955 if (typeof key !== 'string') {
56956 console.log(
56957 'The argument that you passed to storeItem() - '.concat(
56958 key,
56959 ' is not a string.'
56960 )
56961 );
56962 }
56963 if (key.endsWith('p5TypeID')) {
56964 console.log(
56965 'The argument that you passed to storeItem() - '.concat(
56966 key,
56967 " must not end with 'p5TypeID'."
56968 )
56969 );
56970 }
56971
56972 if (typeof value === 'undefined') {
56973 console.log('You cannot store undefined variables using storeItem().');
56974 }
56975 var type = _typeof(value);
56976 switch (type) {
56977 case 'number':
56978 case 'boolean':
56979 value = value.toString();
56980 break;
56981 case 'object':
56982 if (value instanceof _main.default.Color) {
56983 type = 'p5.Color';
56984 } else if (value instanceof _main.default.Vector) {
56985 type = 'p5.Vector';
56986 var coord = [value.x, value.y, value.z];
56987 value = coord;
56988 }
56989 value = JSON.stringify(value);
56990 break;
56991 case 'string':
56992 default:
56993 break;
56994 }
56995
56996 localStorage.setItem(key, value);
56997 var typeKey = ''.concat(key, 'p5TypeID');
56998 localStorage.setItem(typeKey, type);
56999 };
57000
57001 /**
57002 *
57003 * Returns the value of an item that was stored in local storage
57004 * using storeItem()
57005 *
57006 * @method getItem
57007 * @for p5
57008 * @param {String} key name that you wish to use to store in local storage
57009 * @return {Number|Object|String|Boolean|p5.Color|p5.Vector} Value of stored item
57010 *
57011 * @example
57012 * <div><code>
57013 * // Click the mouse to change
57014 * // the color of the background
57015 * // Once you have changed the color
57016 * // it will stay changed even when you
57017 * // reload the page.
57018 *
57019 * let myColor;
57020 *
57021 * function setup() {
57022 * createCanvas(100, 100);
57023 * myColor = getItem('myColor');
57024 * }
57025 *
57026 * function draw() {
57027 * if (myColor !== null) {
57028 * background(myColor);
57029 * }
57030 * }
57031 *
57032 * function mousePressed() {
57033 * myColor = color(random(255), random(255), random(255));
57034 * storeItem('myColor', myColor);
57035 * }
57036 * </code></div>
57037 *
57038 * @alt
57039 * If you click, the canvas changes to a random color.
57040 * If you reload the page, the canvas is still the color it
57041 * was when the page was previously loaded.
57042 */
57043 _main.default.prototype.getItem = function(key) {
57044 var value = localStorage.getItem(key);
57045 var type = localStorage.getItem(''.concat(key, 'p5TypeID'));
57046 if (typeof type === 'undefined') {
57047 console.log(
57048 'Unable to determine type of item stored under '.concat(
57049 key,
57050 'in local storage. Did you save the item with something other than setItem()?'
57051 )
57052 );
57053 } else if (value !== null) {
57054 switch (type) {
57055 case 'number':
57056 value = parseInt(value);
57057 break;
57058 case 'boolean':
57059 value = value === 'true';
57060 break;
57061 case 'object':
57062 value = JSON.parse(value);
57063 break;
57064 case 'p5.Color':
57065 value = JSON.parse(value);
57066 value = this.color.apply(this, _toConsumableArray(value.levels));
57067 break;
57068 case 'p5.Vector':
57069 value = JSON.parse(value);
57070 value = this.createVector.apply(this, _toConsumableArray(value));
57071 break;
57072 case 'string':
57073 default:
57074 break;
57075 }
57076 }
57077 return value;
57078 };
57079
57080 /**
57081 *
57082 * Clears all local storage items set with storeItem()
57083 * for the current domain.
57084 *
57085 * @method clearStorage
57086 * @for p5
57087 *
57088 * @example
57089 * <div class="norender">
57090 * <code>
57091 * function setup() {
57092 * let myNum = 10;
57093 * let myBool = false;
57094 * storeItem('myNum', myNum);
57095 * storeItem('myBool', myBool);
57096 * print(getItem('myNum')); // logs 10 to the console
57097 * print(getItem('myBool')); // logs false to the console
57098 * clearStorage();
57099 * print(getItem('myNum')); // logs null to the console
57100 * print(getItem('myBool')); // logs null to the console
57101 * }
57102 * </code></div>
57103 */
57104 _main.default.prototype.clearStorage = function() {
57105 localStorage.clear();
57106 };
57107
57108 /**
57109 *
57110 * Removes an item that was stored with storeItem()
57111 *
57112 * @method removeItem
57113 * @param {String} key
57114 * @for p5
57115 *
57116 * @example
57117 * <div class="norender">
57118 * <code>
57119 * function setup() {
57120 * let myVar = 10;
57121 * storeItem('myVar', myVar);
57122 * print(getItem('myVar')); // logs 10 to the console
57123 * removeItem('myVar');
57124 * print(getItem('myVar')); // logs null to the console
57125 * }
57126 * </code></div>
57127 */
57128 _main.default.prototype.removeItem = function(key) {
57129 if (typeof key !== 'string') {
57130 console.log(
57131 'The argument that you passed to removeItem() - '.concat(
57132 key,
57133 ' is not a string.'
57134 )
57135 );
57136 }
57137 localStorage.removeItem(key);
57138 localStorage.removeItem(''.concat(key, 'p5TypeID'));
57139 };
57140 },
57141 { '../core/main': 54 }
57142 ],
57143 69: [
57144 function(_dereq_, module, exports) {
57145 'use strict';
57146 Object.defineProperty(exports, '__esModule', { value: true });
57147 exports.default = void 0;
57148
57149 var _main = _interopRequireDefault(_dereq_('../core/main'));
57150 function _interopRequireDefault(obj) {
57151 return obj && obj.__esModule ? obj : { default: obj };
57152 }
57153 /**
57154 * @module Data
57155 * @submodule Dictionary
57156 * @for p5.TypedDict
57157 * @requires core
57158 *
57159 * This module defines the p5 methods for the p5 Dictionary classes.
57160 * The classes StringDict and NumberDict are for storing and working
57161 * with key-value pairs.
57162 */ /**
57163 *
57164 * Creates a new instance of p5.StringDict using the key-value pair
57165 * or the object you provide.
57166 *
57167 * @method createStringDict
57168 * @for p5
57169 * @param {String} key
57170 * @param {String} value
57171 * @return {p5.StringDict}
57172 *
57173 * @example
57174 * <div class="norender">
57175 * <code>
57176 * function setup() {
57177 * let myDictionary = createStringDict('p5', 'js');
57178 * print(myDictionary.hasKey('p5')); // logs true to console
57179 *
57180 * let anotherDictionary = createStringDict({ happy: 'coding' });
57181 * print(anotherDictionary.hasKey('happy')); // logs true to console
57182 * }
57183 * </code></div>
57184 */ /**
57185 * @method createStringDict
57186 * @param {Object} object object
57187 * @return {p5.StringDict}
57188 */ _main.default.prototype.createStringDict = function(key, value) {
57189 _main.default._validateParameters('createStringDict', arguments);
57190 return new _main.default.StringDict(key, value);
57191 };
57192 /**
57193 *
57194 * Creates a new instance of <a href="#/p5.NumberDict">p5.NumberDict</a> using the key-value pair
57195 * or object you provide.
57196 *
57197 * @method createNumberDict
57198 * @for p5
57199 * @param {Number} key
57200 * @param {Number} value
57201 * @return {p5.NumberDict}
57202 *
57203 * @example
57204 * <div class="norender">
57205 * <code>
57206 * function setup() {
57207 * let myDictionary = createNumberDict(100, 42);
57208 * print(myDictionary.hasKey(100)); // logs true to console
57209 *
57210 * let anotherDictionary = createNumberDict({ 200: 84 });
57211 * print(anotherDictionary.hasKey(200)); // logs true to console
57212 * }
57213 * </code></div>
57214 */
57215 /**
57216 * @method createNumberDict
57217 * @param {Object} object object
57218 * @return {p5.NumberDict}
57219 */
57220
57221 _main.default.prototype.createNumberDict = function(key, value) {
57222 _main.default._validateParameters('createNumberDict', arguments);
57223 return new _main.default.NumberDict(key, value);
57224 };
57225
57226 /**
57227 *
57228 * Base class for all p5.Dictionary types. Specifically
57229 * typed Dictionary classes inherit from this class.
57230 *
57231 * @class p5.TypedDict
57232 * @constructor
57233 */
57234
57235 _main.default.TypedDict = function(key, value) {
57236 if (key instanceof Object) {
57237 this.data = key;
57238 } else {
57239 this.data = {};
57240 this.data[key] = value;
57241 }
57242 return this;
57243 };
57244
57245 /**
57246 * Returns the number of key-value pairs currently stored in the Dictionary.
57247 *
57248 * @method size
57249 * @return {Integer} the number of key-value pairs in the Dictionary
57250 *
57251 * @example
57252 * <div class="norender">
57253 * <code>
57254 * function setup() {
57255 * let myDictionary = createNumberDict(1, 10);
57256 * myDictionary.create(2, 20);
57257 * myDictionary.create(3, 30);
57258 * print(myDictionary.size()); // logs 3 to the console
57259 * }
57260 * </code></div>
57261 */
57262 _main.default.TypedDict.prototype.size = function() {
57263 return Object.keys(this.data).length;
57264 };
57265
57266 /**
57267 * Returns true if the given key exists in the Dictionary,
57268 * otherwise returns false.
57269 *
57270 * @method hasKey
57271 * @param {Number|String} key that you want to look up
57272 * @return {Boolean} whether that key exists in Dictionary
57273 *
57274 * @example
57275 * <div class="norender">
57276 * <code>
57277 * function setup() {
57278 * let myDictionary = createStringDict('p5', 'js');
57279 * print(myDictionary.hasKey('p5')); // logs true to console
57280 * }
57281 * </code></div>
57282 */
57283
57284 _main.default.TypedDict.prototype.hasKey = function(key) {
57285 return this.data.hasOwnProperty(key);
57286 };
57287
57288 /**
57289 * Returns the value stored at the given key.
57290 *
57291 * @method get
57292 * @param {Number|String} the key you want to access
57293 * @return {Number|String} the value stored at that key
57294 *
57295 * @example
57296 * <div class="norender">
57297 * <code>
57298 * function setup() {
57299 * let myDictionary = createStringDict('p5', 'js');
57300 * let myValue = myDictionary.get('p5');
57301 * print(myValue === 'js'); // logs true to console
57302 * }
57303 * </code></div>
57304 */
57305
57306 _main.default.TypedDict.prototype.get = function(key) {
57307 if (this.data.hasOwnProperty(key)) {
57308 return this.data[key];
57309 } else {
57310 console.log(''.concat(key, ' does not exist in this Dictionary'));
57311 }
57312 };
57313
57314 /**
57315 * Updates the value associated with the given key in case it already exists
57316 * in the Dictionary. Otherwise a new key-value pair is added.
57317 *
57318 * @method set
57319 * @param {Number|String} key
57320 * @param {Number|String} value
57321 *
57322 * @example
57323 * <div class="norender">
57324 * <code>
57325 * function setup() {
57326 * let myDictionary = createStringDict('p5', 'js');
57327 * myDictionary.set('p5', 'JS');
57328 * myDictionary.print(); // logs "key: p5 - value: JS" to console
57329 * }
57330 * </code></div>
57331 */
57332
57333 _main.default.TypedDict.prototype.set = function(key, value) {
57334 if (this._validate(value)) {
57335 this.data[key] = value;
57336 } else {
57337 console.log('Those values dont work for this dictionary type.');
57338 }
57339 };
57340
57341 /**
57342 * private helper function to handle the user passing in objects
57343 * during construction or calls to create()
57344 */
57345
57346 _main.default.TypedDict.prototype._addObj = function(obj) {
57347 for (var key in obj) {
57348 this.set(key, obj[key]);
57349 }
57350 };
57351
57352 /**
57353 * Creates a new key-value pair in the Dictionary.
57354 *
57355 * @method create
57356 * @param {Number|String} key
57357 * @param {Number|String} value
57358 *
57359 * @example
57360 * <div class="norender">
57361 * <code>
57362 * function setup() {
57363 * let myDictionary = createStringDict('p5', 'js');
57364 * myDictionary.create('happy', 'coding');
57365 * myDictionary.print();
57366 * // above logs "key: p5 - value: js, key: happy - value: coding" to console
57367 * }
57368 * </code></div>
57369 */
57370 /**
57371 * @method create
57372 * @param {Object} obj key/value pair
57373 */
57374
57375 _main.default.TypedDict.prototype.create = function(key, value) {
57376 if (key instanceof Object && typeof value === 'undefined') {
57377 this._addObj(key);
57378 } else if (typeof key !== 'undefined') {
57379 this.set(key, value);
57380 } else {
57381 console.log(
57382 'In order to create a new Dictionary entry you must pass ' +
57383 'an object or a key, value pair'
57384 );
57385 }
57386 };
57387
57388 /**
57389 * Removes all previously stored key-value pairs from the Dictionary.
57390 *
57391 * @method clear
57392 * @example
57393 * <div class="norender">
57394 * <code>
57395 * function setup() {
57396 * let myDictionary = createStringDict('p5', 'js');
57397 * print(myDictionary.hasKey('p5')); // prints 'true'
57398 * myDictionary.clear();
57399 * print(myDictionary.hasKey('p5')); // prints 'false'
57400 * }
57401 * </code>
57402 * </div>
57403 */
57404
57405 _main.default.TypedDict.prototype.clear = function() {
57406 this.data = {};
57407 };
57408
57409 /**
57410 * Removes the key-value pair stored at the given key from the Dictionary.
57411 *
57412 * @method remove
57413 * @param {Number|String} key for the pair to remove
57414 *
57415 * @example
57416 * <div class="norender">
57417 * <code>
57418 * function setup() {
57419 * let myDictionary = createStringDict('p5', 'js');
57420 * myDictionary.create('happy', 'coding');
57421 * myDictionary.print();
57422 * // above logs "key: p5 - value: js, key: happy - value: coding" to console
57423 * myDictionary.remove('p5');
57424 * myDictionary.print();
57425 * // above logs "key: happy value: coding" to console
57426 * }
57427 * </code></div>
57428 */
57429
57430 _main.default.TypedDict.prototype.remove = function(key) {
57431 if (this.data.hasOwnProperty(key)) {
57432 delete this.data[key];
57433 } else {
57434 throw new Error(''.concat(key, ' does not exist in this Dictionary'));
57435 }
57436 };
57437
57438 /**
57439 * Logs the set of items currently stored in the Dictionary to the console.
57440 *
57441 * @method print
57442 *
57443 * @example
57444 * <div class="norender">
57445 * <code>
57446 * function setup() {
57447 * let myDictionary = createStringDict('p5', 'js');
57448 * myDictionary.create('happy', 'coding');
57449 * myDictionary.print();
57450 * // above logs "key: p5 - value: js, key: happy - value: coding" to console
57451 * }
57452 * </code>
57453 * </div>
57454 */
57455
57456 _main.default.TypedDict.prototype.print = function() {
57457 for (var item in this.data) {
57458 console.log('key:'.concat(item, ' value:').concat(this.data[item]));
57459 }
57460 };
57461
57462 /**
57463 * Converts the Dictionary into a CSV file for local download.
57464 *
57465 * @method saveTable
57466 * @example
57467 * <div>
57468 * <code>
57469 * function setup() {
57470 * createCanvas(100, 100);
57471 * background(200);
57472 * text('click here to save', 10, 10, 70, 80);
57473 * }
57474 *
57475 * function mousePressed() {
57476 * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {
57477 * createStringDict({
57478 * john: 1940,
57479 * paul: 1942,
57480 * george: 1943,
57481 * ringo: 1940
57482 * }).saveTable('beatles');
57483 * }
57484 * }
57485 * </code>
57486 * </div>
57487 */
57488
57489 _main.default.TypedDict.prototype.saveTable = function(filename) {
57490 var output = '';
57491
57492 for (var key in this.data) {
57493 output += ''.concat(key, ',').concat(this.data[key], '\n');
57494 }
57495
57496 var blob = new Blob([output], { type: 'text/csv' });
57497 _main.default.prototype.downloadFile(blob, filename || 'mycsv', 'csv');
57498 };
57499
57500 /**
57501 * Converts the Dictionary into a JSON file for local download.
57502 *
57503 * @method saveJSON
57504 * @example
57505 * <div>
57506 * <code>
57507 * function setup() {
57508 * createCanvas(100, 100);
57509 * background(200);
57510 * text('click here to save', 10, 10, 70, 80);
57511 * }
57512 *
57513 * function mousePressed() {
57514 * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {
57515 * createStringDict({
57516 * john: 1940,
57517 * paul: 1942,
57518 * george: 1943,
57519 * ringo: 1940
57520 * }).saveJSON('beatles');
57521 * }
57522 * }
57523 * </code>
57524 * </div>
57525 */
57526
57527 _main.default.TypedDict.prototype.saveJSON = function(filename, opt) {
57528 _main.default.prototype.saveJSON(this.data, filename, opt);
57529 };
57530
57531 /**
57532 * private helper function to ensure that the user passed in valid
57533 * values for the Dictionary type
57534 */
57535
57536 _main.default.TypedDict.prototype._validate = function(value) {
57537 return true;
57538 };
57539
57540 /**
57541 *
57542 * A simple Dictionary class for Strings.
57543 *
57544 * @class p5.StringDict
57545 * @extends p5.TypedDict
57546 */
57547
57548 _main.default.StringDict = function() {
57549 for (
57550 var _len = arguments.length, args = new Array(_len), _key = 0;
57551 _key < _len;
57552 _key++
57553 ) {
57554 args[_key] = arguments[_key];
57555 }
57556 _main.default.TypedDict.apply(this, args);
57557 };
57558
57559 _main.default.StringDict.prototype = Object.create(
57560 _main.default.TypedDict.prototype
57561 );
57562
57563 _main.default.StringDict.prototype._validate = function(value) {
57564 return typeof value === 'string';
57565 };
57566
57567 /**
57568 *
57569 * A simple Dictionary class for Numbers.
57570 *
57571 * @class p5.NumberDict
57572 * @constructor
57573 * @extends p5.TypedDict
57574 */
57575
57576 _main.default.NumberDict = function() {
57577 for (
57578 var _len2 = arguments.length, args = new Array(_len2), _key2 = 0;
57579 _key2 < _len2;
57580 _key2++
57581 ) {
57582 args[_key2] = arguments[_key2];
57583 }
57584 _main.default.TypedDict.apply(this, args);
57585 };
57586
57587 _main.default.NumberDict.prototype = Object.create(
57588 _main.default.TypedDict.prototype
57589 );
57590
57591 /**
57592 * private helper function to ensure that the user passed in valid
57593 * values for the Dictionary type
57594 */
57595
57596 _main.default.NumberDict.prototype._validate = function(value) {
57597 return typeof value === 'number';
57598 };
57599
57600 /**
57601 * Add the given number to the value currently stored at the given key.
57602 * The sum then replaces the value previously stored in the Dictionary.
57603 *
57604 * @method add
57605 * @param {Number} Key for the value you wish to add to
57606 * @param {Number} Number to add to the value
57607 * @example
57608 * <div class='norender'>
57609 * <code>
57610 * function setup() {
57611 * let myDictionary = createNumberDict(2, 5);
57612 * myDictionary.add(2, 2);
57613 * print(myDictionary.get(2)); // logs 7 to console.
57614 * }
57615 * </code></div>
57616 *
57617 */
57618
57619 _main.default.NumberDict.prototype.add = function(key, amount) {
57620 if (this.data.hasOwnProperty(key)) {
57621 this.data[key] += amount;
57622 } else {
57623 console.log('The key - '.concat(key, ' does not exist in this dictionary.'));
57624 }
57625 };
57626
57627 /**
57628 * Subtract the given number from the value currently stored at the given key.
57629 * The difference then replaces the value previously stored in the Dictionary.
57630 *
57631 * @method sub
57632 * @param {Number} Key for the value you wish to subtract from
57633 * @param {Number} Number to subtract from the value
57634 * @example
57635 * <div class='norender'>
57636 * <code>
57637 * function setup() {
57638 * let myDictionary = createNumberDict(2, 5);
57639 * myDictionary.sub(2, 2);
57640 * print(myDictionary.get(2)); // logs 3 to console.
57641 * }
57642 * </code></div>
57643 *
57644 */
57645
57646 _main.default.NumberDict.prototype.sub = function(key, amount) {
57647 this.add(key, -amount);
57648 };
57649
57650 /**
57651 * Multiply the given number with the value currently stored at the given key.
57652 * The product then replaces the value previously stored in the Dictionary.
57653 *
57654 * @method mult
57655 * @param {Number} Key for value you wish to multiply
57656 * @param {Number} Amount to multiply the value by
57657 * @example
57658 * <div class='norender'>
57659 * <code>
57660 * function setup() {
57661 * let myDictionary = createNumberDict(2, 4);
57662 * myDictionary.mult(2, 2);
57663 * print(myDictionary.get(2)); // logs 8 to console.
57664 * }
57665 * </code></div>
57666 *
57667 */
57668
57669 _main.default.NumberDict.prototype.mult = function(key, amount) {
57670 if (this.data.hasOwnProperty(key)) {
57671 this.data[key] *= amount;
57672 } else {
57673 console.log('The key - '.concat(key, ' does not exist in this dictionary.'));
57674 }
57675 };
57676
57677 /**
57678 * Divide the given number with the value currently stored at the given key.
57679 * The quotient then replaces the value previously stored in the Dictionary.
57680 *
57681 * @method div
57682 * @param {Number} Key for value you wish to divide
57683 * @param {Number} Amount to divide the value by
57684 * @example
57685 * <div class='norender'>
57686 * <code>
57687 * function setup() {
57688 * let myDictionary = createNumberDict(2, 8);
57689 * myDictionary.div(2, 2);
57690 * print(myDictionary.get(2)); // logs 4 to console.
57691 * }
57692 * </code></div>
57693 *
57694 */
57695
57696 _main.default.NumberDict.prototype.div = function(key, amount) {
57697 if (this.data.hasOwnProperty(key)) {
57698 this.data[key] /= amount;
57699 } else {
57700 console.log('The key - '.concat(key, ' does not exist in this dictionary.'));
57701 }
57702 };
57703
57704 /**
57705 * private helper function for finding lowest or highest value
57706 * the argument 'flip' is used to flip the comparison arrow
57707 * from 'less than' to 'greater than'
57708 */
57709
57710 _main.default.NumberDict.prototype._valueTest = function(flip) {
57711 if (Object.keys(this.data).length === 0) {
57712 throw new Error(
57713 'Unable to search for a minimum or maximum value on an empty NumberDict'
57714 );
57715 } else if (Object.keys(this.data).length === 1) {
57716 return this.data[Object.keys(this.data)[0]];
57717 } else {
57718 var result = this.data[Object.keys(this.data)[0]];
57719 for (var key in this.data) {
57720 if (this.data[key] * flip < result * flip) {
57721 result = this.data[key];
57722 }
57723 }
57724 return result;
57725 }
57726 };
57727
57728 /**
57729 * Return the lowest number currently stored in the Dictionary.
57730 *
57731 * @method minValue
57732 * @return {Number}
57733 * @example
57734 * <div class='norender'>
57735 * <code>
57736 * function setup() {
57737 * let myDictionary = createNumberDict({ 2: -10, 4: 0.65, 1.2: 3 });
57738 * let lowestValue = myDictionary.minValue(); // value is -10
57739 * print(lowestValue);
57740 * }
57741 * </code></div>
57742 */
57743
57744 _main.default.NumberDict.prototype.minValue = function() {
57745 return this._valueTest(1);
57746 };
57747
57748 /**
57749 * Return the highest number currently stored in the Dictionary.
57750 *
57751 * @method maxValue
57752 * @return {Number}
57753 * @example
57754 * <div class='norender'>
57755 * <code>
57756 * function setup() {
57757 * let myDictionary = createNumberDict({ 2: -10, 4: 0.65, 1.2: 3 });
57758 * let highestValue = myDictionary.maxValue(); // value is 3
57759 * print(highestValue);
57760 * }
57761 * </code></div>
57762 */
57763
57764 _main.default.NumberDict.prototype.maxValue = function() {
57765 return this._valueTest(-1);
57766 };
57767
57768 /**
57769 * private helper function for finding lowest or highest key
57770 * the argument 'flip' is used to flip the comparison arrow
57771 * from 'less than' to 'greater than'
57772 */
57773
57774 _main.default.NumberDict.prototype._keyTest = function(flip) {
57775 if (Object.keys(this.data).length === 0) {
57776 throw new Error('Unable to use minValue on an empty NumberDict');
57777 } else if (Object.keys(this.data).length === 1) {
57778 return Object.keys(this.data)[0];
57779 } else {
57780 var result = Object.keys(this.data)[0];
57781 for (var i = 1; i < Object.keys(this.data).length; i++) {
57782 if (Object.keys(this.data)[i] * flip < result * flip) {
57783 result = Object.keys(this.data)[i];
57784 }
57785 }
57786 return result;
57787 }
57788 };
57789
57790 /**
57791 * Return the lowest key currently used in the Dictionary.
57792 *
57793 * @method minKey
57794 * @return {Number}
57795 * @example
57796 * <div class='norender'>
57797 * <code>
57798 * function setup() {
57799 * let myDictionary = createNumberDict({ 2: 4, 4: 6, 1.2: 3 });
57800 * let lowestKey = myDictionary.minKey(); // value is 1.2
57801 * print(lowestKey);
57802 * }
57803 * </code></div>
57804 */
57805
57806 _main.default.NumberDict.prototype.minKey = function() {
57807 return this._keyTest(1);
57808 };
57809
57810 /**
57811 * Return the highest key currently used in the Dictionary.
57812 *
57813 * @method maxKey
57814 * @return {Number}
57815 * @example
57816 * <div class='norender'>
57817 * <code>
57818 * function setup() {
57819 * let myDictionary = createNumberDict({ 2: 4, 4: 6, 1.2: 3 });
57820 * let highestKey = myDictionary.maxKey(); // value is 4
57821 * print(highestKey);
57822 * }
57823 * </code></div>
57824 */
57825
57826 _main.default.NumberDict.prototype.maxKey = function() {
57827 return this._keyTest(-1);
57828 };
57829 var _default = _main.default.TypedDict;
57830 exports.default = _default;
57831 },
57832 { '../core/main': 54 }
57833 ],
57834 70: [
57835 function(_dereq_, module, exports) {
57836 'use strict';
57837 Object.defineProperty(exports, '__esModule', { value: true });
57838 exports.default = void 0;
57839
57840 var _main = _interopRequireDefault(_dereq_('../core/main'));
57841 function _interopRequireDefault(obj) {
57842 return obj && obj.__esModule ? obj : { default: obj };
57843 }
57844 function _typeof(obj) {
57845 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
57846 _typeof = function _typeof(obj) {
57847 return typeof obj;
57848 };
57849 } else {
57850 _typeof = function _typeof(obj) {
57851 return obj &&
57852 typeof Symbol === 'function' &&
57853 obj.constructor === Symbol &&
57854 obj !== Symbol.prototype
57855 ? 'symbol'
57856 : typeof obj;
57857 };
57858 }
57859 return _typeof(obj);
57860 }
57861
57862 /**
57863 * Searches the page for the first element that matches the given CSS selector string (can be an
57864 * ID, class, tag name or a combination) and returns it as a <a href="#/p5.Element">p5.Element</a>.
57865 * The DOM node itself can be accessed with .elt.
57866 * Returns null if none found. You can also specify a container to search within.
57867 *
57868 * @method select
57869 * @param {String} selectors CSS selector string of element to search for
57870 * @param {String|p5.Element|HTMLElement} [container] CSS selector string, <a href="#/p5.Element">p5.Element</a>, or
57871 * HTML element to search within
57872 * @return {p5.Element|null} <a href="#/p5.Element">p5.Element</a> containing node found
57873 * @example
57874 * <div><code>
57875 * function setup() {
57876 * createCanvas(50, 50);
57877 * background(30);
57878 * // move canvas down and right
57879 * select('canvas').position(10, 30);
57880 * }
57881 * </code></div>
57882 *
57883 * <div class="norender"><code>
57884 * // select using ID
57885 * let a = select('#container');
57886 * let b = select('#beep', '#container');
57887 * let c;
57888 * if (a) {
57889 * // select using class
57890 * c = select('.boop', a);
57891 * }
57892 * // select using CSS selector string
57893 * let d = select('#container #bleep');
57894 * let e = select('#container p');
57895 * [a, b, c, d, e]; // unused
57896 * </code></div>
57897 */
57898 _main.default.prototype.select = function(e, p) {
57899 _main.default._validateParameters('select', arguments);
57900 var container = this._getContainer(p);
57901 var res = container.querySelector(e);
57902 if (res) {
57903 return this._wrapElement(res);
57904 } else {
57905 return null;
57906 }
57907 };
57908
57909 /**
57910 * Searches the page for elements that match the given CSS selector string (can be an ID a class,
57911 * tag name or a combination) and returns them as <a href="#/p5.Element">p5.Element</a>s in
57912 * an array.
57913 * The DOM node itself can be accessed with .elt.
57914 * Returns an empty array if none found.
57915 * You can also specify a container to search within.
57916 *
57917 * @method selectAll
57918 * @param {String} selectors CSS selector string of elements to search for
57919 * @param {String|p5.Element|HTMLElement} [container] CSS selector string, <a href="#/p5.Element">p5.Element</a>
57920 * , or HTML element to search within
57921 * @return {p5.Element[]} Array of <a href="#/p5.Element">p5.Element</a>s containing nodes found
57922 * @example
57923 * <div class='norender'><code>
57924 * function setup() {
57925 * createButton('btn');
57926 * createButton('2nd btn');
57927 * createButton('3rd btn');
57928 * let buttons = selectAll('button');
57929 *
57930 * for (let i = 0; i < buttons.length; i++) {
57931 * buttons[i].size(100, 100);
57932 * }
57933 * }
57934 * </code></div>
57935 * <div class='norender'><code>
57936 * // these are all valid calls to selectAll()
57937 * let a = selectAll('.beep');
57938 * a = selectAll('div');
57939 * a = selectAll('button', '#container');
57940 *
57941 * let b = createDiv();
57942 * b.id('container');
57943 * let c = select('#container');
57944 * a = selectAll('p', c);
57945 * a = selectAll('#container p');
57946 *
57947 * let d = document.getElementById('container');
57948 * a = selectAll('.boop', d);
57949 * a = selectAll('#container .boop');
57950 * console.log(a);
57951 * </code></div>
57952 */
57953 _main.default.prototype.selectAll = function(e, p) {
57954 _main.default._validateParameters('selectAll', arguments);
57955 var arr = [];
57956 var container = this._getContainer(p);
57957 var res = container.querySelectorAll(e);
57958 if (res) {
57959 for (var j = 0; j < res.length; j++) {
57960 var obj = this._wrapElement(res[j]);
57961 arr.push(obj);
57962 }
57963 }
57964 return arr;
57965 };
57966
57967 /**
57968 * Helper function for select and selectAll
57969 */
57970 _main.default.prototype._getContainer = function(p) {
57971 var container = document;
57972 if (typeof p === 'string') {
57973 container = document.querySelector(p) || document;
57974 } else if (p instanceof _main.default.Element) {
57975 container = p.elt;
57976 } else if (p instanceof HTMLElement) {
57977 container = p;
57978 }
57979 return container;
57980 };
57981
57982 /**
57983 * Helper function for getElement and getElements.
57984 */
57985 _main.default.prototype._wrapElement = function(elt) {
57986 var children = Array.prototype.slice.call(elt.children);
57987 if (elt.tagName === 'INPUT' && elt.type === 'checkbox') {
57988 var converted = new _main.default.Element(elt, this);
57989 converted.checked = function() {
57990 if (arguments.length === 0) {
57991 return this.elt.checked;
57992 } else if (arguments[0]) {
57993 this.elt.checked = true;
57994 } else {
57995 this.elt.checked = false;
57996 }
57997 return this;
57998 };
57999 return converted;
58000 } else if (elt.tagName === 'VIDEO' || elt.tagName === 'AUDIO') {
58001 return new _main.default.MediaElement(elt, this);
58002 } else if (elt.tagName === 'SELECT') {
58003 return this.createSelect(new _main.default.Element(elt, this));
58004 } else if (
58005 children.length > 0 &&
58006 children.every(function(c) {
58007 return c.tagName === 'INPUT' || c.tagName === 'LABEL';
58008 })
58009 ) {
58010 return this.createRadio(new _main.default.Element(elt, this));
58011 } else {
58012 return new _main.default.Element(elt, this);
58013 }
58014 };
58015
58016 /**
58017 * Removes all elements created by p5, except any canvas / graphics
58018 * elements created by <a href="#/p5/createCanvas">createCanvas</a> or <a href="#/p5/createGraphics">createGraphics</a>.
58019 * Event handlers are removed, and element is removed from the DOM.
58020 * @method removeElements
58021 * @example
58022 * <div class='norender'><code>
58023 * function setup() {
58024 * createCanvas(100, 100);
58025 * createDiv('this is some text');
58026 * createP('this is a paragraph');
58027 * }
58028 * function mousePressed() {
58029 * removeElements(); // this will remove the div and p, not canvas
58030 * }
58031 * </code></div>
58032 */
58033 _main.default.prototype.removeElements = function(e) {
58034 _main.default._validateParameters('removeElements', arguments);
58035 // el.remove splices from this._elements, so don't mix iteration with it
58036 var isNotCanvasElement = function isNotCanvasElement(el) {
58037 return !(el.elt instanceof HTMLCanvasElement);
58038 };
58039 var removeableElements = this._elements.filter(isNotCanvasElement);
58040 removeableElements.map(function(el) {
58041 return el.remove();
58042 });
58043 };
58044
58045 /**
58046 * The .<a href="#/p5.Element/changed">changed()</a> function is called when the value of an
58047 * element changes.
58048 * This can be used to attach an element specific event listener.
58049 *
58050 * @method changed
58051 * @param {Function|Boolean} fxn function to be fired when the value of
58052 * an element changes.
58053 * if `false` is passed instead, the previously
58054 * firing function will no longer fire.
58055 * @chainable
58056 * @example
58057 * <div><code>
58058 * let sel;
58059 *
58060 * function setup() {
58061 * textAlign(CENTER);
58062 * background(200);
58063 * sel = createSelect();
58064 * sel.position(10, 10);
58065 * sel.option('pear');
58066 * sel.option('kiwi');
58067 * sel.option('grape');
58068 * sel.changed(mySelectEvent);
58069 * }
58070 *
58071 * function mySelectEvent() {
58072 * let item = sel.value();
58073 * background(200);
58074 * text("it's a " + item + '!', 50, 50);
58075 * }
58076 * </code></div>
58077 *
58078 * <div><code>
58079 * let checkbox;
58080 * let cnv;
58081 *
58082 * function setup() {
58083 * checkbox = createCheckbox(' fill');
58084 * checkbox.changed(changeFill);
58085 * cnv = createCanvas(100, 100);
58086 * cnv.position(0, 30);
58087 * noFill();
58088 * }
58089 *
58090 * function draw() {
58091 * background(200);
58092 * ellipse(50, 50, 50, 50);
58093 * }
58094 *
58095 * function changeFill() {
58096 * if (checkbox.checked()) {
58097 * fill(0);
58098 * } else {
58099 * noFill();
58100 * }
58101 * }
58102 * </code></div>
58103 *
58104 * @alt
58105 * dropdown: pear, kiwi, grape. When selected text "its a" + selection shown.
58106 */
58107 _main.default.Element.prototype.changed = function(fxn) {
58108 _main.default.Element._adjustListener('change', fxn, this);
58109 return this;
58110 };
58111
58112 /**
58113 * The .<a href="#/p5.Element/input">input()</a> function is called when any user input is
58114 * detected with an element. The input event is often used
58115 * to detect keystrokes in a input element, or changes on a
58116 * slider element. This can be used to attach an element specific
58117 * event listener.
58118 *
58119 * @method input
58120 * @param {Function|Boolean} fxn function to be fired when any user input is
58121 * detected within the element.
58122 * if `false` is passed instead, the previously
58123 * firing function will no longer fire.
58124 * @chainable
58125 * @example
58126 * <div class='norender'><code>
58127 * // Open your console to see the output
58128 * function setup() {
58129 * let inp = createInput('');
58130 * inp.input(myInputEvent);
58131 * }
58132 *
58133 * function myInputEvent() {
58134 * console.log('you are typing: ', this.value());
58135 * }
58136 * </code></div>
58137 *
58138 * @alt
58139 * no display.
58140 */
58141 _main.default.Element.prototype.input = function(fxn) {
58142 _main.default.Element._adjustListener('input', fxn, this);
58143 return this;
58144 };
58145
58146 /**
58147 * Helpers for create methods.
58148 */
58149 function addElement(elt, pInst, media) {
58150 var node = pInst._userNode ? pInst._userNode : document.body;
58151 node.appendChild(elt);
58152 var c = media
58153 ? new _main.default.MediaElement(elt, pInst)
58154 : new _main.default.Element(elt, pInst);
58155 pInst._elements.push(c);
58156 return c;
58157 }
58158
58159 /**
58160 * Creates a &lt;div&gt;&lt;/div&gt; element in the DOM with given inner HTML.
58161 *
58162 * @method createDiv
58163 * @param {String} [html] inner HTML for element created
58164 * @return {p5.Element} pointer to <a href="#/p5.Element">p5.Element</a> holding created node
58165 * @example
58166 * <div class='norender'><code>
58167 * createDiv('this is some text');
58168 * </code></div>
58169 */
58170 _main.default.prototype.createDiv = function() {
58171 var html =
58172 arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
58173 var elt = document.createElement('div');
58174 elt.innerHTML = html;
58175 return addElement(elt, this);
58176 };
58177
58178 /**
58179 * Creates a &lt;p&gt;&lt;/p&gt; element in the DOM with given inner HTML. Used
58180 * for paragraph length text.
58181 *
58182 * @method createP
58183 * @param {String} [html] inner HTML for element created
58184 * @return {p5.Element} pointer to <a href="#/p5.Element">p5.Element</a> holding created node
58185 * @example
58186 * <div class='norender'><code>
58187 * createP('this is some text');
58188 * </code></div>
58189 */
58190 _main.default.prototype.createP = function() {
58191 var html =
58192 arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
58193 var elt = document.createElement('p');
58194 elt.innerHTML = html;
58195 return addElement(elt, this);
58196 };
58197
58198 /**
58199 * Creates a &lt;span&gt;&lt;/span&gt; element in the DOM with given inner HTML.
58200 *
58201 * @method createSpan
58202 * @param {String} [html] inner HTML for element created
58203 * @return {p5.Element} pointer to <a href="#/p5.Element">p5.Element</a> holding created node
58204 * @example
58205 * <div class='norender'><code>
58206 * createSpan('this is some text');
58207 * </code></div>
58208 */
58209 _main.default.prototype.createSpan = function() {
58210 var html =
58211 arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
58212 var elt = document.createElement('span');
58213 elt.innerHTML = html;
58214 return addElement(elt, this);
58215 };
58216
58217 /**
58218 * Creates an &lt;img&gt; element in the DOM with given src and
58219 * alternate text.
58220 *
58221 * @method createImg
58222 * @param {String} src src path or url for image
58223 * @param {String} alt <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Img#Attributes">alternate text</a> to be used if image does not load. You can use also an empty string (`""`) if that an image is not intended to be viewed.
58224 * @return {p5.Element} pointer to <a href="#/p5.Element">p5.Element</a> holding created node
58225 * @example
58226 * <div class='norender'><code>
58227 * createImg(
58228 * 'https://p5js.org/assets/img/asterisk-01.png',
58229 * 'the p5 magenta asterisk'
58230 * );
58231 * </code></div>
58232 */
58233 /**
58234 * @method createImg
58235 * @param {String} src
58236 * @param {String} alt
58237 * @param {String} crossOrigin <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes">crossOrigin property</a> of the `img` element; use either 'anonymous' or 'use-credentials' to retrieve the image with cross-origin access (for later use with `canvas`. if an empty string(`""`) is passed, CORS is not used
58238 * @param {Function} [successCallback] callback to be called once image data is loaded with the <a href="#/p5.Element">p5.Element</a> as argument
58239 * @return {p5.Element} pointer to <a href="#/p5.Element">p5.Element</a> holding created node
58240 */
58241 _main.default.prototype.createImg = function() {
58242 _main.default._validateParameters('createImg', arguments);
58243 var elt = document.createElement('img');
58244 var args = arguments;
58245 var self;
58246 if (args.length > 1 && typeof args[1] === 'string') {
58247 elt.alt = args[1];
58248 }
58249 if (args.length > 2 && typeof args[2] === 'string') {
58250 elt.crossOrigin = args[2];
58251 }
58252 elt.src = args[0];
58253 self = addElement(elt, this);
58254 elt.addEventListener('load', function() {
58255 self.width = elt.offsetWidth || elt.width;
58256 self.height = elt.offsetHeight || elt.height;
58257 var last = args[args.length - 1];
58258 if (typeof last === 'function') last(self);
58259 });
58260 return self;
58261 };
58262
58263 /**
58264 * Creates an &lt;a&gt;&lt;/a&gt; element in the DOM for including a hyperlink.
58265 *
58266 * @method createA
58267 * @param {String} href url of page to link to
58268 * @param {String} html inner html of link element to display
58269 * @param {String} [target] target where new link should open,
58270 * could be _blank, _self, _parent, _top.
58271 * @return {p5.Element} pointer to <a href="#/p5.Element">p5.Element</a> holding created node
58272 * @example
58273 * <div class='norender'><code>
58274 * createA('http://p5js.org/', 'this is a link');
58275 * </code></div>
58276 */
58277 _main.default.prototype.createA = function(href, html, target) {
58278 _main.default._validateParameters('createA', arguments);
58279 var elt = document.createElement('a');
58280 elt.href = href;
58281 elt.innerHTML = html;
58282 if (target) elt.target = target;
58283 return addElement(elt, this);
58284 };
58285
58286 /** INPUT **/
58287
58288 /**
58289 * Creates a slider &lt;input&gt;&lt;/input&gt; element in the DOM.
58290 * Use .size() to set the display length of the slider.
58291 *
58292 * @method createSlider
58293 * @param {Number} min minimum value of the slider
58294 * @param {Number} max maximum value of the slider
58295 * @param {Number} [value] default value of the slider
58296 * @param {Number} [step] 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)
58297 * @return {p5.Element} pointer to <a href="#/p5.Element">p5.Element</a> holding created node
58298 * @example
58299 * <div><code>
58300 * let slider;
58301 * function setup() {
58302 * slider = createSlider(0, 255, 100);
58303 * slider.position(10, 10);
58304 * slider.style('width', '80px');
58305 * }
58306 *
58307 * function draw() {
58308 * let val = slider.value();
58309 * background(val);
58310 * }
58311 * </code></div>
58312 *
58313 * <div><code>
58314 * let slider;
58315 * function setup() {
58316 * colorMode(HSB);
58317 * slider = createSlider(0, 360, 60, 40);
58318 * slider.position(10, 10);
58319 * slider.style('width', '80px');
58320 * }
58321 *
58322 * function draw() {
58323 * let val = slider.value();
58324 * background(val, 100, 100, 1);
58325 * }
58326 * </code></div>
58327 */
58328 _main.default.prototype.createSlider = function(min, max, value, step) {
58329 _main.default._validateParameters('createSlider', arguments);
58330 var elt = document.createElement('input');
58331 elt.type = 'range';
58332 elt.min = min;
58333 elt.max = max;
58334 if (step === 0) {
58335 elt.step = 0.000000000000000001; // smallest valid step
58336 } else if (step) {
58337 elt.step = step;
58338 }
58339 if (typeof value === 'number') elt.value = value;
58340 return addElement(elt, this);
58341 };
58342
58343 /**
58344 * Creates a &lt;button&gt;&lt;/button&gt; element in the DOM.
58345 * Use .size() to set the display size of the button.
58346 * Use .mousePressed() to specify behavior on press.
58347 *
58348 * @method createButton
58349 * @param {String} label label displayed on the button
58350 * @param {String} [value] value of the button
58351 * @return {p5.Element} pointer to <a href="#/p5.Element">p5.Element</a> holding created node
58352 * @example
58353 * <div class='norender'><code>
58354 * let button;
58355 * function setup() {
58356 * createCanvas(100, 100);
58357 * background(0);
58358 * button = createButton('click me');
58359 * button.position(19, 19);
58360 * button.mousePressed(changeBG);
58361 * }
58362 *
58363 * function changeBG() {
58364 * let val = random(255);
58365 * background(val);
58366 * }
58367 * </code></div>
58368 */
58369 _main.default.prototype.createButton = function(label, value) {
58370 _main.default._validateParameters('createButton', arguments);
58371 var elt = document.createElement('button');
58372 elt.innerHTML = label;
58373 if (value) elt.value = value;
58374 return addElement(elt, this);
58375 };
58376
58377 /**
58378 * Creates a checkbox &lt;input&gt;&lt;/input&gt; element in the DOM.
58379 * Calling .checked() on a checkbox returns if it is checked or not
58380 *
58381 * @method createCheckbox
58382 * @param {String} [label] label displayed after checkbox
58383 * @param {boolean} [value] value of the checkbox; checked is true, unchecked is false
58384 * @return {p5.Element} pointer to <a href="#/p5.Element">p5.Element</a> holding created node
58385 * @example
58386 * <div class='norender'><code>
58387 * let checkbox;
58388 *
58389 * function setup() {
58390 * checkbox = createCheckbox('label', false);
58391 * checkbox.changed(myCheckedEvent);
58392 * }
58393 *
58394 * function myCheckedEvent() {
58395 * if (this.checked()) {
58396 * console.log('Checking!');
58397 * } else {
58398 * console.log('Unchecking!');
58399 * }
58400 * }
58401 * </code></div>
58402 */
58403 _main.default.prototype.createCheckbox = function() {
58404 _main.default._validateParameters('createCheckbox', arguments);
58405 var elt = document.createElement('div');
58406 var checkbox = document.createElement('input');
58407 checkbox.type = 'checkbox';
58408 elt.appendChild(checkbox);
58409 //checkbox must be wrapped in p5.Element before label so that label appears after
58410 var self = addElement(elt, this);
58411 self.checked = function() {
58412 var cb = self.elt.getElementsByTagName('input')[0];
58413 if (cb) {
58414 if (arguments.length === 0) {
58415 return cb.checked;
58416 } else if (arguments[0]) {
58417 cb.checked = true;
58418 } else {
58419 cb.checked = false;
58420 }
58421 }
58422 return self;
58423 };
58424 this.value = function(val) {
58425 self.value = val;
58426 return this;
58427 };
58428 if (arguments[0]) {
58429 var ran = Math.random()
58430 .toString(36)
58431 .slice(2);
58432 var label = document.createElement('label');
58433 checkbox.setAttribute('id', ran);
58434 label.htmlFor = ran;
58435 self.value(arguments[0]);
58436 label.appendChild(document.createTextNode(arguments[0]));
58437 elt.appendChild(label);
58438 }
58439 if (arguments[1]) {
58440 checkbox.checked = true;
58441 }
58442 return self;
58443 };
58444
58445 /**
58446 * Creates a dropdown menu &lt;select&gt;&lt;/select&gt; element in the DOM.
58447 * It also helps to assign select-box methods to <a href="#/p5.Element">p5.Element</a> when selecting existing select box.
58448 * - `.option(name, [value])` can be used to set options for the select after it is created.
58449 * - `.value()` will return the currently selected option.
58450 * - `.selected()` will return current dropdown element which is an instance of <a href="#/p5.Element">p5.Element</a>
58451 * - `.selected(value)` can be used to make given option selected by default when the page first loads.
58452 * - `.disable()` marks whole of dropdown element as disabled.
58453 * - `.disable(value)` marks given option as disabled
58454 *
58455 * @method createSelect
58456 * @param {boolean} [multiple] true if dropdown should support multiple selections
58457 * @return {p5.Element}
58458 * @example
58459 * <div><code>
58460 * let sel;
58461 *
58462 * function setup() {
58463 * textAlign(CENTER);
58464 * background(200);
58465 * sel = createSelect();
58466 * sel.position(10, 10);
58467 * sel.option('pear');
58468 * sel.option('kiwi');
58469 * sel.option('grape');
58470 * sel.selected('kiwi');
58471 * sel.changed(mySelectEvent);
58472 * }
58473 *
58474 * function mySelectEvent() {
58475 * let item = sel.value();
58476 * background(200);
58477 * text('It is a ' + item + '!', 50, 50);
58478 * }
58479 * </code></div>
58480 *
58481 * <div><code>
58482 * let sel;
58483 *
58484 * function setup() {
58485 * textAlign(CENTER);
58486 * background(200);
58487 * sel = createSelect();
58488 * sel.position(10, 10);
58489 * sel.option('oil');
58490 * sel.option('milk');
58491 * sel.option('bread');
58492 * sel.disable('milk');
58493 * }
58494 * </code></div>
58495 */
58496 /**
58497 * @method createSelect
58498 * @param {Object} existing DOM select element
58499 * @return {p5.Element}
58500 */
58501
58502 _main.default.prototype.createSelect = function() {
58503 _main.default._validateParameters('createSelect', arguments);
58504 var self;
58505 var arg = arguments[0];
58506 if (
58507 arg instanceof _main.default.Element &&
58508 arg.elt instanceof HTMLSelectElement
58509 ) {
58510 // If given argument is p5.Element of select type
58511 self = arg;
58512 this.elt = arg.elt;
58513 } else if (arg instanceof HTMLSelectElement) {
58514 self = addElement(arg, this);
58515 this.elt = arg;
58516 } else {
58517 var elt = document.createElement('select');
58518 if (arg && typeof arg === 'boolean') {
58519 elt.setAttribute('multiple', 'true');
58520 }
58521 self = addElement(elt, this);
58522 this.elt = elt;
58523 }
58524 self.option = function(name, value) {
58525 var index;
58526
58527 // if no name is passed, return
58528 if (name === undefined) {
58529 return;
58530 }
58531 //see if there is already an option with this name
58532 for (var i = 0; i < this.elt.length; i += 1) {
58533 if (this.elt[i].innerHTML === name) {
58534 index = i;
58535 break;
58536 }
58537 }
58538 //if there is an option with this name we will modify it
58539 if (index !== undefined) {
58540 //if the user passed in false then delete that option
58541 if (value === false) {
58542 this.elt.remove(index);
58543 } else {
58544 // Update the option at index with the value
58545 this.elt[index].value = value;
58546 }
58547 } else {
58548 //if it doesn't exist create it
58549 var opt = document.createElement('option');
58550 opt.innerHTML = name;
58551 opt.value = value === undefined ? name : value;
58552 this.elt.appendChild(opt);
58553 this._pInst._elements.push(opt);
58554 }
58555 };
58556
58557 self.selected = function(value) {
58558 // Update selected status of option
58559 if (value !== undefined) {
58560 for (var i = 0; i < this.elt.length; i += 1) {
58561 if (this.elt[i].value.toString() === value.toString()) {
58562 this.elt.selectedIndex = i;
58563 }
58564 }
58565 return this;
58566 } else {
58567 if (this.elt.getAttribute('multiple')) {
58568 var arr = [];
58569 var _iteratorNormalCompletion = true;
58570 var _didIteratorError = false;
58571 var _iteratorError = undefined;
58572 try {
58573 for (
58574 var _iterator = this.elt.selectedOptions[Symbol.iterator](), _step;
58575 !(_iteratorNormalCompletion = (_step = _iterator.next()).done);
58576 _iteratorNormalCompletion = true
58577 ) {
58578 var selectedOption = _step.value;
58579 arr.push(selectedOption.value);
58580 }
58581 } catch (err) {
58582 _didIteratorError = true;
58583 _iteratorError = err;
58584 } finally {
58585 try {
58586 if (!_iteratorNormalCompletion && _iterator.return != null) {
58587 _iterator.return();
58588 }
58589 } finally {
58590 if (_didIteratorError) {
58591 throw _iteratorError;
58592 }
58593 }
58594 }
58595 return arr;
58596 } else {
58597 return this.elt.value;
58598 }
58599 }
58600 };
58601
58602 self.disable = function(value) {
58603 if (typeof value === 'string') {
58604 for (var i = 0; i < this.elt.length; i++) {
58605 if (this.elt[i].value.toString() === value) {
58606 this.elt[i].disabled = true;
58607 this.elt[i].selected = false;
58608 }
58609 }
58610 } else {
58611 this.elt.disabled = true;
58612 }
58613 return this;
58614 };
58615
58616 return self;
58617 };
58618
58619 /**
58620 * Creates a radio button element in the DOM.It also helps existing radio buttons
58621 * assign methods of <a href="#/p5.Element/">p5.Element</a>.
58622 * - `.option(value, [label])` can be used to create a new option for the
58623 * element. If an option with a value already exists, it will be returned.
58624 * Optionally, a label can be provided as second argument for the option.
58625 * - `.remove(value)` can be used to remove an option for the element.
58626 * - `.value()` method will return the currently selected value.
58627 * - `.selected()` method will return the currently selected input element.
58628 * - `.selected(value)` method will select the option and return it.
58629 * - `.disable(Boolean)` method will enable/disable the whole radio button element.
58630 *
58631 * @method createRadio
58632 * @param {Object} containerElement An container HTML Element either a div
58633 * or span inside which all existing radio inputs will be considered as options.
58634 * @param {string} [name] A name parameter for each Input Element.
58635 * @return {p5.Element} pointer to <a href="#/p5.Element">p5.Element</a> holding created node
58636 * @example
58637 * <div><code>
58638 * let radio;
58639 *
58640 * function setup() {
58641 * radio = createRadio();
58642 * radio.option('black');
58643 * radio.option('white');
58644 * radio.option('gray');
58645 * radio.style('width', '60px');
58646 * textAlign(CENTER);
58647 * fill(255, 0, 0);
58648 * }
58649 *
58650 * function draw() {
58651 * let val = radio.value();
58652 * background(val);
58653 * text(val, width / 2, height / 2);
58654 * }
58655 * </code></div>
58656 * <div><code>
58657 * let radio;
58658 *
58659 * function setup() {
58660 * radio = createRadio();
58661 * radio.option('apple', 1);
58662 * radio.option('bread', 2);
58663 * radio.option('juice', 3);
58664 * radio.style('width', '60px');
58665 * textAlign(CENTER);
58666 * }
58667 *
58668 * function draw() {
58669 * background(200);
58670 * let val = radio.value();
58671 * if (val) {
58672 * text('item cost is $' + val, width / 2, height / 2);
58673 * }
58674 * }
58675 * </code></div>
58676 */
58677 /**
58678 * @method createRadio
58679 * @param {String} name
58680 * @return {p5.Element} pointer to <a href="#/p5.Element">p5.Element</a> holding created node
58681 */
58682 /**
58683 * @method createRadio
58684 * @return {p5.Element} pointer to <a href="#/p5.Element">p5.Element</a> holding created node
58685 */
58686 _main.default.prototype.createRadio = function() {
58687 // Creates a div, adds each option as an individual input inside it.
58688 // If already given with a containerEl, will search for all input[radio]
58689 // it, create a p5.Element out of it, add options to it and return the p5.Element.
58690
58691 var radioElement;
58692 var name;
58693 var arg0 = arguments[0];
58694 // If existing radio Element is provided as argument 0
58695 if (arg0 instanceof HTMLDivElement || arg0 instanceof HTMLSpanElement) {
58696 radioElement = arg0;
58697 if (typeof arguments[1] === 'string') name = arguments[1];
58698 } else {
58699 if (typeof arg0 === 'string') name = arg0;
58700 radioElement = document.createElement('div');
58701 }
58702 this.elt = radioElement;
58703 var self = addElement(radioElement, this);
58704 self._name = name || 'radioOption';
58705
58706 // setup member functions
58707 var isRadioInput = function isRadioInput(el) {
58708 return el instanceof HTMLInputElement && el.type === 'radio';
58709 };
58710 var isNextLabel = function isNextLabel(el) {
58711 return el.nextElementSibling instanceof HTMLLabelElement;
58712 };
58713
58714 self._getOptionsArray = function() {
58715 return Array.from(this.elt.children).filter(isRadioInput);
58716 };
58717
58718 self.option = function(value, label) {
58719 // return an option with this value, create if not exists.
58720 var optionEl;
58721 var _iteratorNormalCompletion2 = true;
58722 var _didIteratorError2 = false;
58723 var _iteratorError2 = undefined;
58724 try {
58725 for (
58726 var _iterator2 = self._getOptionsArray()[Symbol.iterator](), _step2;
58727 !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done);
58728 _iteratorNormalCompletion2 = true
58729 ) {
58730 var option = _step2.value;
58731 if (option.value === value) {
58732 optionEl = option;
58733 break;
58734 }
58735 }
58736
58737 // Create a new option, add it to radioElement and return it.
58738 } catch (err) {
58739 _didIteratorError2 = true;
58740 _iteratorError2 = err;
58741 } finally {
58742 try {
58743 if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
58744 _iterator2.return();
58745 }
58746 } finally {
58747 if (_didIteratorError2) {
58748 throw _iteratorError2;
58749 }
58750 }
58751 }
58752 if (optionEl === undefined) {
58753 optionEl = document.createElement('input');
58754 optionEl.setAttribute('type', 'radio');
58755 optionEl.setAttribute('value', value);
58756 this.elt.appendChild(optionEl);
58757 }
58758
58759 // Check if label element exists, else create it
58760 var labelElement;
58761 if (!isNextLabel(optionEl)) {
58762 labelElement = document.createElement('label');
58763 optionEl.insertAdjacentElement('afterend', labelElement);
58764 } else {
58765 labelElement = optionEl.nextElementSibling;
58766 }
58767
58768 labelElement.innerHTML = label === undefined ? value : label;
58769 optionEl.setAttribute('name', self._name);
58770 return optionEl;
58771 };
58772
58773 self.remove = function(value) {
58774 var _iteratorNormalCompletion3 = true;
58775 var _didIteratorError3 = false;
58776 var _iteratorError3 = undefined;
58777 try {
58778 for (
58779 var _iterator3 = self._getOptionsArray()[Symbol.iterator](), _step3;
58780 !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done);
58781 _iteratorNormalCompletion3 = true
58782 ) {
58783 var optionEl = _step3.value;
58784 if (optionEl.value === value) {
58785 if (isNextLabel(optionEl)) optionEl.nextElementSibling.remove();
58786 optionEl.remove();
58787 return;
58788 }
58789 }
58790 } catch (err) {
58791 _didIteratorError3 = true;
58792 _iteratorError3 = err;
58793 } finally {
58794 try {
58795 if (!_iteratorNormalCompletion3 && _iterator3.return != null) {
58796 _iterator3.return();
58797 }
58798 } finally {
58799 if (_didIteratorError3) {
58800 throw _iteratorError3;
58801 }
58802 }
58803 }
58804 };
58805
58806 self.value = function() {
58807 var result = '';
58808 var _iteratorNormalCompletion4 = true;
58809 var _didIteratorError4 = false;
58810 var _iteratorError4 = undefined;
58811 try {
58812 for (
58813 var _iterator4 = self._getOptionsArray()[Symbol.iterator](), _step4;
58814 !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done);
58815 _iteratorNormalCompletion4 = true
58816 ) {
58817 var option = _step4.value;
58818 if (option.checked) {
58819 result = option.value;
58820 break;
58821 }
58822 }
58823 } catch (err) {
58824 _didIteratorError4 = true;
58825 _iteratorError4 = err;
58826 } finally {
58827 try {
58828 if (!_iteratorNormalCompletion4 && _iterator4.return != null) {
58829 _iterator4.return();
58830 }
58831 } finally {
58832 if (_didIteratorError4) {
58833 throw _iteratorError4;
58834 }
58835 }
58836 }
58837 return result;
58838 };
58839
58840 self.selected = function(value) {
58841 var result = null;
58842 if (value === undefined) {
58843 var _iteratorNormalCompletion5 = true;
58844 var _didIteratorError5 = false;
58845 var _iteratorError5 = undefined;
58846 try {
58847 for (
58848 var _iterator5 = self._getOptionsArray()[Symbol.iterator](), _step5;
58849 !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done);
58850 _iteratorNormalCompletion5 = true
58851 ) {
58852 var option = _step5.value;
58853 if (option.checked) {
58854 result = option;
58855 break;
58856 }
58857 }
58858 } catch (err) {
58859 _didIteratorError5 = true;
58860 _iteratorError5 = err;
58861 } finally {
58862 try {
58863 if (!_iteratorNormalCompletion5 && _iterator5.return != null) {
58864 _iterator5.return();
58865 }
58866 } finally {
58867 if (_didIteratorError5) {
58868 throw _iteratorError5;
58869 }
58870 }
58871 }
58872 } else {
58873 var _iteratorNormalCompletion6 = true;
58874 var _didIteratorError6 = false;
58875 var _iteratorError6 = undefined;
58876 try {
58877 for (
58878 var _iterator6 = self._getOptionsArray()[Symbol.iterator](), _step6;
58879 !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done);
58880 _iteratorNormalCompletion6 = true
58881 ) {
58882 var _option = _step6.value;
58883 if (_option.value === value) {
58884 _option.setAttribute('checked', true);
58885 result = _option;
58886 }
58887 }
58888 } catch (err) {
58889 _didIteratorError6 = true;
58890 _iteratorError6 = err;
58891 } finally {
58892 try {
58893 if (!_iteratorNormalCompletion6 && _iterator6.return != null) {
58894 _iterator6.return();
58895 }
58896 } finally {
58897 if (_didIteratorError6) {
58898 throw _iteratorError6;
58899 }
58900 }
58901 }
58902 }
58903 return result;
58904 };
58905
58906 self.disable = function() {
58907 var shouldDisable =
58908 arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
58909 var _iteratorNormalCompletion7 = true;
58910 var _didIteratorError7 = false;
58911 var _iteratorError7 = undefined;
58912 try {
58913 for (
58914 var _iterator7 = self._getOptionsArray()[Symbol.iterator](), _step7;
58915 !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done);
58916 _iteratorNormalCompletion7 = true
58917 ) {
58918 var radioInput = _step7.value;
58919 radioInput.setAttribute('disabled', shouldDisable);
58920 }
58921 } catch (err) {
58922 _didIteratorError7 = true;
58923 _iteratorError7 = err;
58924 } finally {
58925 try {
58926 if (!_iteratorNormalCompletion7 && _iterator7.return != null) {
58927 _iterator7.return();
58928 }
58929 } finally {
58930 if (_didIteratorError7) {
58931 throw _iteratorError7;
58932 }
58933 }
58934 }
58935 };
58936
58937 return self;
58938 };
58939
58940 /**
58941 * Creates a colorPicker element in the DOM for color input.
58942 * The .value() method will return a hex string (#rrggbb) of the color.
58943 * The .color() method will return a p5.Color object with the current chosen color.
58944 *
58945 * @method createColorPicker
58946 * @param {String|p5.Color} [value] default color of element
58947 * @return {p5.Element} pointer to <a href="#/p5.Element">p5.Element</a> holding created node
58948 * @example
58949 * <div><code>
58950 * let colorPicker;
58951 * function setup() {
58952 * createCanvas(100, 100);
58953 * colorPicker = createColorPicker('#ed225d');
58954 * colorPicker.position(0, height + 5);
58955 * }
58956 *
58957 * function draw() {
58958 * background(colorPicker.color());
58959 * }
58960 * </code></div>
58961 * <div><code>
58962 * let inp1, inp2;
58963 * function setup() {
58964 * createCanvas(100, 100);
58965 * background('grey');
58966 * inp1 = createColorPicker('#ff0000');
58967 * inp1.position(0, height + 5);
58968 * inp1.input(setShade1);
58969 * inp2 = createColorPicker(color('yellow'));
58970 * inp2.position(0, height + 30);
58971 * inp2.input(setShade2);
58972 * setMidShade();
58973 * }
58974 *
58975 * function setMidShade() {
58976 * // Finding a shade between the two
58977 * let commonShade = lerpColor(inp1.color(), inp2.color(), 0.5);
58978 * fill(commonShade);
58979 * rect(20, 20, 60, 60);
58980 * }
58981 *
58982 * function setShade1() {
58983 * setMidShade();
58984 * console.log('You are choosing shade 1 to be : ', this.value());
58985 * }
58986 * function setShade2() {
58987 * setMidShade();
58988 * console.log('You are choosing shade 2 to be : ', this.value());
58989 * }
58990 * </code></div>
58991 */
58992 _main.default.prototype.createColorPicker = function(value) {
58993 _main.default._validateParameters('createColorPicker', arguments);
58994 var elt = document.createElement('input');
58995 var self;
58996 elt.type = 'color';
58997 if (value) {
58998 if (value instanceof _main.default.Color) {
58999 elt.value = value.toString('#rrggbb');
59000 } else {
59001 _main.default.prototype._colorMode = 'rgb';
59002 _main.default.prototype._colorMaxes = {
59003 rgb: [255, 255, 255, 255],
59004 hsb: [360, 100, 100, 1],
59005 hsl: [360, 100, 100, 1]
59006 };
59007
59008 elt.value = _main.default.prototype.color(value).toString('#rrggbb');
59009 }
59010 } else {
59011 elt.value = '#000000';
59012 }
59013 self = addElement(elt, this);
59014 // Method to return a p5.Color object for the given color.
59015 self.color = function() {
59016 if (value) {
59017 if (value.mode) {
59018 _main.default.prototype._colorMode = value.mode;
59019 }
59020 if (value.maxes) {
59021 _main.default.prototype._colorMaxes = value.maxes;
59022 }
59023 }
59024 return _main.default.prototype.color(this.elt.value);
59025 };
59026 return self;
59027 };
59028
59029 /**
59030 * Creates an &lt;input&gt;&lt;/input&gt; element in the DOM for text input.
59031 * Use .<a href="#/p5.Element/size">size()</a> to set the display length of the box.
59032 *
59033 * @method createInput
59034 * @param {String} value default value of the input box
59035 * @param {String} [type] type of text, ie text, password etc. Defaults to text.
59036 * Needs a value to be specified first.
59037 * @return {p5.Element} pointer to <a href="#/p5.Element">p5.Element</a> holding created node
59038 * @example
59039 * <div class='norender'><code>
59040 * function setup() {
59041 * let inp = createInput('');
59042 * inp.input(myInputEvent);
59043 * }
59044 *
59045 * function myInputEvent() {
59046 * console.log('you are typing: ', this.value());
59047 * }
59048 * </code></div>
59049 */
59050 /**
59051 * @method createInput
59052 * @param {String} [value]
59053 * @return {p5.Element}
59054 */
59055 _main.default.prototype.createInput = function() {
59056 var value =
59057 arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
59058 var type =
59059 arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'text';
59060 _main.default._validateParameters('createInput', arguments);
59061 var elt = document.createElement('input');
59062 elt.setAttribute('value', value);
59063 elt.setAttribute('type', type);
59064 return addElement(elt, this);
59065 };
59066
59067 /**
59068 * Creates an &lt;input&gt;&lt;/input&gt; element in the DOM of type 'file'.
59069 * This allows users to select local files for use in a sketch.
59070 *
59071 * @method createFileInput
59072 * @param {Function} callback callback function for when a file is loaded
59073 * @param {Boolean} [multiple] optional, to allow multiple files to be selected
59074 * @return {p5.Element} pointer to <a href="#/p5.Element">p5.Element</a> holding created DOM element
59075 * @example
59076 * <div><code>
59077 * let input;
59078 * let img;
59079 *
59080 * function setup() {
59081 * input = createFileInput(handleFile);
59082 * input.position(0, 0);
59083 * }
59084 *
59085 * function draw() {
59086 * background(255);
59087 * if (img) {
59088 * image(img, 0, 0, width, height);
59089 * }
59090 * }
59091 *
59092 * function handleFile(file) {
59093 * print(file);
59094 * if (file.type === 'image') {
59095 * img = createImg(file.data, '');
59096 * img.hide();
59097 * } else {
59098 * img = null;
59099 * }
59100 * }
59101 * </code></div>
59102 */
59103 _main.default.prototype.createFileInput = function(callback) {
59104 var multiple =
59105 arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
59106 _main.default._validateParameters('createFileInput', arguments);
59107
59108 var handleFileSelect = function handleFileSelect(event) {
59109 var _iteratorNormalCompletion8 = true;
59110 var _didIteratorError8 = false;
59111 var _iteratorError8 = undefined;
59112 try {
59113 for (
59114 var _iterator8 = event.target.files[Symbol.iterator](), _step8;
59115 !(_iteratorNormalCompletion8 = (_step8 = _iterator8.next()).done);
59116 _iteratorNormalCompletion8 = true
59117 ) {
59118 var file = _step8.value;
59119 _main.default.File._load(file, callback);
59120 }
59121 } catch (err) {
59122 _didIteratorError8 = true;
59123 _iteratorError8 = err;
59124 } finally {
59125 try {
59126 if (!_iteratorNormalCompletion8 && _iterator8.return != null) {
59127 _iterator8.return();
59128 }
59129 } finally {
59130 if (_didIteratorError8) {
59131 throw _iteratorError8;
59132 }
59133 }
59134 }
59135 };
59136
59137 // If File API's are not supported, throw Error
59138 if (!(window.File && window.FileReader && window.FileList && window.Blob)) {
59139 console.log(
59140 'The File APIs are not fully supported in this browser. Cannot create element.'
59141 );
59142
59143 return;
59144 }
59145
59146 var fileInput = document.createElement('input');
59147 fileInput.setAttribute('type', 'file');
59148 if (multiple) fileInput.setAttribute('multiple', true);
59149 fileInput.addEventListener('change', handleFileSelect, false);
59150 return addElement(fileInput, this);
59151 };
59152
59153 /** VIDEO STUFF **/
59154
59155 // Helps perform similar tasks for media element methods.
59156 function createMedia(pInst, type, src, callback) {
59157 var elt = document.createElement(type);
59158
59159 // Create source elements from given sources
59160 src = src || '';
59161 if (typeof src === 'string') {
59162 src = [src];
59163 }
59164 var _iteratorNormalCompletion9 = true;
59165 var _didIteratorError9 = false;
59166 var _iteratorError9 = undefined;
59167 try {
59168 for (
59169 var _iterator9 = src[Symbol.iterator](), _step9;
59170 !(_iteratorNormalCompletion9 = (_step9 = _iterator9.next()).done);
59171 _iteratorNormalCompletion9 = true
59172 ) {
59173 var mediaSource = _step9.value;
59174 var sourceEl = document.createElement('source');
59175 sourceEl.setAttribute('src', mediaSource);
59176 elt.appendChild(sourceEl);
59177 }
59178
59179 // If callback is provided, attach to element
59180 } catch (err) {
59181 _didIteratorError9 = true;
59182 _iteratorError9 = err;
59183 } finally {
59184 try {
59185 if (!_iteratorNormalCompletion9 && _iterator9.return != null) {
59186 _iterator9.return();
59187 }
59188 } finally {
59189 if (_didIteratorError9) {
59190 throw _iteratorError9;
59191 }
59192 }
59193 }
59194 if (typeof callback === 'function') {
59195 var callbackHandler = function callbackHandler() {
59196 callback();
59197 elt.removeEventListener('canplaythrough', callbackHandler);
59198 };
59199 elt.addEventListener('canplaythrough', callbackHandler);
59200 }
59201
59202 var mediaEl = addElement(elt, pInst, true);
59203 mediaEl.loadedmetadata = false;
59204
59205 // set width and height onload metadata
59206 elt.addEventListener('loadedmetadata', function() {
59207 mediaEl.width = elt.videoWidth;
59208 mediaEl.height = elt.videoHeight;
59209
59210 // set elt width and height if not set
59211 if (mediaEl.elt.width === 0) mediaEl.elt.width = elt.videoWidth;
59212 if (mediaEl.elt.height === 0) mediaEl.elt.height = elt.videoHeight;
59213 if (mediaEl.presetPlaybackRate) {
59214 mediaEl.elt.playbackRate = mediaEl.presetPlaybackRate;
59215 delete mediaEl.presetPlaybackRate;
59216 }
59217 mediaEl.loadedmetadata = true;
59218 });
59219
59220 return mediaEl;
59221 }
59222
59223 /**
59224 * Creates an HTML5 &lt;video&gt; element in the DOM for simple playback
59225 * of audio/video. Shown by default, can be hidden with .<a href="#/p5.Element/hide">hide()</a>
59226 * and drawn into canvas using <a href="#/p5/image">image()</a>. The first parameter
59227 * can be either a single string path to a video file, or an array of string
59228 * paths to different formats of the same video. This is useful for ensuring
59229 * that your video can play across different browsers, as each supports
59230 * different formats. See <a href='https://developer.mozilla.org/en-US/docs/Web/HTML/Supported_media_formats'>this
59231 * page</a> for further information about supported formats.
59232 *
59233 * @method createVideo
59234 * @param {String|String[]} src path to a video file, or array of paths for
59235 * supporting different browsers
59236 * @param {Function} [callback] callback function to be called upon
59237 * 'canplaythrough' event fire, that is, when the
59238 * browser can play the media, and estimates that
59239 * enough data has been loaded to play the media
59240 * up to its end without having to stop for
59241 * further buffering of content
59242 * @return {p5.MediaElement} pointer to video <a href="#/p5.Element">p5.Element</a>
59243 * @example
59244 * <div><code>
59245 * let vid;
59246 * function setup() {
59247 * noCanvas();
59248 *
59249 * vid = createVideo(
59250 * ['assets/small.mp4', 'assets/small.ogv', 'assets/small.webm'],
59251 * vidLoad
59252 * );
59253 *
59254 * vid.size(100, 100);
59255 * }
59256 *
59257 * // This function is called when the video loads
59258 * function vidLoad() {
59259 * vid.loop();
59260 * vid.volume(0);
59261 * }
59262 * </code></div>
59263 */
59264 _main.default.prototype.createVideo = function(src, callback) {
59265 _main.default._validateParameters('createVideo', arguments);
59266 return createMedia(this, 'video', src, callback);
59267 };
59268
59269 /** AUDIO STUFF **/
59270
59271 /**
59272 * Creates a hidden HTML5 &lt;audio&gt; element in the DOM for simple audio
59273 * playback. The first parameter can be either a single string path to a
59274 * audio file, or an array of string paths to different formats of the same
59275 * audio. This is useful for ensuring that your audio can play across
59276 * different browsers, as each supports different formats.
59277 * See <a href='https://developer.mozilla.org/en-US/docs/Web/HTML/Supported_media_formats'>this
59278 * page for further information about supported formats</a>.
59279 *
59280 * @method createAudio
59281 * @param {String|String[]} [src] path to an audio file, or array of paths
59282 * for supporting different browsers
59283 * @param {Function} [callback] callback function to be called upon
59284 * 'canplaythrough' event fire, that is, when the
59285 * browser can play the media, and estimates that
59286 * enough data has been loaded to play the media
59287 * up to its end without having to stop for
59288 * further buffering of content
59289 * @return {p5.MediaElement} pointer to audio <a href="#/p5.Element">p5.Element</a>
59290 * @example
59291 * <div><code>
59292 * let ele;
59293 * function setup() {
59294 * ele = createAudio('assets/beat.mp3');
59295 *
59296 * // here we set the element to autoplay
59297 * // The element will play as soon
59298 * // as it is able to do so.
59299 * ele.autoplay(true);
59300 * }
59301 * </code></div>
59302 */
59303 _main.default.prototype.createAudio = function(src, callback) {
59304 _main.default._validateParameters('createAudio', arguments);
59305 return createMedia(this, 'audio', src, callback);
59306 };
59307
59308 /** CAMERA STUFF **/
59309
59310 /**
59311 * @property {String} VIDEO
59312 * @final
59313 * @category Constants
59314 */
59315 _main.default.prototype.VIDEO = 'video';
59316 /**
59317 * @property {String} AUDIO
59318 * @final
59319 * @category Constants
59320 */
59321 _main.default.prototype.AUDIO = 'audio';
59322
59323 // from: https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia
59324 // Older browsers might not implement mediaDevices at all, so we set an empty object first
59325 if (navigator.mediaDevices === undefined) {
59326 navigator.mediaDevices = {};
59327 }
59328
59329 // Some browsers partially implement mediaDevices. We can't just assign an object
59330 // with getUserMedia as it would overwrite existing properties.
59331 // Here, we will just add the getUserMedia property if it's missing.
59332 if (navigator.mediaDevices.getUserMedia === undefined) {
59333 navigator.mediaDevices.getUserMedia = function(constraints) {
59334 // First get ahold of the legacy getUserMedia, if present
59335 var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
59336
59337 // Some browsers just don't implement it - return a rejected promise with an error
59338 // to keep a consistent interface
59339 if (!getUserMedia) {
59340 return Promise.reject(
59341 new Error('getUserMedia is not implemented in this browser')
59342 );
59343 }
59344
59345 // Otherwise, wrap the call to the old navigator.getUserMedia with a Promise
59346 return new Promise(function(resolve, reject) {
59347 getUserMedia.call(navigator, constraints, resolve, reject);
59348 });
59349 };
59350 }
59351
59352 /**
59353 * Creates a new HTML5 &lt;video&gt; element that contains the audio/video feed
59354 * from a webcam. The element is separate from the canvas and is displayed by
59355 * default. The element can be hidden using .<a href="#/p5.Element/hide">hide()</a>.
59356 * The feed can be drawn onto the canvas using <a href="#/p5/image">image()</a>.
59357 * The loadedmetadata property can be used to detect when the element has fully
59358 * loaded (see second example).
59359 *
59360 * More specific properties of the feed can be passing in a Constraints object.
59361 * See the <a href='http://w3c.github.io/mediacapture-main/getusermedia.html#media-track-constraints'>
59362 * W3C spec</a> for possible properties. Note that not all of these are supported
59363 * by all browsers.
59364 *
59365 * <em>Security note</em>: A new browser security specification requires that
59366 * getUserMedia, which is behind <a href="#/p5/createCapture">createCapture()</a>,
59367 * only works when you're running the code locally, or on HTTPS. Learn more
59368 * <a href='http://stackoverflow.com/questions/34197653/getusermedia-in-chrome-47-without-using-https'>here</a>
59369 * and <a href='https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia'>here</a>.
59370 *
59371 * @method createCapture
59372 * @param {String|Constant|Object} type type of capture, either VIDEO or
59373 * AUDIO if none specified, default both,
59374 * or a Constraints object
59375 * @param {Function} [callback] function to be called once
59376 * stream has loaded
59377 * @return {p5.Element} capture video <a href="#/p5.Element">p5.Element</a>
59378 * @example
59379 * <div class='norender notest'>
59380 * <code>
59381 * let capture;
59382 *
59383 * function setup() {
59384 * createCanvas(480, 480);
59385 * capture = createCapture(VIDEO);
59386 * capture.hide();
59387 * }
59388 *
59389 * function draw() {
59390 * image(capture, 0, 0, width, width * capture.height / capture.width);
59391 * filter(INVERT);
59392 * }
59393 * </code>
59394 * </div>
59395 *
59396 * <div class='norender notest'>
59397 * <code>
59398 * function setup() {
59399 * createCanvas(480, 120);
59400 * let constraints = {
59401 * video: {
59402 * mandatory: {
59403 * minWidth: 1280,
59404 * minHeight: 720
59405 * },
59406 * optional: [{ maxFrameRate: 10 }]
59407 * },
59408 * audio: true
59409 * };
59410 * createCapture(constraints, function(stream) {
59411 * console.log(stream);
59412 * });
59413 * }
59414 * </code>
59415 * </div>
59416 * <div class='norender notest'>
59417 * <code>
59418 * let capture;
59419 *
59420 * function setup() {
59421 * createCanvas(640, 480);
59422 * capture = createCapture(VIDEO);
59423 * }
59424 * function draw() {
59425 * background(0);
59426 * if (capture.loadedmetadata) {
59427 * let c = capture.get(0, 0, 100, 100);
59428 * image(c, 0, 0);
59429 * }
59430 * }
59431 * </code>
59432 * </div>
59433 */
59434 _main.default.prototype.createCapture = function() {
59435 _main.default._validateParameters('createCapture', arguments);
59436
59437 // return if getUserMedia is not supported by browser
59438 if (!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia)) {
59439 throw new DOMException('getUserMedia not supported in this browser');
59440 }
59441
59442 var useVideo = true;
59443 var useAudio = true;
59444 var constraints;
59445 var callback;
59446 var _iteratorNormalCompletion10 = true;
59447 var _didIteratorError10 = false;
59448 var _iteratorError10 = undefined;
59449 try {
59450 for (
59451 var _iterator10 = arguments[Symbol.iterator](), _step10;
59452 !(_iteratorNormalCompletion10 = (_step10 = _iterator10.next()).done);
59453 _iteratorNormalCompletion10 = true
59454 ) {
59455 var arg = _step10.value;
59456 if (arg === _main.default.prototype.VIDEO) useAudio = false;
59457 else if (arg === _main.default.prototype.AUDIO) useVideo = false;
59458 else if (_typeof(arg) === 'object') constraints = arg;
59459 else if (typeof arg === 'function') callback = arg;
59460 }
59461 } catch (err) {
59462 _didIteratorError10 = true;
59463 _iteratorError10 = err;
59464 } finally {
59465 try {
59466 if (!_iteratorNormalCompletion10 && _iterator10.return != null) {
59467 _iterator10.return();
59468 }
59469 } finally {
59470 if (_didIteratorError10) {
59471 throw _iteratorError10;
59472 }
59473 }
59474 }
59475 if (!constraints) constraints = { video: useVideo, audio: useAudio };
59476
59477 var domElement = document.createElement('video');
59478 // required to work in iOS 11 & up:
59479 domElement.setAttribute('playsinline', '');
59480
59481 navigator.mediaDevices.getUserMedia(constraints).then(function(stream) {
59482 try {
59483 if ('srcObject' in domElement) {
59484 domElement.srcObject = stream;
59485 } else {
59486 domElement.src = window.URL.createObjectURL(stream);
59487 }
59488 } catch (err) {
59489 domElement.src = stream;
59490 }
59491 }, console.log);
59492
59493 var videoEl = addElement(domElement, this, true);
59494 videoEl.loadedmetadata = false;
59495 // set width and height onload metadata
59496 domElement.addEventListener('loadedmetadata', function() {
59497 domElement.play();
59498 if (domElement.width) {
59499 videoEl.width = domElement.width;
59500 videoEl.height = domElement.height;
59501 } else {
59502 videoEl.width = videoEl.elt.width = domElement.videoWidth;
59503 videoEl.height = videoEl.elt.height = domElement.videoHeight;
59504 }
59505 videoEl.loadedmetadata = true;
59506
59507 if (callback) callback(domElement.srcObject);
59508 });
59509 return videoEl;
59510 };
59511
59512 /**
59513 * Creates element with given tag in the DOM with given content.
59514 *
59515 * @method createElement
59516 * @param {String} tag tag for the new element
59517 * @param {String} [content] html content to be inserted into the element
59518 * @return {p5.Element} pointer to <a href="#/p5.Element">p5.Element</a> holding created node
59519 * @example
59520 * <div class='norender'><code>
59521 * createElement('h2', 'im an h2 p5.element!');
59522 * </code></div>
59523 */
59524 _main.default.prototype.createElement = function(tag, content) {
59525 _main.default._validateParameters('createElement', arguments);
59526 var elt = document.createElement(tag);
59527 if (typeof content !== 'undefined') {
59528 elt.innerHTML = content;
59529 }
59530 return addElement(elt, this);
59531 };
59532
59533 // =============================================================================
59534 // p5.Element additions
59535 // =============================================================================
59536 /**
59537 *
59538 * Adds specified class to the element.
59539 *
59540 * @for p5.Element
59541 * @method addClass
59542 * @param {String} class name of class to add
59543 * @chainable
59544 * @example
59545 * <div class='norender'><code>
59546 * let div = createDiv('div');
59547 * div.addClass('myClass');
59548 * </code></div>
59549 */
59550 _main.default.Element.prototype.addClass = function(c) {
59551 if (this.elt.className) {
59552 if (!this.hasClass(c)) {
59553 this.elt.className = this.elt.className + ' ' + c;
59554 }
59555 } else {
59556 this.elt.className = c;
59557 }
59558 return this;
59559 };
59560
59561 /**
59562 *
59563 * Removes specified class from the element.
59564 *
59565 * @method removeClass
59566 * @param {String} class name of class to remove
59567 * @chainable
59568 * @example
59569 * <div class='norender'><code>
59570 * // In this example, a class is set when the div is created
59571 * // and removed when mouse is pressed. This could link up
59572 * // with a CSS style rule to toggle style properties.
59573 *
59574 * let div;
59575 *
59576 * function setup() {
59577 * div = createDiv('div');
59578 * div.addClass('myClass');
59579 * }
59580 *
59581 * function mousePressed() {
59582 * div.removeClass('myClass');
59583 * }
59584 * </code></div>
59585 */
59586 _main.default.Element.prototype.removeClass = function(c) {
59587 // Note: Removing a class that does not exist does NOT throw an error in classList.remove method
59588 this.elt.classList.remove(c);
59589 return this;
59590 };
59591
59592 /**
59593 *
59594 * Checks if specified class already set to element
59595 *
59596 * @method hasClass
59597 * @returns {boolean} a boolean value if element has specified class
59598 * @param c {String} class name of class to check
59599 * @example
59600 * <div class='norender'><code>
59601 * let div;
59602 *
59603 * function setup() {
59604 * div = createDiv('div');
59605 * div.addClass('show');
59606 * }
59607 *
59608 * function mousePressed() {
59609 * if (div.hasClass('show')) {
59610 * div.addClass('show');
59611 * } else {
59612 * div.removeClass('show');
59613 * }
59614 * }
59615 * </code></div>
59616 */
59617 _main.default.Element.prototype.hasClass = function(c) {
59618 return this.elt.classList.contains(c);
59619 };
59620
59621 /**
59622 *
59623 * Toggles element class
59624 *
59625 * @method toggleClass
59626 * @param c {String} class name to toggle
59627 * @chainable
59628 * @example
59629 * <div class='norender'><code>
59630 * let div;
59631 *
59632 * function setup() {
59633 * div = createDiv('div');
59634 * div.addClass('show');
59635 * }
59636 *
59637 * function mousePressed() {
59638 * div.toggleClass('show');
59639 * }
59640 * </code></div>
59641 */
59642 _main.default.Element.prototype.toggleClass = function(c) {
59643 // classList also has a toggle() method, but we cannot use that yet as support is unclear.
59644 // See https://github.com/processing/p5.js/issues/3631
59645 // this.elt.classList.toggle(c);
59646 if (this.elt.classList.contains(c)) {
59647 this.elt.classList.remove(c);
59648 } else {
59649 this.elt.classList.add(c);
59650 }
59651 return this;
59652 };
59653
59654 /**
59655 *
59656 * Attaches the element as a child to the parent specified.
59657 * Accepts either a string ID, DOM node, or <a href="#/p5.Element">p5.Element</a>.
59658 * If no argument is specified, an array of children DOM nodes is returned.
59659 *
59660 * @method child
59661 * @returns {Node[]} an array of child nodes
59662 * @example
59663 * <div class='norender'><code>
59664 * let div0 = createDiv('this is the parent');
59665 * let div1 = createDiv('this is the child');
59666 * div0.child(div1); // use p5.Element
59667 * </code></div>
59668 * <div class='norender'><code>
59669 * let div0 = createDiv('this is the parent');
59670 * let div1 = createDiv('this is the child');
59671 * div1.id('apples');
59672 * div0.child('apples'); // use id
59673 * </code></div>
59674 * <div class='norender notest'><code>
59675 * // this example assumes there is a div already on the page
59676 * // with id "myChildDiv"
59677 * let div0 = createDiv('this is the parent');
59678 * let elt = document.getElementById('myChildDiv');
59679 * div0.child(elt); // use element from page
59680 * </code></div>
59681 */
59682 /**
59683 * @method child
59684 * @param {String|p5.Element} [child] the ID, DOM node, or <a href="#/p5.Element">p5.Element</a>
59685 * to add to the current element
59686 * @chainable
59687 */
59688 _main.default.Element.prototype.child = function(childNode) {
59689 if (typeof childNode === 'undefined') {
59690 return this.elt.childNodes;
59691 }
59692 if (typeof childNode === 'string') {
59693 if (childNode[0] === '#') {
59694 childNode = childNode.substring(1);
59695 }
59696 childNode = document.getElementById(childNode);
59697 } else if (childNode instanceof _main.default.Element) {
59698 childNode = childNode.elt;
59699 }
59700
59701 if (childNode instanceof HTMLElement) {
59702 this.elt.appendChild(childNode);
59703 }
59704 return this;
59705 };
59706
59707 /**
59708 * Centers a p5 Element either vertically, horizontally,
59709 * or both, relative to its parent or according to
59710 * the body if the Element has no parent. If no argument is passed
59711 * the Element is aligned both vertically and horizontally.
59712 *
59713 * @method center
59714 * @param {String} [align] passing 'vertical', 'horizontal' aligns element accordingly
59715 * @chainable
59716 *
59717 * @example
59718 * <div><code>
59719 * function setup() {
59720 * let div = createDiv('').size(10, 10);
59721 * div.style('background-color', 'orange');
59722 * div.center();
59723 * }
59724 * </code></div>
59725 */
59726 _main.default.Element.prototype.center = function(align) {
59727 var style = this.elt.style.display;
59728 var hidden = this.elt.style.display === 'none';
59729 var parentHidden = this.parent().style.display === 'none';
59730 var pos = { x: this.elt.offsetLeft, y: this.elt.offsetTop };
59731
59732 if (hidden) this.show();
59733 if (parentHidden) this.parent().show();
59734 this.elt.style.display = 'block';
59735
59736 this.position(0, 0);
59737 var wOffset = Math.abs(this.parent().offsetWidth - this.elt.offsetWidth);
59738 var hOffset = Math.abs(this.parent().offsetHeight - this.elt.offsetHeight);
59739
59740 if (align === 'both' || align === undefined) {
59741 this.position(
59742 wOffset / 2 + this.parent().offsetLeft,
59743 hOffset / 2 + this.parent().offsetTop
59744 );
59745 } else if (align === 'horizontal') {
59746 this.position(wOffset / 2 + this.parent().offsetLeft, pos.y);
59747 } else if (align === 'vertical') {
59748 this.position(pos.x, hOffset / 2 + this.parent().offsetTop);
59749 }
59750
59751 this.style('display', style);
59752 if (hidden) this.hide();
59753 if (parentHidden) this.parent().hide();
59754
59755 return this;
59756 };
59757
59758 /**
59759 *
59760 * If an argument is given, sets the inner HTML of the element,
59761 * replacing any existing html. If true is included as a second
59762 * argument, html is appended instead of replacing existing html.
59763 * If no arguments are given, returns
59764 * the inner HTML of the element.
59765 *
59766 * @for p5.Element
59767 * @method html
59768 * @returns {String} the inner HTML of the element
59769 * @example
59770 * <div class='norender'><code>
59771 * let div = createDiv('').size(100, 100);
59772 * div.html('hi');
59773 * </code></div>
59774 * <div class='norender'><code>
59775 * let div = createDiv('Hello ').size(100, 100);
59776 * div.html('World', true);
59777 * </code></div>
59778 */
59779 /**
59780 * @method html
59781 * @param {String} [html] the HTML to be placed inside the element
59782 * @param {boolean} [append] whether to append HTML to existing
59783 * @chainable
59784 */
59785 _main.default.Element.prototype.html = function() {
59786 if (arguments.length === 0) {
59787 return this.elt.innerHTML;
59788 } else if (arguments[1]) {
59789 this.elt.insertAdjacentHTML('beforeend', arguments[0]);
59790 return this;
59791 } else {
59792 this.elt.innerHTML = arguments[0];
59793 return this;
59794 }
59795 };
59796
59797 /**
59798 *
59799 * Sets the position of the element. If no position type argument is given, the
59800 * position will be relative to (0, 0) of the window.
59801 * Essentially, this sets position:absolute and left and top
59802 * properties of style. If an optional third argument specifying position type is given,
59803 * the x and y coordinates will be interpreted based on the <a target="_blank"
59804 * href="https://developer.mozilla.org/en-US/docs/Web/CSS/position">positioning scheme</a>.
59805 * If no arguments given, the function returns the x and y position of the element.
59806 *
59807 * found documentation on how to be more specific with object type
59808 * https://stackoverflow.com/questions/14714314/how-do-i-comment-object-literals-in-yuidoc
59809 *
59810 * @method position
59811 * @returns {Object} object of form { x: 0, y: 0 } containing the position of the element in an object
59812 * @example
59813 * <div><code class='norender'>
59814 * function setup() {
59815 * let cnv = createCanvas(100, 100);
59816 * // positions canvas 50px to the right and 100px
59817 * // below upper left corner of the window
59818 * cnv.position(50, 100);
59819 * }
59820 * </code></div>
59821 * <div><code class='norender'>
59822 * function setup() {
59823 * let cnv = createCanvas(100, 100);
59824 * // positions canvas 50px to the right and 100px
59825 * // below upper left corner of the window
59826 * cnv.position(0, 0, 'fixed');
59827 * }
59828 * </code></div>
59829 */
59830 /**
59831 * @method position
59832 * @param {Number} [x] x-position relative to upper left of window (optional)
59833 * @param {Number} [y] y-position relative to upper left of window (optional)
59834 * @param {String} positionType it can be static, fixed, relative, sticky, initial or inherit (optional)
59835 * @chainable
59836 */
59837 _main.default.Element.prototype.position = function() {
59838 if (arguments.length === 0) {
59839 return { x: this.elt.offsetLeft, y: this.elt.offsetTop };
59840 } else {
59841 var positionType = 'absolute';
59842 if (
59843 arguments[2] === 'static' ||
59844 arguments[2] === 'fixed' ||
59845 arguments[2] === 'relative' ||
59846 arguments[2] === 'sticky' ||
59847 arguments[2] === 'initial' ||
59848 arguments[2] === 'inherit'
59849 ) {
59850 positionType = arguments[2];
59851 }
59852 this.elt.style.position = positionType;
59853 this.elt.style.left = arguments[0] + 'px';
59854 this.elt.style.top = arguments[1] + 'px';
59855 this.x = arguments[0];
59856 this.y = arguments[1];
59857 return this;
59858 }
59859 };
59860
59861 /* Helper method called by p5.Element.style() */
59862 _main.default.Element.prototype._translate = function() {
59863 this.elt.style.position = 'absolute';
59864 // save out initial non-translate transform styling
59865 var transform = '';
59866 if (this.elt.style.transform) {
59867 transform = this.elt.style.transform.replace(/translate3d\(.*\)/g, '');
59868 transform = transform.replace(/translate[X-Z]?\(.*\)/g, '');
59869 }
59870 if (arguments.length === 2) {
59871 this.elt.style.transform =
59872 'translate(' + arguments[0] + 'px, ' + arguments[1] + 'px)';
59873 } else if (arguments.length > 2) {
59874 this.elt.style.transform =
59875 'translate3d(' +
59876 arguments[0] +
59877 'px,' +
59878 arguments[1] +
59879 'px,' +
59880 arguments[2] +
59881 'px)';
59882 if (arguments.length === 3) {
59883 this.elt.parentElement.style.perspective = '1000px';
59884 } else {
59885 this.elt.parentElement.style.perspective = arguments[3] + 'px';
59886 }
59887 }
59888 // add any extra transform styling back on end
59889 this.elt.style.transform += transform;
59890 return this;
59891 };
59892
59893 /* Helper method called by p5.Element.style() */
59894 _main.default.Element.prototype._rotate = function() {
59895 // save out initial non-rotate transform styling
59896 var transform = '';
59897 if (this.elt.style.transform) {
59898 transform = this.elt.style.transform.replace(/rotate3d\(.*\)/g, '');
59899 transform = transform.replace(/rotate[X-Z]?\(.*\)/g, '');
59900 }
59901
59902 if (arguments.length === 1) {
59903 this.elt.style.transform = 'rotate(' + arguments[0] + 'deg)';
59904 } else if (arguments.length === 2) {
59905 this.elt.style.transform =
59906 'rotate(' + arguments[0] + 'deg, ' + arguments[1] + 'deg)';
59907 } else if (arguments.length === 3) {
59908 this.elt.style.transform = 'rotateX(' + arguments[0] + 'deg)';
59909 this.elt.style.transform += 'rotateY(' + arguments[1] + 'deg)';
59910 this.elt.style.transform += 'rotateZ(' + arguments[2] + 'deg)';
59911 }
59912 // add remaining transform back on
59913 this.elt.style.transform += transform;
59914 return this;
59915 };
59916
59917 /**
59918 * Sets the given style (css) property (1st arg) of the element with the
59919 * given value (2nd arg). If a single argument is given, .style()
59920 * returns the value of the given property; however, if the single argument
59921 * is given in css syntax ('text-align:center'), .style() sets the css
59922 * appropriately.
59923 *
59924 * @method style
59925 * @param {String} property property to be set
59926 * @returns {String} value of property
59927 * @example
59928 * <div><code class='norender'>
59929 * let myDiv = createDiv('I like pandas.');
59930 * myDiv.style('font-size', '18px');
59931 * myDiv.style('color', '#ff0000');
59932 * </code></div>
59933 * <div><code class='norender'>
59934 * let col = color(25, 23, 200, 50);
59935 * let button = createButton('button');
59936 * button.style('background-color', col);
59937 * button.position(10, 10);
59938 * </code></div>
59939 * <div><code class='norender'>
59940 * let myDiv;
59941 * function setup() {
59942 * background(200);
59943 * myDiv = createDiv('I like gray.');
59944 * myDiv.position(20, 20);
59945 * }
59946 *
59947 * function draw() {
59948 * myDiv.style('font-size', mouseX + 'px');
59949 * }
59950 * </code></div>
59951 */
59952 /**
59953 * @method style
59954 * @param {String} property
59955 * @param {String|p5.Color} value value to assign to property
59956 * @return {String} current value of property, if no value is given as second argument
59957 * @chainable
59958 */
59959 _main.default.Element.prototype.style = function(prop, val) {
59960 var self = this;
59961
59962 if (val instanceof _main.default.Color) {
59963 val =
59964 'rgba(' +
59965 val.levels[0] +
59966 ',' +
59967 val.levels[1] +
59968 ',' +
59969 val.levels[2] +
59970 ',' +
59971 val.levels[3] / 255 +
59972 ')';
59973 }
59974
59975 if (typeof val === 'undefined') {
59976 if (prop.indexOf(':') === -1) {
59977 // no value set, so assume requesting a value
59978 var styles = window.getComputedStyle(self.elt);
59979 var style = styles.getPropertyValue(prop);
59980 return style;
59981 } else {
59982 // value set using `:` in a single line string
59983 var attrs = prop.split(';');
59984 for (var i = 0; i < attrs.length; i++) {
59985 var parts = attrs[i].split(':');
59986 if (parts[0] && parts[1]) {
59987 this.elt.style[parts[0].trim()] = parts[1].trim();
59988 }
59989 }
59990 }
59991 } else {
59992 // input provided as key,val pair
59993 this.elt.style[prop] = val;
59994 if (
59995 prop === 'width' ||
59996 prop === 'height' ||
59997 prop === 'left' ||
59998 prop === 'top'
59999 ) {
60000 var _styles = window.getComputedStyle(self.elt);
60001 var styleVal = _styles.getPropertyValue(prop);
60002 var numVal = styleVal.replace(/\D+/g, '');
60003 this[prop] = parseInt(numVal, 10);
60004 }
60005 }
60006 return this;
60007 };
60008
60009 /**
60010 *
60011 * Adds a new attribute or changes the value of an existing attribute
60012 * on the specified element. If no value is specified, returns the
60013 * value of the given attribute, or null if attribute is not set.
60014 *
60015 * @method attribute
60016 * @return {String} value of attribute
60017 *
60018 * @example
60019 * <div class='norender'><code>
60020 * let myDiv = createDiv('I like pandas.');
60021 * myDiv.attribute('align', 'center');
60022 * </code></div>
60023 */
60024 /**
60025 * @method attribute
60026 * @param {String} attr attribute to set
60027 * @param {String} value value to assign to attribute
60028 * @chainable
60029 */
60030 _main.default.Element.prototype.attribute = function(attr, value) {
60031 //handling for checkboxes and radios to ensure options get
60032 //attributes not divs
60033 if (
60034 this.elt.firstChild != null &&
60035 (this.elt.firstChild.type === 'checkbox' ||
60036 this.elt.firstChild.type === 'radio')
60037 ) {
60038 if (typeof value === 'undefined') {
60039 return this.elt.firstChild.getAttribute(attr);
60040 } else {
60041 for (var i = 0; i < this.elt.childNodes.length; i++) {
60042 this.elt.childNodes[i].setAttribute(attr, value);
60043 }
60044 }
60045 } else if (typeof value === 'undefined') {
60046 return this.elt.getAttribute(attr);
60047 } else {
60048 this.elt.setAttribute(attr, value);
60049 return this;
60050 }
60051 };
60052
60053 /**
60054 *
60055 * Removes an attribute on the specified element.
60056 *
60057 * @method removeAttribute
60058 * @param {String} attr attribute to remove
60059 * @chainable
60060 *
60061 * @example
60062 * <div><code>
60063 * let button;
60064 * let checkbox;
60065 *
60066 * function setup() {
60067 * checkbox = createCheckbox('enable', true);
60068 * checkbox.changed(enableButton);
60069 * button = createButton('button');
60070 * button.position(10, 10);
60071 * }
60072 *
60073 * function enableButton() {
60074 * if (this.checked()) {
60075 * // Re-enable the button
60076 * button.removeAttribute('disabled');
60077 * } else {
60078 * // Disable the button
60079 * button.attribute('disabled', '');
60080 * }
60081 * }
60082 * </code></div>
60083 */
60084 _main.default.Element.prototype.removeAttribute = function(attr) {
60085 if (
60086 this.elt.firstChild != null &&
60087 (this.elt.firstChild.type === 'checkbox' ||
60088 this.elt.firstChild.type === 'radio')
60089 ) {
60090 for (var i = 0; i < this.elt.childNodes.length; i++) {
60091 this.elt.childNodes[i].removeAttribute(attr);
60092 }
60093 }
60094 this.elt.removeAttribute(attr);
60095 return this;
60096 };
60097
60098 /**
60099 * Either returns the value of the element if no arguments
60100 * given, or sets the value of the element.
60101 *
60102 * @method value
60103 * @return {String|Number} value of the element
60104 * @example
60105 * <div class='norender'><code>
60106 * // gets the value
60107 * let inp;
60108 * function setup() {
60109 * inp = createInput('');
60110 * }
60111 *
60112 * function mousePressed() {
60113 * print(inp.value());
60114 * }
60115 * </code></div>
60116 * <div class='norender'><code>
60117 * // sets the value
60118 * let inp;
60119 * function setup() {
60120 * inp = createInput('myValue');
60121 * }
60122 *
60123 * function mousePressed() {
60124 * inp.value('myValue');
60125 * }
60126 * </code></div>
60127 */
60128 /**
60129 * @method value
60130 * @param {String|Number} value
60131 * @chainable
60132 */
60133 _main.default.Element.prototype.value = function() {
60134 if (arguments.length > 0) {
60135 this.elt.value = arguments[0];
60136 return this;
60137 } else {
60138 if (this.elt.type === 'range') {
60139 return parseFloat(this.elt.value);
60140 } else return this.elt.value;
60141 }
60142 };
60143
60144 /**
60145 *
60146 * Shows the current element. Essentially, setting display:block for the style.
60147 *
60148 * @method show
60149 * @chainable
60150 * @example
60151 * <div class='norender'><code>
60152 * let div = createDiv('div');
60153 * div.style('display', 'none');
60154 * div.show(); // turns display to block
60155 * </code></div>
60156 */
60157 _main.default.Element.prototype.show = function() {
60158 this.elt.style.display = 'block';
60159 return this;
60160 };
60161
60162 /**
60163 * Hides the current element. Essentially, setting display:none for the style.
60164 *
60165 * @method hide
60166 * @chainable
60167 * @example
60168 * <div class='norender'><code>
60169 * let div = createDiv('this is a div');
60170 * div.hide();
60171 * </code></div>
60172 */
60173 _main.default.Element.prototype.hide = function() {
60174 this.elt.style.display = 'none';
60175 return this;
60176 };
60177
60178 /**
60179 *
60180 * Sets the width and height of the element. AUTO can be used to
60181 * only adjust one dimension at a time. If no arguments are given, it
60182 * returns the width and height of the element in an object. In case of
60183 * elements which need to be loaded, such as images, it is recommended
60184 * to call the function after the element has finished loading.
60185 *
60186 * @method size
60187 * @return {Object} the width and height of the element in an object
60188 * @example
60189 * <div class='norender'><code>
60190 * let div = createDiv('this is a div');
60191 * div.size(100, 100);
60192 * let img = createImg(
60193 * 'assets/rockies.jpg',
60194 * 'A tall mountain with a small forest and field in front of it on a sunny day',
60195 * '',
60196 * () => {
60197 * img.size(10, AUTO);
60198 * }
60199 * );
60200 * </code></div>
60201 */
60202 /**
60203 * @method size
60204 * @param {Number|Constant} w width of the element, either AUTO, or a number
60205 * @param {Number|Constant} [h] height of the element, either AUTO, or a number
60206 * @chainable
60207 */
60208 _main.default.Element.prototype.size = function(w, h) {
60209 if (arguments.length === 0) {
60210 return { width: this.elt.offsetWidth, height: this.elt.offsetHeight };
60211 } else {
60212 var aW = w;
60213 var aH = h;
60214 var AUTO = _main.default.prototype.AUTO;
60215 if (aW !== AUTO || aH !== AUTO) {
60216 if (aW === AUTO) {
60217 aW = h * this.width / this.height;
60218 } else if (aH === AUTO) {
60219 aH = w * this.height / this.width;
60220 }
60221 // set diff for cnv vs normal div
60222 if (this.elt instanceof HTMLCanvasElement) {
60223 var j = {};
60224 var k = this.elt.getContext('2d');
60225 var prop;
60226 for (prop in k) {
60227 j[prop] = k[prop];
60228 }
60229 this.elt.setAttribute('width', aW * this._pInst._pixelDensity);
60230 this.elt.setAttribute('height', aH * this._pInst._pixelDensity);
60231 this.elt.style.width = aW + 'px';
60232 this.elt.style.height = aH + 'px';
60233 this._pInst.scale(this._pInst._pixelDensity, this._pInst._pixelDensity);
60234 for (prop in j) {
60235 this.elt.getContext('2d')[prop] = j[prop];
60236 }
60237 } else {
60238 this.elt.style.width = aW + 'px';
60239 this.elt.style.height = aH + 'px';
60240 this.elt.width = aW;
60241 this.elt.height = aH;
60242 }
60243
60244 this.width = this.elt.offsetWidth;
60245 this.height = this.elt.offsetHeight;
60246
60247 if (this._pInst && this._pInst._curElement) {
60248 // main canvas associated with p5 instance
60249 if (this._pInst._curElement.elt === this.elt) {
60250 this._pInst._setProperty('width', this.elt.offsetWidth);
60251 this._pInst._setProperty('height', this.elt.offsetHeight);
60252 }
60253 }
60254 }
60255 return this;
60256 }
60257 };
60258
60259 /**
60260 * Removes the element, stops all media streams, and deregisters all listeners.
60261 * @method remove
60262 * @example
60263 * <div class='norender'><code>
60264 * let myDiv = createDiv('this is some text');
60265 * myDiv.remove();
60266 * </code></div>
60267 */
60268 _main.default.Element.prototype.remove = function() {
60269 // stop all audios/videos and detach all devices like microphone/camera etc
60270 // used as input/output for audios/videos.
60271 if (this instanceof _main.default.MediaElement) {
60272 var tracks = this.elt.srcObject.getTracks();
60273 tracks.forEach(function(track) {
60274 track.stop();
60275 });
60276 }
60277
60278 // delete the reference in this._pInst._elements
60279 var index = this._pInst._elements.indexOf(this);
60280 if (index !== -1) {
60281 this._pInst._elements.splice(index, 1);
60282 }
60283
60284 // deregister events
60285 for (var ev in this._events) {
60286 this.elt.removeEventListener(ev, this._events[ev]);
60287 }
60288 if (this.elt && this.elt.parentNode) {
60289 this.elt.parentNode.removeChild(this.elt);
60290 }
60291 };
60292
60293 /**
60294 * Registers a callback that gets called every time a file that is
60295 * dropped on the element has been loaded.
60296 * p5 will load every dropped file into memory and pass it as a p5.File object to the callback.
60297 * Multiple files dropped at the same time will result in multiple calls to the callback.
60298 *
60299 * You can optionally pass a second callback which will be registered to the raw
60300 * <a href="https://developer.mozilla.org/en-US/docs/Web/Events/drop">drop</a> event.
60301 * The callback will thus be provided the original
60302 * <a href="https://developer.mozilla.org/en-US/docs/Web/API/DragEvent">DragEvent</a>.
60303 * Dropping multiple files at the same time will trigger the second callback once per drop,
60304 * whereas the first callback will trigger for each loaded file.
60305 *
60306 * @method drop
60307 * @param {Function} callback callback to receive loaded file, called for each file dropped.
60308 * @param {Function} [fxn] callback triggered once when files are dropped with the drop event.
60309 * @chainable
60310 * @example
60311 * <div><code>
60312 * function setup() {
60313 * let c = createCanvas(100, 100);
60314 * background(200);
60315 * textAlign(CENTER);
60316 * text('drop file', width / 2, height / 2);
60317 * c.drop(gotFile);
60318 * }
60319 *
60320 * function gotFile(file) {
60321 * background(200);
60322 * text('received file:', width / 2, height / 2);
60323 * text(file.name, width / 2, height / 2 + 50);
60324 * }
60325 * </code></div>
60326 *
60327 * <div><code>
60328 * let img;
60329 *
60330 * function setup() {
60331 * let c = createCanvas(100, 100);
60332 * background(200);
60333 * textAlign(CENTER);
60334 * text('drop image', width / 2, height / 2);
60335 * c.drop(gotFile);
60336 * }
60337 *
60338 * function draw() {
60339 * if (img) {
60340 * image(img, 0, 0, width, height);
60341 * }
60342 * }
60343 *
60344 * function gotFile(file) {
60345 * img = createImg(file.data, '').hide();
60346 * }
60347 * </code></div>
60348 *
60349 * @alt
60350 * Canvas turns into whatever image is dragged/dropped onto it.
60351 */
60352 _main.default.Element.prototype.drop = function(callback, fxn) {
60353 // Is the file stuff supported?
60354 if (window.File && window.FileReader && window.FileList && window.Blob) {
60355 if (!this._dragDisabled) {
60356 this._dragDisabled = true;
60357
60358 var preventDefault = function preventDefault(evt) {
60359 evt.preventDefault();
60360 };
60361
60362 // If you want to be able to drop you've got to turn off
60363 // a lot of default behavior.
60364 // avoid `attachListener` here, since it overrides other handlers.
60365 this.elt.addEventListener('dragover', preventDefault);
60366
60367 // If this is a drag area we need to turn off the default behavior
60368 this.elt.addEventListener('dragleave', preventDefault);
60369 }
60370
60371 // Deal with the files
60372 _main.default.Element._attachListener(
60373 'drop',
60374 function(evt) {
60375 evt.preventDefault();
60376 // Call the second argument as a callback that receives the raw drop event
60377 if (typeof fxn === 'function') {
60378 fxn.call(this, evt);
60379 }
60380 // A FileList
60381 var files = evt.dataTransfer.files;
60382
60383 // Load each one and trigger the callback
60384 for (var i = 0; i < files.length; i++) {
60385 var f = files[i];
60386 _main.default.File._load(f, callback);
60387 }
60388 },
60389 this
60390 );
60391 } else {
60392 console.log('The File APIs are not fully supported in this browser.');
60393 }
60394
60395 return this;
60396 };
60397
60398 // =============================================================================
60399 // p5.MediaElement additions
60400 // =============================================================================
60401
60402 /**
60403 * Extends <a href="#/p5.Element">p5.Element</a> to handle audio and video. In addition to the methods
60404 * of <a href="#/p5.Element">p5.Element</a>, it also contains methods for controlling media. It is not
60405 * called directly, but <a href="#/p5.MediaElement">p5.MediaElement</a>s are created by calling <a href="#/p5/createVideo">createVideo</a>,
60406 * <a href="#/p5/createAudio">createAudio</a>, and <a href="#/p5/createCapture">createCapture</a>.
60407 *
60408 * @class p5.MediaElement
60409 * @constructor
60410 * @param {String} elt DOM node that is wrapped
60411 */
60412 _main.default.MediaElement = function(elt, pInst) {
60413 _main.default.Element.call(this, elt, pInst);
60414
60415 var self = this;
60416 this.elt.crossOrigin = 'anonymous';
60417
60418 this._prevTime = 0;
60419 this._cueIDCounter = 0;
60420 this._cues = [];
60421 this._pixelsState = this;
60422 this._pixelDensity = 1;
60423 this._modified = false;
60424
60425 /**
60426 * Path to the media element source.
60427 *
60428 * @property src
60429 * @return {String} src
60430 * @example
60431 * <div><code>
60432 * let ele;
60433 *
60434 * function setup() {
60435 * background(250);
60436 *
60437 * //p5.MediaElement objects are usually created
60438 * //by calling the createAudio(), createVideo(),
60439 * //and createCapture() functions.
60440 *
60441 * //In this example we create
60442 * //a new p5.MediaElement via createAudio().
60443 * ele = createAudio('assets/beat.mp3');
60444 *
60445 * //We'll set up our example so that
60446 * //when you click on the text,
60447 * //an alert box displays the MediaElement's
60448 * //src field.
60449 * textAlign(CENTER);
60450 * text('Click Me!', width / 2, height / 2);
60451 * }
60452 *
60453 * function mouseClicked() {
60454 * //here we test if the mouse is over the
60455 * //canvas element when it's clicked
60456 * if (mouseX >= 0 && mouseX <= width && mouseY >= 0 && mouseY <= height) {
60457 * //Show our p5.MediaElement's src field
60458 * alert(ele.src);
60459 * }
60460 * }
60461 * </code></div>
60462 */
60463 Object.defineProperty(self, 'src', {
60464 get: function get() {
60465 var firstChildSrc = self.elt.children[0].src;
60466 var srcVal = self.elt.src === window.location.href ? '' : self.elt.src;
60467 var ret = firstChildSrc === window.location.href ? srcVal : firstChildSrc;
60468 return ret;
60469 },
60470 set: function set(newValue) {
60471 for (var i = 0; i < self.elt.children.length; i++) {
60472 self.elt.removeChild(self.elt.children[i]);
60473 }
60474 var source = document.createElement('source');
60475 source.src = newValue;
60476 elt.appendChild(source);
60477 self.elt.src = newValue;
60478 self.modified = true;
60479 }
60480 });
60481
60482 // private _onended callback, set by the method: onended(callback)
60483 self._onended = function() {};
60484 self.elt.onended = function() {
60485 self._onended(self);
60486 };
60487 };
60488 _main.default.MediaElement.prototype = Object.create(
60489 _main.default.Element.prototype
60490 );
60491
60492 /**
60493 * Play an HTML5 media element.
60494 *
60495 * @method play
60496 * @chainable
60497 * @example
60498 * <div><code>
60499 * let ele;
60500 *
60501 * function setup() {
60502 * //p5.MediaElement objects are usually created
60503 * //by calling the createAudio(), createVideo(),
60504 * //and createCapture() functions.
60505 *
60506 * //In this example we create
60507 * //a new p5.MediaElement via createAudio().
60508 * ele = createAudio('assets/beat.mp3');
60509 *
60510 * background(250);
60511 * textAlign(CENTER);
60512 * text('Click to Play!', width / 2, height / 2);
60513 * }
60514 *
60515 * function mouseClicked() {
60516 * //here we test if the mouse is over the
60517 * //canvas element when it's clicked
60518 * if (mouseX >= 0 && mouseX <= width && mouseY >= 0 && mouseY <= height) {
60519 * //Here we call the play() function on
60520 * //the p5.MediaElement we created above.
60521 * //This will start the audio sample.
60522 * ele.play();
60523 *
60524 * background(200);
60525 * text('You clicked Play!', width / 2, height / 2);
60526 * }
60527 * }
60528 * </code></div>
60529 */
60530 _main.default.MediaElement.prototype.play = function() {
60531 if (this.elt.currentTime === this.elt.duration) {
60532 this.elt.currentTime = 0;
60533 }
60534 var promise;
60535 if (this.elt.readyState > 1) {
60536 promise = this.elt.play();
60537 } else {
60538 // in Chrome, playback cannot resume after being stopped and must reload
60539 this.elt.load();
60540 promise = this.elt.play();
60541 }
60542 if (promise && promise.catch) {
60543 promise.catch(function(e) {
60544 // if it's an autoplay failure error
60545 if (e.name === 'NotAllowedError') {
60546 _main.default._friendlyAutoplayError(this.src);
60547 } else {
60548 // any other kind of error
60549 console.error('Media play method encountered an unexpected error', e);
60550 }
60551 });
60552 }
60553 return this;
60554 };
60555
60556 /**
60557 * Stops an HTML5 media element (sets current time to zero).
60558 *
60559 * @method stop
60560 * @chainable
60561 * @example
60562 * <div><code>
60563 * //This example both starts
60564 * //and stops a sound sample
60565 * //when the user clicks the canvas
60566 *
60567 * //We will store the p5.MediaElement
60568 * //object in here
60569 * let ele;
60570 *
60571 * //while our audio is playing,
60572 * //this will be set to true
60573 * let sampleIsPlaying = false;
60574 *
60575 * function setup() {
60576 * //Here we create a p5.MediaElement object
60577 * //using the createAudio() function.
60578 * ele = createAudio('assets/beat.mp3');
60579 * background(200);
60580 * textAlign(CENTER);
60581 * text('Click to play!', width / 2, height / 2);
60582 * }
60583 *
60584 * function mouseClicked() {
60585 * //here we test if the mouse is over the
60586 * //canvas element when it's clicked
60587 * if (mouseX >= 0 && mouseX <= width && mouseY >= 0 && mouseY <= height) {
60588 * background(200);
60589 *
60590 * if (sampleIsPlaying) {
60591 * //if the sample is currently playing
60592 * //calling the stop() function on
60593 * //our p5.MediaElement will stop
60594 * //it and reset its current
60595 * //time to 0 (i.e. it will start
60596 * //at the beginning the next time
60597 * //you play it)
60598 * ele.stop();
60599 *
60600 * sampleIsPlaying = false;
60601 * text('Click to play!', width / 2, height / 2);
60602 * } else {
60603 * //loop our sound element until we
60604 * //call ele.stop() on it.
60605 * ele.loop();
60606 *
60607 * sampleIsPlaying = true;
60608 * text('Click to stop!', width / 2, height / 2);
60609 * }
60610 * }
60611 * }
60612 * </code></div>
60613 */
60614 _main.default.MediaElement.prototype.stop = function() {
60615 this.elt.pause();
60616 this.elt.currentTime = 0;
60617 return this;
60618 };
60619
60620 /**
60621 * Pauses an HTML5 media element.
60622 *
60623 * @method pause
60624 * @chainable
60625 * @example
60626 * <div><code>
60627 * //This example both starts
60628 * //and pauses a sound sample
60629 * //when the user clicks the canvas
60630 *
60631 * //We will store the p5.MediaElement
60632 * //object in here
60633 * let ele;
60634 *
60635 * //while our audio is playing,
60636 * //this will be set to true
60637 * let sampleIsPlaying = false;
60638 *
60639 * function setup() {
60640 * //Here we create a p5.MediaElement object
60641 * //using the createAudio() function.
60642 * ele = createAudio('assets/lucky_dragons.mp3');
60643 * background(200);
60644 * textAlign(CENTER);
60645 * text('Click to play!', width / 2, height / 2);
60646 * }
60647 *
60648 * function mouseClicked() {
60649 * //here we test if the mouse is over the
60650 * //canvas element when it's clicked
60651 * if (mouseX >= 0 && mouseX <= width && mouseY >= 0 && mouseY <= height) {
60652 * background(200);
60653 *
60654 * if (sampleIsPlaying) {
60655 * //Calling pause() on our
60656 * //p5.MediaElement will stop it
60657 * //playing, but when we call the
60658 * //loop() or play() functions
60659 * //the sample will start from
60660 * //where we paused it.
60661 * ele.pause();
60662 *
60663 * sampleIsPlaying = false;
60664 * text('Click to resume!', width / 2, height / 2);
60665 * } else {
60666 * //loop our sound element until we
60667 * //call ele.pause() on it.
60668 * ele.loop();
60669 *
60670 * sampleIsPlaying = true;
60671 * text('Click to pause!', width / 2, height / 2);
60672 * }
60673 * }
60674 * }
60675 * </code></div>
60676 */
60677 _main.default.MediaElement.prototype.pause = function() {
60678 this.elt.pause();
60679 return this;
60680 };
60681
60682 /**
60683 * Set 'loop' to true for an HTML5 media element, and starts playing.
60684 *
60685 * @method loop
60686 * @chainable
60687 * @example
60688 * <div><code>
60689 * //Clicking the canvas will loop
60690 * //the audio sample until the user
60691 * //clicks again to stop it
60692 *
60693 * //We will store the p5.MediaElement
60694 * //object in here
60695 * let ele;
60696 *
60697 * //while our audio is playing,
60698 * //this will be set to true
60699 * let sampleIsLooping = false;
60700 *
60701 * function setup() {
60702 * //Here we create a p5.MediaElement object
60703 * //using the createAudio() function.
60704 * ele = createAudio('assets/lucky_dragons.mp3');
60705 * background(200);
60706 * textAlign(CENTER);
60707 * text('Click to loop!', width / 2, height / 2);
60708 * }
60709 *
60710 * function mouseClicked() {
60711 * //here we test if the mouse is over the
60712 * //canvas element when it's clicked
60713 * if (mouseX >= 0 && mouseX <= width && mouseY >= 0 && mouseY <= height) {
60714 * background(200);
60715 *
60716 * if (!sampleIsLooping) {
60717 * //loop our sound element until we
60718 * //call ele.stop() on it.
60719 * ele.loop();
60720 *
60721 * sampleIsLooping = true;
60722 * text('Click to stop!', width / 2, height / 2);
60723 * } else {
60724 * ele.stop();
60725 *
60726 * sampleIsLooping = false;
60727 * text('Click to loop!', width / 2, height / 2);
60728 * }
60729 * }
60730 * }
60731 * </code></div>
60732 */
60733 _main.default.MediaElement.prototype.loop = function() {
60734 this.elt.setAttribute('loop', true);
60735 this.play();
60736 return this;
60737 };
60738 /**
60739 * Set 'loop' to false for an HTML5 media element. Element will stop
60740 * when it reaches the end.
60741 *
60742 * @method noLoop
60743 * @chainable
60744 * @example
60745 * <div><code>
60746 * //This example both starts
60747 * //and stops loop of sound sample
60748 * //when the user clicks the canvas
60749 *
60750 * //We will store the p5.MediaElement
60751 * //object in here
60752 * let ele;
60753 * //while our audio is playing,
60754 * //this will be set to true
60755 * let sampleIsPlaying = false;
60756 *
60757 * function setup() {
60758 * //Here we create a p5.MediaElement object
60759 * //using the createAudio() function.
60760 * ele = createAudio('assets/beat.mp3');
60761 * background(200);
60762 * textAlign(CENTER);
60763 * text('Click to play!', width / 2, height / 2);
60764 * }
60765 *
60766 * function mouseClicked() {
60767 * //here we test if the mouse is over the
60768 * //canvas element when it's clicked
60769 * if (mouseX >= 0 && mouseX <= width && mouseY >= 0 && mouseY <= height) {
60770 * background(200);
60771 *
60772 * if (sampleIsPlaying) {
60773 * ele.noLoop();
60774 * sampleIsPlaying = false;
60775 * text('No more Loops!', width / 2, height / 2);
60776 * } else {
60777 * ele.loop();
60778 * sampleIsPlaying = true;
60779 * text('Click to stop looping!', width / 2, height / 2);
60780 * }
60781 * }
60782 * }
60783 * </code></div>
60784 */
60785 _main.default.MediaElement.prototype.noLoop = function() {
60786 this.elt.removeAttribute('loop');
60787 return this;
60788 };
60789
60790 /**
60791 * Sets up logic to check that autoplay succeeded.
60792 *
60793 * @method setupAutoplayFailDetection
60794 * @private
60795 */
60796 _main.default.MediaElement.prototype._setupAutoplayFailDetection = function() {
60797 var _this = this;
60798 var timeout = setTimeout(function() {
60799 return _main.default._friendlyAutoplayError(_this.src);
60800 }, 500);
60801 this.elt.addEventListener(
60802 'play',
60803 function() {
60804 return clearTimeout(timeout);
60805 },
60806 {
60807 passive: true,
60808 once: true
60809 }
60810 );
60811 };
60812
60813 /**
60814 * Set HTML5 media element to autoplay or not. If no argument is specified, by
60815 * default it will autoplay.
60816 *
60817 * @method autoplay
60818 * @param {Boolean} shouldAutoplay whether the element should autoplay
60819 * @chainable
60820 * @example
60821 * <div><code>
60822 * let videoElement;
60823 * function setup() {
60824 * noCanvas();
60825 * videoElement = createVideo(['assets/small.mp4'], onVideoLoad);
60826 * }
60827 * function onVideoLoad() {
60828 * // The media will play as soon as it is loaded.
60829 * videoElement.autoplay();
60830 * videoElement.volume(0);
60831 * videoElement.size(100, 100);
60832 * }
60833 * </code></div>
60834 *
60835 * <div><code>
60836 * let videoElement;
60837 * function setup() {
60838 * noCanvas();
60839 * videoElement = createVideo(['assets/small.mp4'], onVideoLoad);
60840 * }
60841 * function onVideoLoad() {
60842 * // The media will not play untill some explicitly triggered.
60843 * videoElement.autoplay(false);
60844 * videoElement.volume(0);
60845 * videoElement.size(100, 100);
60846 * }
60847 *
60848 * function mouseClicked() {
60849 * videoElement.play();
60850 * }
60851 * </code></div>
60852 *
60853 * @alt
60854 * An example of a video element which autoplays after it is loaded.
60855 * An example of a video element which waits for a trigger for playing.
60856 */
60857
60858 _main.default.MediaElement.prototype.autoplay = function(val) {
60859 var _this2 = this;
60860 var oldVal = this.elt.getAttribute('autoplay');
60861 this.elt.setAttribute('autoplay', val);
60862 // if we turned on autoplay
60863 if (val && !oldVal) {
60864 // bind method to this scope
60865 var setupAutoplayFailDetection = function setupAutoplayFailDetection() {
60866 return _this2._setupAutoplayFailDetection();
60867 };
60868 // if media is ready to play, schedule check now
60869 if (this.elt.readyState === 4) {
60870 setupAutoplayFailDetection();
60871 } else {
60872 // otherwise, schedule check whenever it is ready
60873 this.elt.addEventListener('canplay', setupAutoplayFailDetection, {
60874 passive: true,
60875 once: true
60876 });
60877 }
60878 }
60879
60880 return this;
60881 };
60882
60883 /**
60884 * Sets volume for this HTML5 media element. If no argument is given,
60885 * returns the current volume.
60886 *
60887 * @method volume
60888 * @return {Number} current volume
60889 *
60890 * @example
60891 * <div><code>
60892 * let ele;
60893 * function setup() {
60894 * // p5.MediaElement objects are usually created
60895 * // by calling the createAudio(), createVideo(),
60896 * // and createCapture() functions.
60897 * // In this example we create
60898 * // a new p5.MediaElement via createAudio().
60899 * ele = createAudio('assets/lucky_dragons.mp3');
60900 * background(250);
60901 * textAlign(CENTER);
60902 * text('Click to Play!', width / 2, height / 2);
60903 * }
60904 * function mouseClicked() {
60905 * // Here we call the volume() function
60906 * // on the sound element to set its volume
60907 * // Volume must be between 0.0 and 1.0
60908 * ele.volume(0.2);
60909 * ele.play();
60910 * background(200);
60911 * text('You clicked Play!', width / 2, height / 2);
60912 * }
60913 * </code></div>
60914 * <div><code>
60915 * let audio;
60916 * let counter = 0;
60917 *
60918 * function loaded() {
60919 * audio.play();
60920 * }
60921 *
60922 * function setup() {
60923 * audio = createAudio('assets/lucky_dragons.mp3', loaded);
60924 * textAlign(CENTER);
60925 * }
60926 *
60927 * function draw() {
60928 * if (counter === 0) {
60929 * background(0, 255, 0);
60930 * text('volume(0.9)', width / 2, height / 2);
60931 * } else if (counter === 1) {
60932 * background(255, 255, 0);
60933 * text('volume(0.5)', width / 2, height / 2);
60934 * } else if (counter === 2) {
60935 * background(255, 0, 0);
60936 * text('volume(0.1)', width / 2, height / 2);
60937 * }
60938 * }
60939 *
60940 * function mousePressed() {
60941 * counter++;
60942 * if (counter === 0) {
60943 * audio.volume(0.9);
60944 * } else if (counter === 1) {
60945 * audio.volume(0.5);
60946 * } else if (counter === 2) {
60947 * audio.volume(0.1);
60948 * } else {
60949 * counter = 0;
60950 * audio.volume(0.9);
60951 * }
60952 * }
60953 * </code>
60954 * </div>
60955 */
60956 /**
60957 * @method volume
60958 * @param {Number} val volume between 0.0 and 1.0
60959 * @chainable
60960 */
60961 _main.default.MediaElement.prototype.volume = function(val) {
60962 if (typeof val === 'undefined') {
60963 return this.elt.volume;
60964 } else {
60965 this.elt.volume = val;
60966 }
60967 };
60968
60969 /**
60970 * If no arguments are given, returns the current playback speed of the
60971 * element. The speed parameter sets the speed where 2.0 will play the
60972 * element twice as fast, 0.5 will play at half the speed, and -1 will play
60973 * the element in normal speed in reverse.(Note that not all browsers support
60974 * backward playback and even if they do, playback might not be smooth.)
60975 *
60976 * @method speed
60977 * @return {Number} current playback speed of the element
60978 *
60979 * @example
60980 * <div class='norender notest'><code>
60981 * //Clicking the canvas will loop
60982 * //the audio sample until the user
60983 * //clicks again to stop it
60984 *
60985 * //We will store the p5.MediaElement
60986 * //object in here
60987 * let ele;
60988 * let button;
60989 *
60990 * function setup() {
60991 * createCanvas(710, 400);
60992 * //Here we create a p5.MediaElement object
60993 * //using the createAudio() function.
60994 * ele = createAudio('assets/beat.mp3');
60995 * ele.loop();
60996 * background(200);
60997 *
60998 * button = createButton('2x speed');
60999 * button.position(100, 68);
61000 * button.mousePressed(twice_speed);
61001 *
61002 * button = createButton('half speed');
61003 * button.position(200, 68);
61004 * button.mousePressed(half_speed);
61005 *
61006 * button = createButton('reverse play');
61007 * button.position(300, 68);
61008 * button.mousePressed(reverse_speed);
61009 *
61010 * button = createButton('STOP');
61011 * button.position(400, 68);
61012 * button.mousePressed(stop_song);
61013 *
61014 * button = createButton('PLAY!');
61015 * button.position(500, 68);
61016 * button.mousePressed(play_speed);
61017 * }
61018 *
61019 * function twice_speed() {
61020 * ele.speed(2);
61021 * }
61022 *
61023 * function half_speed() {
61024 * ele.speed(0.5);
61025 * }
61026 *
61027 * function reverse_speed() {
61028 * ele.speed(-1);
61029 * }
61030 *
61031 * function stop_song() {
61032 * ele.stop();
61033 * }
61034 *
61035 * function play_speed() {
61036 * ele.play();
61037 * }
61038 * </code></div>
61039 */
61040
61041 /**
61042 * @method speed
61043 * @param {Number} speed speed multiplier for element playback
61044 * @chainable
61045 */
61046 _main.default.MediaElement.prototype.speed = function(val) {
61047 if (typeof val === 'undefined') {
61048 return this.presetPlaybackRate || this.elt.playbackRate;
61049 } else {
61050 if (this.loadedmetadata) {
61051 this.elt.playbackRate = val;
61052 } else {
61053 this.presetPlaybackRate = val;
61054 }
61055 }
61056 };
61057
61058 /**
61059 * If no arguments are given, returns the current time of the element.
61060 * If an argument is given the current time of the element is set to it.
61061 *
61062 * @method time
61063 * @return {Number} current time (in seconds)
61064 *
61065 * @example
61066 * <div><code>
61067 * let ele;
61068 * let beginning = true;
61069 * function setup() {
61070 * //p5.MediaElement objects are usually created
61071 * //by calling the createAudio(), createVideo(),
61072 * //and createCapture() functions.
61073 *
61074 * //In this example we create
61075 * //a new p5.MediaElement via createAudio().
61076 * ele = createAudio('assets/lucky_dragons.mp3');
61077 * background(250);
61078 * textAlign(CENTER);
61079 * text('start at beginning', width / 2, height / 2);
61080 * }
61081 *
61082 * // this function fires with click anywhere
61083 * function mousePressed() {
61084 * if (beginning === true) {
61085 * // here we start the sound at the beginning
61086 * // time(0) is not necessary here
61087 * // as this produces the same result as
61088 * // play()
61089 * ele.play().time(0);
61090 * background(200);
61091 * text('jump 2 sec in', width / 2, height / 2);
61092 * beginning = false;
61093 * } else {
61094 * // here we jump 2 seconds into the sound
61095 * ele.play().time(2);
61096 * background(250);
61097 * text('start at beginning', width / 2, height / 2);
61098 * beginning = true;
61099 * }
61100 * }
61101 * </code></div>
61102 */
61103 /**
61104 * @method time
61105 * @param {Number} time time to jump to (in seconds)
61106 * @chainable
61107 */
61108 _main.default.MediaElement.prototype.time = function(val) {
61109 if (typeof val === 'undefined') {
61110 return this.elt.currentTime;
61111 } else {
61112 this.elt.currentTime = val;
61113 return this;
61114 }
61115 };
61116
61117 /**
61118 * Returns the duration of the HTML5 media element.
61119 *
61120 * @method duration
61121 * @return {Number} duration
61122 *
61123 * @example
61124 * <div><code>
61125 * let ele;
61126 * function setup() {
61127 * //p5.MediaElement objects are usually created
61128 * //by calling the createAudio(), createVideo(),
61129 * //and createCapture() functions.
61130 * //In this example we create
61131 * //a new p5.MediaElement via createAudio().
61132 * ele = createAudio('assets/doorbell.mp3');
61133 * background(250);
61134 * textAlign(CENTER);
61135 * text('Click to know the duration!', 10, 25, 70, 80);
61136 * }
61137 * function mouseClicked() {
61138 * ele.play();
61139 * background(200);
61140 * //ele.duration dislpays the duration
61141 * text(ele.duration() + ' seconds', width / 2, height / 2);
61142 * }
61143 * </code></div>
61144 */
61145 _main.default.MediaElement.prototype.duration = function() {
61146 return this.elt.duration;
61147 };
61148 _main.default.MediaElement.prototype.pixels = [];
61149 _main.default.MediaElement.prototype._ensureCanvas = function() {
61150 if (!this.canvas) {
61151 this.canvas = document.createElement('canvas');
61152 this.drawingContext = this.canvas.getContext('2d');
61153 this.setModified(true);
61154 }
61155 if (this.loadedmetadata) {
61156 // wait for metadata for w/h
61157 if (this.canvas.width !== this.elt.width) {
61158 this.canvas.width = this.elt.width;
61159 this.canvas.height = this.elt.height;
61160 this.width = this.canvas.width;
61161 this.height = this.canvas.height;
61162 }
61163
61164 this.drawingContext.drawImage(
61165 this.elt,
61166 0,
61167 0,
61168 this.canvas.width,
61169 this.canvas.height
61170 );
61171
61172 this.setModified(true);
61173 }
61174 };
61175 _main.default.MediaElement.prototype.loadPixels = function() {
61176 this._ensureCanvas();
61177 return _main.default.Renderer2D.prototype.loadPixels.apply(this, arguments);
61178 };
61179 _main.default.MediaElement.prototype.updatePixels = function(x, y, w, h) {
61180 if (this.loadedmetadata) {
61181 // wait for metadata
61182 this._ensureCanvas();
61183 _main.default.Renderer2D.prototype.updatePixels.call(this, x, y, w, h);
61184 }
61185 this.setModified(true);
61186 return this;
61187 };
61188 _main.default.MediaElement.prototype.get = function() {
61189 this._ensureCanvas();
61190 return _main.default.Renderer2D.prototype.get.apply(this, arguments);
61191 };
61192 _main.default.MediaElement.prototype._getPixel = function() {
61193 this.loadPixels();
61194 return _main.default.Renderer2D.prototype._getPixel.apply(this, arguments);
61195 };
61196
61197 _main.default.MediaElement.prototype.set = function(x, y, imgOrCol) {
61198 if (this.loadedmetadata) {
61199 // wait for metadata
61200 this._ensureCanvas();
61201 _main.default.Renderer2D.prototype.set.call(this, x, y, imgOrCol);
61202 this.setModified(true);
61203 }
61204 };
61205 _main.default.MediaElement.prototype.copy = function() {
61206 this._ensureCanvas();
61207 _main.default.prototype.copy.apply(this, arguments);
61208 };
61209 _main.default.MediaElement.prototype.mask = function() {
61210 this.loadPixels();
61211 this.setModified(true);
61212 _main.default.Image.prototype.mask.apply(this, arguments);
61213 };
61214 /**
61215 * helper method for web GL mode to figure out if the element
61216 * has been modified and might need to be re-uploaded to texture
61217 * memory between frames.
61218 * @method isModified
61219 * @private
61220 * @return {boolean} a boolean indicating whether or not the
61221 * image has been updated or modified since last texture upload.
61222 */
61223 _main.default.MediaElement.prototype.isModified = function() {
61224 return this._modified;
61225 };
61226 /**
61227 * helper method for web GL mode to indicate that an element has been
61228 * changed or unchanged since last upload. gl texture upload will
61229 * set this value to false after uploading the texture; or might set
61230 * it to true if metadata has become available but there is no actual
61231 * texture data available yet..
61232 * @method setModified
61233 * @param {boolean} val sets whether or not the element has been
61234 * modified.
61235 * @private
61236 */
61237 _main.default.MediaElement.prototype.setModified = function(value) {
61238 this._modified = value;
61239 };
61240 /**
61241 * Schedule an event to be called when the audio or video
61242 * element reaches the end. If the element is looping,
61243 * this will not be called. The element is passed in
61244 * as the argument to the onended callback.
61245 *
61246 * @method onended
61247 * @param {Function} callback function to call when the
61248 * soundfile has ended. The
61249 * media element will be passed
61250 * in as the argument to the
61251 * callback.
61252 * @chainable
61253 * @example
61254 * <div><code>
61255 * function setup() {
61256 * let audioEl = createAudio('assets/beat.mp3');
61257 * audioEl.showControls();
61258 * audioEl.onended(sayDone);
61259 * }
61260 *
61261 * function sayDone(elt) {
61262 * alert('done playing ' + elt.src);
61263 * }
61264 * </code></div>
61265 */
61266 _main.default.MediaElement.prototype.onended = function(callback) {
61267 this._onended = callback;
61268 return this;
61269 };
61270
61271 /*** CONNECT TO WEB AUDIO API / p5.sound.js ***/
61272
61273 /**
61274 * Send the audio output of this element to a specified audioNode or
61275 * p5.sound object. If no element is provided, connects to p5's main
61276 * output. That connection is established when this method is first called.
61277 * All connections are removed by the .disconnect() method.
61278 *
61279 * This method is meant to be used with the p5.sound.js addon library.
61280 *
61281 * @method connect
61282 * @param {AudioNode|Object} audioNode AudioNode from the Web Audio API,
61283 * or an object from the p5.sound library
61284 */
61285 _main.default.MediaElement.prototype.connect = function(obj) {
61286 var audioContext, mainOutput;
61287
61288 // if p5.sound exists, same audio context
61289 if (typeof _main.default.prototype.getAudioContext === 'function') {
61290 audioContext = _main.default.prototype.getAudioContext();
61291 mainOutput = _main.default.soundOut.input;
61292 } else {
61293 try {
61294 audioContext = obj.context;
61295 mainOutput = audioContext.destination;
61296 } catch (e) {
61297 throw 'connect() is meant to be used with Web Audio API or p5.sound.js';
61298 }
61299 }
61300
61301 // create a Web Audio MediaElementAudioSourceNode if none already exists
61302 if (!this.audioSourceNode) {
61303 this.audioSourceNode = audioContext.createMediaElementSource(this.elt);
61304
61305 // connect to main output when this method is first called
61306 this.audioSourceNode.connect(mainOutput);
61307 }
61308
61309 // connect to object if provided
61310 if (obj) {
61311 if (obj.input) {
61312 this.audioSourceNode.connect(obj.input);
61313 } else {
61314 this.audioSourceNode.connect(obj);
61315 }
61316 } else {
61317 // otherwise connect to main output of p5.sound / AudioContext
61318 this.audioSourceNode.connect(mainOutput);
61319 }
61320 };
61321
61322 /**
61323 * Disconnect all Web Audio routing, including to main output.
61324 * This is useful if you want to re-route the output through
61325 * audio effects, for example.
61326 *
61327 * @method disconnect
61328 */
61329 _main.default.MediaElement.prototype.disconnect = function() {
61330 if (this.audioSourceNode) {
61331 this.audioSourceNode.disconnect();
61332 } else {
61333 throw 'nothing to disconnect';
61334 }
61335 };
61336
61337 /*** SHOW / HIDE CONTROLS ***/
61338
61339 /**
61340 * Show the default MediaElement controls, as determined by the web browser.
61341 *
61342 * @method showControls
61343 * @example
61344 * <div><code>
61345 * let ele;
61346 * function setup() {
61347 * //p5.MediaElement objects are usually created
61348 * //by calling the createAudio(), createVideo(),
61349 * //and createCapture() functions.
61350 * //In this example we create
61351 * //a new p5.MediaElement via createAudio()
61352 * ele = createAudio('assets/lucky_dragons.mp3');
61353 * background(200);
61354 * textAlign(CENTER);
61355 * text('Click to Show Controls!', 10, 25, 70, 80);
61356 * }
61357 * function mousePressed() {
61358 * ele.showControls();
61359 * background(200);
61360 * text('Controls Shown', width / 2, height / 2);
61361 * }
61362 * </code></div>
61363 */
61364 _main.default.MediaElement.prototype.showControls = function() {
61365 // must set style for the element to show on the page
61366 this.elt.style['text-align'] = 'inherit';
61367 this.elt.controls = true;
61368 };
61369
61370 /**
61371 * Hide the default mediaElement controls.
61372 * @method hideControls
61373 * @example
61374 * <div><code>
61375 * let ele;
61376 * function setup() {
61377 * //p5.MediaElement objects are usually created
61378 * //by calling the createAudio(), createVideo(),
61379 * //and createCapture() functions.
61380 * //In this example we create
61381 * //a new p5.MediaElement via createAudio()
61382 * ele = createAudio('assets/lucky_dragons.mp3');
61383 * ele.showControls();
61384 * background(200);
61385 * textAlign(CENTER);
61386 * text('Click to hide Controls!', 10, 25, 70, 80);
61387 * }
61388 * function mousePressed() {
61389 * ele.hideControls();
61390 * background(200);
61391 * text('Controls hidden', width / 2, height / 2);
61392 * }
61393 * </code></div>
61394 */
61395 _main.default.MediaElement.prototype.hideControls = function() {
61396 this.elt.controls = false;
61397 };
61398
61399 /*** SCHEDULE EVENTS ***/
61400
61401 // Cue inspired by JavaScript setTimeout, and the
61402 // Tone.js Transport Timeline Event, MIT License Yotam Mann 2015 tonejs.org
61403 var Cue = function Cue(callback, time, id, val) {
61404 this.callback = callback;
61405 this.time = time;
61406 this.id = id;
61407 this.val = val;
61408 };
61409
61410 /**
61411 * Schedule events to trigger every time a MediaElement
61412 * (audio/video) reaches a playback cue point.
61413 *
61414 * Accepts a callback function, a time (in seconds) at which to trigger
61415 * the callback, and an optional parameter for the callback.
61416 *
61417 * Time will be passed as the first parameter to the callback function,
61418 * and param will be the second parameter.
61419 *
61420 * @method addCue
61421 * @param {Number} time Time in seconds, relative to this media
61422 * element's playback. For example, to trigger
61423 * an event every time playback reaches two
61424 * seconds, pass in the number 2. This will be
61425 * passed as the first parameter to
61426 * the callback function.
61427 * @param {Function} callback Name of a function that will be
61428 * called at the given time. The callback will
61429 * receive time and (optionally) param as its
61430 * two parameters.
61431 * @param {Object} [value] An object to be passed as the
61432 * second parameter to the
61433 * callback function.
61434 * @return {Number} id ID of this cue,
61435 * useful for removeCue(id)
61436 * @example
61437 * <div><code>
61438 * //
61439 * //
61440 * function setup() {
61441 * noCanvas();
61442 *
61443 * let audioEl = createAudio('assets/beat.mp3');
61444 * audioEl.showControls();
61445 *
61446 * // schedule three calls to changeBackground
61447 * audioEl.addCue(0.5, changeBackground, color(255, 0, 0));
61448 * audioEl.addCue(1.0, changeBackground, color(0, 255, 0));
61449 * audioEl.addCue(2.5, changeBackground, color(0, 0, 255));
61450 * audioEl.addCue(3.0, changeBackground, color(0, 255, 255));
61451 * audioEl.addCue(4.2, changeBackground, color(255, 255, 0));
61452 * audioEl.addCue(5.0, changeBackground, color(255, 255, 0));
61453 * }
61454 *
61455 * function changeBackground(val) {
61456 * background(val);
61457 * }
61458 * </code></div>
61459 */
61460 _main.default.MediaElement.prototype.addCue = function(time, callback, val) {
61461 var id = this._cueIDCounter++;
61462
61463 var cue = new Cue(callback, time, id, val);
61464 this._cues.push(cue);
61465
61466 if (!this.elt.ontimeupdate) {
61467 this.elt.ontimeupdate = this._onTimeUpdate.bind(this);
61468 }
61469
61470 return id;
61471 };
61472
61473 /**
61474 * Remove a callback based on its ID. The ID is returned by the
61475 * addCue method.
61476 * @method removeCue
61477 * @param {Number} id ID of the cue, as returned by addCue
61478 * @example
61479 * <div><code>
61480 * let audioEl, id1, id2;
61481 * function setup() {
61482 * background(255, 255, 255);
61483 * audioEl = createAudio('assets/beat.mp3');
61484 * audioEl.showControls();
61485 * // schedule five calls to changeBackground
61486 * id1 = audioEl.addCue(0.5, changeBackground, color(255, 0, 0));
61487 * audioEl.addCue(1.0, changeBackground, color(0, 255, 0));
61488 * audioEl.addCue(2.5, changeBackground, color(0, 0, 255));
61489 * audioEl.addCue(3.0, changeBackground, color(0, 255, 255));
61490 * id2 = audioEl.addCue(4.2, changeBackground, color(255, 255, 0));
61491 * text('Click to remove first and last Cue!', 10, 25, 70, 80);
61492 * }
61493 * function mousePressed() {
61494 * audioEl.removeCue(id1);
61495 * audioEl.removeCue(id2);
61496 * }
61497 * function changeBackground(val) {
61498 * background(val);
61499 * }
61500 * </code></div>
61501 */
61502 _main.default.MediaElement.prototype.removeCue = function(id) {
61503 for (var i = 0; i < this._cues.length; i++) {
61504 if (this._cues[i].id === id) {
61505 console.log(id);
61506 this._cues.splice(i, 1);
61507 }
61508 }
61509
61510 if (this._cues.length === 0) {
61511 this.elt.ontimeupdate = null;
61512 }
61513 };
61514
61515 /**
61516 * Remove all of the callbacks that had originally been scheduled
61517 * via the addCue method.
61518 * @method clearCues
61519 * @param {Number} id ID of the cue, as returned by addCue
61520 * @example
61521 * <div><code>
61522 * let audioEl;
61523 * function setup() {
61524 * background(255, 255, 255);
61525 * audioEl = createAudio('assets/beat.mp3');
61526 * //Show the default MediaElement controls, as determined by the web browser
61527 * audioEl.showControls();
61528 * // schedule calls to changeBackground
61529 * background(200);
61530 * text('Click to change Cue!', 10, 25, 70, 80);
61531 * audioEl.addCue(0.5, changeBackground, color(255, 0, 0));
61532 * audioEl.addCue(1.0, changeBackground, color(0, 255, 0));
61533 * audioEl.addCue(2.5, changeBackground, color(0, 0, 255));
61534 * audioEl.addCue(3.0, changeBackground, color(0, 255, 255));
61535 * audioEl.addCue(4.2, changeBackground, color(255, 255, 0));
61536 * }
61537 * function mousePressed() {
61538 * // here we clear the scheduled callbacks
61539 * audioEl.clearCues();
61540 * // then we add some more callbacks
61541 * audioEl.addCue(1, changeBackground, color(2, 2, 2));
61542 * audioEl.addCue(3, changeBackground, color(255, 255, 0));
61543 * }
61544 * function changeBackground(val) {
61545 * background(val);
61546 * }
61547 * </code></div>
61548 */
61549 _main.default.MediaElement.prototype.clearCues = function() {
61550 this._cues = [];
61551 this.elt.ontimeupdate = null;
61552 };
61553
61554 // private method that checks for cues to be fired if events
61555 // have been scheduled using addCue(callback, time).
61556 _main.default.MediaElement.prototype._onTimeUpdate = function() {
61557 var playbackTime = this.time();
61558
61559 for (var i = 0; i < this._cues.length; i++) {
61560 var callbackTime = this._cues[i].time;
61561 var val = this._cues[i].val;
61562
61563 if (this._prevTime < callbackTime && callbackTime <= playbackTime) {
61564 // pass the scheduled callbackTime as parameter to the callback
61565 this._cues[i].callback(val);
61566 }
61567 }
61568
61569 this._prevTime = playbackTime;
61570 };
61571
61572 /**
61573 * Base class for a file.
61574 * Used for Element.drop and createFileInput.
61575 *
61576 * @class p5.File
61577 * @constructor
61578 * @param {File} file File that is wrapped
61579 */
61580 _main.default.File = function(file, pInst) {
61581 /**
61582 * Underlying File object. All normal File methods can be called on this.
61583 *
61584 * @property file
61585 */
61586 this.file = file;
61587
61588 this._pInst = pInst;
61589
61590 // Splitting out the file type into two components
61591 // This makes determining if image or text etc simpler
61592 var typeList = file.type.split('/');
61593 /**
61594 * File type (image, text, etc.)
61595 *
61596 * @property type
61597 */
61598 this.type = typeList[0];
61599 /**
61600 * File subtype (usually the file extension jpg, png, xml, etc.)
61601 *
61602 * @property subtype
61603 */
61604 this.subtype = typeList[1];
61605 /**
61606 * File name
61607 *
61608 * @property name
61609 */
61610 this.name = file.name;
61611 /**
61612 * File size
61613 *
61614 * @property size
61615 */
61616 this.size = file.size;
61617
61618 /**
61619 * URL string containing either image data, the text contents of the file or
61620 * a parsed object if file is JSON and p5.XML if XML
61621 *
61622 * @property data
61623 */
61624 this.data = undefined;
61625 };
61626
61627 _main.default.File._createLoader = function(theFile, callback) {
61628 var reader = new FileReader();
61629 reader.onload = function(e) {
61630 var p5file = new _main.default.File(theFile);
61631 if (p5file.file.type === 'application/json') {
61632 // Parse JSON and store the result in data
61633 p5file.data = JSON.parse(e.target.result);
61634 } else if (p5file.file.type === 'text/xml') {
61635 // Parse XML, wrap it in p5.XML and store the result in data
61636 var parser = new DOMParser();
61637 var xml = parser.parseFromString(e.target.result, 'text/xml');
61638 p5file.data = new _main.default.XML(xml.documentElement);
61639 } else {
61640 p5file.data = e.target.result;
61641 }
61642 callback(p5file);
61643 };
61644 return reader;
61645 };
61646
61647 _main.default.File._load = function(f, callback) {
61648 // Text or data?
61649 // This should likely be improved
61650 if (/^text\//.test(f.type) || f.type === 'application/json') {
61651 _main.default.File._createLoader(f, callback).readAsText(f);
61652 } else if (!/^(video|audio)\//.test(f.type)) {
61653 _main.default.File._createLoader(f, callback).readAsDataURL(f);
61654 } else {
61655 var file = new _main.default.File(f);
61656 file.data = URL.createObjectURL(f);
61657 callback(file);
61658 }
61659 };
61660 var _default = _main.default;
61661 exports.default = _default;
61662 },
61663 { '../core/main': 54 }
61664 ],
61665 71: [
61666 function(_dereq_, module, exports) {
61667 'use strict';
61668 function _typeof(obj) {
61669 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
61670 _typeof = function _typeof(obj) {
61671 return typeof obj;
61672 };
61673 } else {
61674 _typeof = function _typeof(obj) {
61675 return obj &&
61676 typeof Symbol === 'function' &&
61677 obj.constructor === Symbol &&
61678 obj !== Symbol.prototype
61679 ? 'symbol'
61680 : typeof obj;
61681 };
61682 }
61683 return _typeof(obj);
61684 }
61685 Object.defineProperty(exports, '__esModule', { value: true });
61686 exports.default = void 0;
61687
61688 var _main = _interopRequireDefault(_dereq_('../core/main'));
61689 var constants = _interopRequireWildcard(_dereq_('../core/constants'));
61690 function _getRequireWildcardCache() {
61691 if (typeof WeakMap !== 'function') return null;
61692 var cache = new WeakMap();
61693 _getRequireWildcardCache = function _getRequireWildcardCache() {
61694 return cache;
61695 };
61696 return cache;
61697 }
61698 function _interopRequireWildcard(obj) {
61699 if (obj && obj.__esModule) {
61700 return obj;
61701 }
61702 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) {
61703 return { default: obj };
61704 }
61705 var cache = _getRequireWildcardCache();
61706 if (cache && cache.has(obj)) {
61707 return cache.get(obj);
61708 }
61709 var newObj = {};
61710 var hasPropertyDescriptor =
61711 Object.defineProperty && Object.getOwnPropertyDescriptor;
61712 for (var key in obj) {
61713 if (Object.prototype.hasOwnProperty.call(obj, key)) {
61714 var desc = hasPropertyDescriptor
61715 ? Object.getOwnPropertyDescriptor(obj, key)
61716 : null;
61717 if (desc && (desc.get || desc.set)) {
61718 Object.defineProperty(newObj, key, desc);
61719 } else {
61720 newObj[key] = obj[key];
61721 }
61722 }
61723 }
61724 newObj.default = obj;
61725 if (cache) {
61726 cache.set(obj, newObj);
61727 }
61728 return newObj;
61729 }
61730 function _interopRequireDefault(obj) {
61731 return obj && obj.__esModule ? obj : { default: obj };
61732 }
61733 /**
61734 * @module Events
61735 * @submodule Acceleration
61736 * @for p5
61737 * @requires core
61738 */ /**
61739 * The system variable deviceOrientation always contains the orientation of
61740 * the device. The value of this variable will either be set 'landscape'
61741 * or 'portrait'. If no data is available it will be set to 'undefined'.
61742 * either LANDSCAPE or PORTRAIT.
61743 *
61744 * @property {Constant} deviceOrientation
61745 * @readOnly
61746 */ _main.default.prototype.deviceOrientation =
61747 window.innerWidth / window.innerHeight > 1.0 ? 'landscape' : 'portrait';
61748 /**
61749 * The system variable accelerationX always contains the acceleration of the
61750 * device along the x axis. Value is represented as meters per second squared.
61751 *
61752 * @property {Number} accelerationX
61753 * @readOnly
61754 * @example
61755 * <div>
61756 * <code>
61757 * // Move a touchscreen device to register
61758 * // acceleration changes.
61759 * function draw() {
61760 * background(220, 50);
61761 * fill('magenta');
61762 * ellipse(width / 2, height / 2, accelerationX);
61763 * }
61764 * </code>
61765 * </div>
61766 * @alt
61767 * Magnitude of device acceleration is displayed as ellipse size
61768 */
61769 _main.default.prototype.accelerationX = 0;
61770
61771 /**
61772 * The system variable accelerationY always contains the acceleration of the
61773 * device along the y axis. Value is represented as meters per second squared.
61774 *
61775 * @property {Number} accelerationY
61776 * @readOnly
61777 * @example
61778 * <div>
61779 * <code>
61780 * // Move a touchscreen device to register
61781 * // acceleration changes.
61782 * function draw() {
61783 * background(220, 50);
61784 * fill('magenta');
61785 * ellipse(width / 2, height / 2, accelerationY);
61786 * }
61787 * </code>
61788 * </div>
61789 * @alt
61790 * Magnitude of device acceleration is displayed as ellipse size
61791 */
61792 _main.default.prototype.accelerationY = 0;
61793
61794 /**
61795 * The system variable accelerationZ always contains the acceleration of the
61796 * device along the z axis. Value is represented as meters per second squared.
61797 *
61798 * @property {Number} accelerationZ
61799 * @readOnly
61800 *
61801 * @example
61802 * <div>
61803 * <code>
61804 * // Move a touchscreen device to register
61805 * // acceleration changes.
61806 * function draw() {
61807 * background(220, 50);
61808 * fill('magenta');
61809 * ellipse(width / 2, height / 2, accelerationZ);
61810 * }
61811 * </code>
61812 * </div>
61813 *
61814 * @alt
61815 * Magnitude of device acceleration is displayed as ellipse size
61816 */
61817 _main.default.prototype.accelerationZ = 0;
61818
61819 /**
61820 * The system variable pAccelerationX always contains the acceleration of the
61821 * device along the x axis in the frame previous to the current frame. Value
61822 * is represented as meters per second squared.
61823 *
61824 * @property {Number} pAccelerationX
61825 * @readOnly
61826 */
61827 _main.default.prototype.pAccelerationX = 0;
61828
61829 /**
61830 * The system variable pAccelerationY always contains the acceleration of the
61831 * device along the y axis in the frame previous to the current frame. Value
61832 * is represented as meters per second squared.
61833 *
61834 * @property {Number} pAccelerationY
61835 * @readOnly
61836 */
61837 _main.default.prototype.pAccelerationY = 0;
61838
61839 /**
61840 * The system variable pAccelerationZ always contains the acceleration of the
61841 * device along the z axis in the frame previous to the current frame. Value
61842 * is represented as meters per second squared.
61843 *
61844 * @property {Number} pAccelerationZ
61845 * @readOnly
61846 */
61847 _main.default.prototype.pAccelerationZ = 0;
61848
61849 /**
61850 * _updatePAccelerations updates the pAcceleration values
61851 *
61852 * @private
61853 */
61854 _main.default.prototype._updatePAccelerations = function() {
61855 this._setProperty('pAccelerationX', this.accelerationX);
61856 this._setProperty('pAccelerationY', this.accelerationY);
61857 this._setProperty('pAccelerationZ', this.accelerationZ);
61858 };
61859
61860 /**
61861 * The system variable rotationX always contains the rotation of the
61862 * device along the x axis. If the sketch <a href="#/p5/angleMode">
61863 * angleMode()</a> is set to DEGREES, the value will be -180 to 180. If
61864 * it is set to RADIANS, the value will be -PI to PI.
61865 *
61866 * Note: The order the rotations are called is important, ie. if used
61867 * together, it must be called in the order Z-X-Y or there might be
61868 * unexpected behaviour.
61869 *
61870 * @property {Number} rotationX
61871 * @readOnly
61872 * @example
61873 * <div>
61874 * <code>
61875 * function setup() {
61876 * createCanvas(100, 100, WEBGL);
61877 * }
61878 *
61879 * function draw() {
61880 * background(200);
61881 * //rotateZ(radians(rotationZ));
61882 * rotateX(radians(rotationX));
61883 * //rotateY(radians(rotationY));
61884 * box(200, 200, 200);
61885 * }
61886 * </code>
61887 * </div>
61888 * @alt
61889 * red horizontal line right, green vertical line bottom. black background.
61890 */
61891 _main.default.prototype.rotationX = 0;
61892
61893 /**
61894 * The system variable rotationY always contains the rotation of the
61895 * device along the y axis. If the sketch <a href="#/p5/angleMode">
61896 * angleMode()</a> is set to DEGREES, the value will be -90 to 90. If
61897 * it is set to RADIANS, the value will be -PI/2 to PI/2.
61898 *
61899 * Note: The order the rotations are called is important, ie. if used
61900 * together, it must be called in the order Z-X-Y or there might be
61901 * unexpected behaviour.
61902 *
61903 * @property {Number} rotationY
61904 * @readOnly
61905 * @example
61906 * <div>
61907 * <code>
61908 * function setup() {
61909 * createCanvas(100, 100, WEBGL);
61910 * }
61911 *
61912 * function draw() {
61913 * background(200);
61914 * //rotateZ(radians(rotationZ));
61915 * //rotateX(radians(rotationX));
61916 * rotateY(radians(rotationY));
61917 * box(200, 200, 200);
61918 * }
61919 * </code>
61920 * </div>
61921 * @alt
61922 * red horizontal line right, green vertical line bottom. black background.
61923 */
61924 _main.default.prototype.rotationY = 0;
61925
61926 /**
61927 * The system variable rotationZ always contains the rotation of the
61928 * device along the z axis. If the sketch <a href="#/p5/angleMode">
61929 * angleMode()</a> is set to DEGREES, the value will be 0 to 360. If
61930 * it is set to RADIANS, the value will be 0 to 2*PI.
61931 *
61932 * Unlike rotationX and rotationY, this variable is available for devices
61933 * with a built-in compass only.
61934 *
61935 * Note: The order the rotations are called is important, ie. if used
61936 * together, it must be called in the order Z-X-Y or there might be
61937 * unexpected behaviour.
61938 *
61939 * @example
61940 * <div>
61941 * <code>
61942 * function setup() {
61943 * createCanvas(100, 100, WEBGL);
61944 * }
61945 *
61946 * function draw() {
61947 * background(200);
61948 * rotateZ(radians(rotationZ));
61949 * //rotateX(radians(rotationX));
61950 * //rotateY(radians(rotationY));
61951 * box(200, 200, 200);
61952 * }
61953 * </code>
61954 * </div>
61955 *
61956 * @property {Number} rotationZ
61957 * @readOnly
61958 *
61959 * @alt
61960 * red horizontal line right, green vertical line bottom. black background.
61961 */
61962 _main.default.prototype.rotationZ = 0;
61963
61964 /**
61965 * The system variable pRotationX always contains the rotation of the
61966 * device along the x axis in the frame previous to the current frame.
61967 * If the sketch <a href="#/p5/angleMode"> angleMode()</a> is set to DEGREES,
61968 * the value will be -180 to 180. If it is set to RADIANS, the value will
61969 * be -PI to PI.
61970 *
61971 * pRotationX can also be used with rotationX to determine the rotate
61972 * direction of the device along the X-axis.
61973 * @example
61974 * <div class='norender'>
61975 * <code>
61976 * // A simple if statement looking at whether
61977 * // rotationX - pRotationX < 0 is true or not will be
61978 * // sufficient for determining the rotate direction
61979 * // in most cases.
61980 *
61981 * // Some extra logic is needed to account for cases where
61982 * // the angles wrap around.
61983 * let rotateDirection = 'clockwise';
61984 *
61985 * // Simple range conversion to make things simpler.
61986 * // This is not absolutely necessary but the logic
61987 * // will be different in that case.
61988 *
61989 * let rX = rotationX + 180;
61990 * let pRX = pRotationX + 180;
61991 *
61992 * if ((rX - pRX > 0 && rX - pRX < 270) || rX - pRX < -270) {
61993 * rotateDirection = 'clockwise';
61994 * } else if (rX - pRX < 0 || rX - pRX > 270) {
61995 * rotateDirection = 'counter-clockwise';
61996 * }
61997 *
61998 * print(rotateDirection);
61999 * </code>
62000 * </div>
62001 *
62002 * @alt
62003 * no image to display.
62004 *
62005 * @property {Number} pRotationX
62006 * @readOnly
62007 */
62008 _main.default.prototype.pRotationX = 0;
62009
62010 /**
62011 * The system variable pRotationY always contains the rotation of the
62012 * device along the y axis in the frame previous to the current frame.
62013 * If the sketch <a href="#/p5/angleMode"> angleMode()</a> is set to DEGREES,
62014 * the value will be -90 to 90. If it is set to RADIANS, the value will
62015 * be -PI/2 to PI/2.
62016 *
62017 * pRotationY can also be used with rotationY to determine the rotate
62018 * direction of the device along the Y-axis.
62019 * @example
62020 * <div class='norender'>
62021 * <code>
62022 * // A simple if statement looking at whether
62023 * // rotationY - pRotationY < 0 is true or not will be
62024 * // sufficient for determining the rotate direction
62025 * // in most cases.
62026 *
62027 * // Some extra logic is needed to account for cases where
62028 * // the angles wrap around.
62029 * let rotateDirection = 'clockwise';
62030 *
62031 * // Simple range conversion to make things simpler.
62032 * // This is not absolutely necessary but the logic
62033 * // will be different in that case.
62034 *
62035 * let rY = rotationY + 180;
62036 * let pRY = pRotationY + 180;
62037 *
62038 * if ((rY - pRY > 0 && rY - pRY < 270) || rY - pRY < -270) {
62039 * rotateDirection = 'clockwise';
62040 * } else if (rY - pRY < 0 || rY - pRY > 270) {
62041 * rotateDirection = 'counter-clockwise';
62042 * }
62043 * print(rotateDirection);
62044 * </code>
62045 * </div>
62046 *
62047 * @alt
62048 * no image to display.
62049 *
62050 * @property {Number} pRotationY
62051 * @readOnly
62052 */
62053 _main.default.prototype.pRotationY = 0;
62054
62055 /**
62056 * The system variable pRotationZ always contains the rotation of the
62057 * device along the z axis in the frame previous to the current frame.
62058 * If the sketch <a href="#/p5/angleMode"> angleMode()</a> is set to DEGREES,
62059 * the value will be 0 to 360. If it is set to RADIANS, the value will
62060 * be 0 to 2*PI.
62061 *
62062 * pRotationZ can also be used with rotationZ to determine the rotate
62063 * direction of the device along the Z-axis.
62064 * @example
62065 * <div class='norender'>
62066 * <code>
62067 * // A simple if statement looking at whether
62068 * // rotationZ - pRotationZ < 0 is true or not will be
62069 * // sufficient for determining the rotate direction
62070 * // in most cases.
62071 *
62072 * // Some extra logic is needed to account for cases where
62073 * // the angles wrap around.
62074 * let rotateDirection = 'clockwise';
62075 *
62076 * if (
62077 * (rotationZ - pRotationZ > 0 && rotationZ - pRotationZ < 270) ||
62078 * rotationZ - pRotationZ < -270
62079 * ) {
62080 * rotateDirection = 'clockwise';
62081 * } else if (rotationZ - pRotationZ < 0 || rotationZ - pRotationZ > 270) {
62082 * rotateDirection = 'counter-clockwise';
62083 * }
62084 * print(rotateDirection);
62085 * </code>
62086 * </div>
62087 *
62088 * @alt
62089 * no image to display.
62090 *
62091 * @property {Number} pRotationZ
62092 * @readOnly
62093 */
62094 _main.default.prototype.pRotationZ = 0;
62095
62096 var startAngleX = 0;
62097 var startAngleY = 0;
62098 var startAngleZ = 0;
62099
62100 var rotateDirectionX = 'clockwise';
62101 var rotateDirectionY = 'clockwise';
62102 var rotateDirectionZ = 'clockwise';
62103
62104 _main.default.prototype.pRotateDirectionX = undefined;
62105 _main.default.prototype.pRotateDirectionY = undefined;
62106 _main.default.prototype.pRotateDirectionZ = undefined;
62107
62108 _main.default.prototype._updatePRotations = function() {
62109 this._setProperty('pRotationX', this.rotationX);
62110 this._setProperty('pRotationY', this.rotationY);
62111 this._setProperty('pRotationZ', this.rotationZ);
62112 };
62113
62114 /**
62115 * When a device is rotated, the axis that triggers the <a href="#/p5/deviceTurned">deviceTurned()</a>
62116 * method is stored in the turnAxis variable. The turnAxis variable is only defined within
62117 * the scope of deviceTurned().
62118 * @property {String} turnAxis
62119 * @readOnly
62120 * @example
62121 * <div>
62122 * <code>
62123 * // Run this example on a mobile device
62124 * // Rotate the device by 90 degrees in the
62125 * // X-axis to change the value.
62126 *
62127 * let value = 0;
62128 * function draw() {
62129 * fill(value);
62130 * rect(25, 25, 50, 50);
62131 * }
62132 * function deviceTurned() {
62133 * if (turnAxis === 'X') {
62134 * if (value === 0) {
62135 * value = 255;
62136 * } else if (value === 255) {
62137 * value = 0;
62138 * }
62139 * }
62140 * }
62141 * </code>
62142 * </div>
62143 *
62144 * @alt
62145 * 50x50 black rect in center of canvas. turns white on mobile when device turns
62146 * 50x50 black rect in center of canvas. turns white on mobile when x-axis turns
62147 */
62148 _main.default.prototype.turnAxis = undefined;
62149
62150 var move_threshold = 0.5;
62151 var shake_threshold = 30;
62152
62153 /**
62154 * The <a href="#/p5/setMoveThreshold">setMoveThreshold()</a> function is used to set the movement threshold for
62155 * the <a href="#/p5/deviceMoved">deviceMoved()</a> function. The default threshold is set to 0.5.
62156 *
62157 * @method setMoveThreshold
62158 * @param {number} value The threshold value
62159 * @example
62160 * <div class="norender">
62161 * <code>
62162 * // Run this example on a mobile device
62163 * // You will need to move the device incrementally further
62164 * // the closer the square's color gets to white in order to change the value.
62165 *
62166 * let value = 0;
62167 * let threshold = 0.5;
62168 * function setup() {
62169 * setMoveThreshold(threshold);
62170 * }
62171 * function draw() {
62172 * fill(value);
62173 * rect(25, 25, 50, 50);
62174 * }
62175 * function deviceMoved() {
62176 * value = value + 5;
62177 * threshold = threshold + 0.1;
62178 * if (value > 255) {
62179 * value = 0;
62180 * threshold = 30;
62181 * }
62182 * setMoveThreshold(threshold);
62183 * }
62184 * </code>
62185 * </div>
62186 *
62187 * @alt
62188 * 50x50 black rect in center of canvas. turns white on mobile when device moves
62189 */
62190
62191 _main.default.prototype.setMoveThreshold = function(val) {
62192 _main.default._validateParameters('setMoveThreshold', arguments);
62193 move_threshold = val;
62194 };
62195
62196 /**
62197 * The <a href="#/p5/setShakeThreshold">setShakeThreshold()</a> function is used to set the movement threshold for
62198 * the <a href="#/p5/deviceShaken">deviceShaken()</a> function. The default threshold is set to 30.
62199 *
62200 * @method setShakeThreshold
62201 * @param {number} value The threshold value
62202 * @example
62203 * <div class="norender">
62204 * <code>
62205 * // Run this example on a mobile device
62206 * // You will need to shake the device more firmly
62207 * // the closer the box's fill gets to white in order to change the value.
62208 *
62209 * let value = 0;
62210 * let threshold = 30;
62211 * function setup() {
62212 * setShakeThreshold(threshold);
62213 * }
62214 * function draw() {
62215 * fill(value);
62216 * rect(25, 25, 50, 50);
62217 * }
62218 * function deviceMoved() {
62219 * value = value + 5;
62220 * threshold = threshold + 5;
62221 * if (value > 255) {
62222 * value = 0;
62223 * threshold = 30;
62224 * }
62225 * setShakeThreshold(threshold);
62226 * }
62227 * </code>
62228 * </div>
62229 *
62230 * @alt
62231 * 50x50 black rect in center of canvas. turns white on mobile when device
62232 * is being shaked
62233 */
62234
62235 _main.default.prototype.setShakeThreshold = function(val) {
62236 _main.default._validateParameters('setShakeThreshold', arguments);
62237 shake_threshold = val;
62238 };
62239
62240 /**
62241 * The <a href="#/p5/deviceMoved">deviceMoved()</a> function is called when the device is moved by more than
62242 * the threshold value along X, Y or Z axis. The default threshold is set to 0.5.
62243 * The threshold value can be changed using <a href="https://p5js.org/reference/#/p5/setMoveThreshold">setMoveThreshold()</a>.
62244 *
62245 * @method deviceMoved
62246 * @example
62247 * <div class="norender">
62248 * <code>
62249 * // Run this example on a mobile device
62250 * // Move the device around
62251 * // to change the value.
62252 *
62253 * let value = 0;
62254 * function draw() {
62255 * fill(value);
62256 * rect(25, 25, 50, 50);
62257 * }
62258 * function deviceMoved() {
62259 * value = value + 5;
62260 * if (value > 255) {
62261 * value = 0;
62262 * }
62263 * }
62264 * </code>
62265 * </div>
62266 *
62267 * @alt
62268 * 50x50 black rect in center of canvas. turns white on mobile when device moves
62269 */
62270
62271 /**
62272 * The <a href="#/p5/deviceTurned">deviceTurned()</a> function is called when the device rotates by
62273 * more than 90 degrees continuously.
62274 *
62275 * The axis that triggers the <a href="#/p5/deviceTurned">deviceTurned()</a> method is stored in the turnAxis
62276 * variable. The <a href="#/p5/deviceTurned">deviceTurned()</a> method can be locked to trigger on any axis:
62277 * X, Y or Z by comparing the turnAxis variable to 'X', 'Y' or 'Z'.
62278 *
62279 * @method deviceTurned
62280 * @example
62281 * <div class="norender">
62282 * <code>
62283 * // Run this example on a mobile device
62284 * // Rotate the device by 90 degrees
62285 * // to change the value.
62286 *
62287 * let value = 0;
62288 * function draw() {
62289 * fill(value);
62290 * rect(25, 25, 50, 50);
62291 * }
62292 * function deviceTurned() {
62293 * if (value === 0) {
62294 * value = 255;
62295 * } else if (value === 255) {
62296 * value = 0;
62297 * }
62298 * }
62299 * </code>
62300 * </div>
62301 * <div>
62302 * <code>
62303 * // Run this example on a mobile device
62304 * // Rotate the device by 90 degrees in the
62305 * // X-axis to change the value.
62306 *
62307 * let value = 0;
62308 * function draw() {
62309 * fill(value);
62310 * rect(25, 25, 50, 50);
62311 * }
62312 * function deviceTurned() {
62313 * if (turnAxis === 'X') {
62314 * if (value === 0) {
62315 * value = 255;
62316 * } else if (value === 255) {
62317 * value = 0;
62318 * }
62319 * }
62320 * }
62321 * </code>
62322 * </div>
62323 *
62324 * @alt
62325 * 50x50 black rect in center of canvas. turns white on mobile when device turns
62326 * 50x50 black rect in center of canvas. turns white on mobile when x-axis turns
62327 */
62328
62329 /**
62330 * The <a href="#/p5/deviceShaken">deviceShaken()</a> function is called when the device total acceleration
62331 * changes of accelerationX and accelerationY values is more than
62332 * the threshold value. The default threshold is set to 30.
62333 * The threshold value can be changed using <a href="https://p5js.org/reference/#/p5/setShakeThreshold">setShakeThreshold()</a>.
62334 *
62335 * @method deviceShaken
62336 * @example
62337 * <div class="norender">
62338 * <code>
62339 * // Run this example on a mobile device
62340 * // Shake the device to change the value.
62341 *
62342 * let value = 0;
62343 * function draw() {
62344 * fill(value);
62345 * rect(25, 25, 50, 50);
62346 * }
62347 * function deviceShaken() {
62348 * value = value + 5;
62349 * if (value > 255) {
62350 * value = 0;
62351 * }
62352 * }
62353 * </code>
62354 * </div>
62355 *
62356 * @alt
62357 * 50x50 black rect in center of canvas. turns white on mobile when device shakes
62358 */
62359
62360 _main.default.prototype._ondeviceorientation = function(e) {
62361 this._updatePRotations();
62362 if (this._angleMode === constants.radians) {
62363 e.beta = e.beta * (_PI / 180.0);
62364 e.gamma = e.gamma * (_PI / 180.0);
62365 e.alpha = e.alpha * (_PI / 180.0);
62366 }
62367 this._setProperty('rotationX', e.beta);
62368 this._setProperty('rotationY', e.gamma);
62369 this._setProperty('rotationZ', e.alpha);
62370 this._handleMotion();
62371 };
62372 _main.default.prototype._ondevicemotion = function(e) {
62373 this._updatePAccelerations();
62374 this._setProperty('accelerationX', e.acceleration.x * 2);
62375 this._setProperty('accelerationY', e.acceleration.y * 2);
62376 this._setProperty('accelerationZ', e.acceleration.z * 2);
62377 this._handleMotion();
62378 };
62379 _main.default.prototype._handleMotion = function() {
62380 if (window.orientation === 90 || window.orientation === -90) {
62381 this._setProperty('deviceOrientation', 'landscape');
62382 } else if (window.orientation === 0) {
62383 this._setProperty('deviceOrientation', 'portrait');
62384 } else if (window.orientation === undefined) {
62385 this._setProperty('deviceOrientation', 'undefined');
62386 }
62387 var deviceMoved = this.deviceMoved || window.deviceMoved;
62388 if (typeof deviceMoved === 'function') {
62389 if (
62390 Math.abs(this.accelerationX - this.pAccelerationX) > move_threshold ||
62391 Math.abs(this.accelerationY - this.pAccelerationY) > move_threshold ||
62392 Math.abs(this.accelerationZ - this.pAccelerationZ) > move_threshold
62393 ) {
62394 deviceMoved();
62395 }
62396 }
62397 var deviceTurned = this.deviceTurned || window.deviceTurned;
62398 if (typeof deviceTurned === 'function') {
62399 // The angles given by rotationX etc is from range -180 to 180.
62400 // The following will convert them to 0 to 360 for ease of calculation
62401 // of cases when the angles wrapped around.
62402 // _startAngleX will be converted back at the end and updated.
62403 var wRX = this.rotationX + 180;
62404 var wPRX = this.pRotationX + 180;
62405 var wSAX = startAngleX + 180;
62406 if ((wRX - wPRX > 0 && wRX - wPRX < 270) || wRX - wPRX < -270) {
62407 rotateDirectionX = 'clockwise';
62408 } else if (wRX - wPRX < 0 || wRX - wPRX > 270) {
62409 rotateDirectionX = 'counter-clockwise';
62410 }
62411 if (rotateDirectionX !== this.pRotateDirectionX) {
62412 wSAX = wRX;
62413 }
62414 if (Math.abs(wRX - wSAX) > 90 && Math.abs(wRX - wSAX) < 270) {
62415 wSAX = wRX;
62416 this._setProperty('turnAxis', 'X');
62417 deviceTurned();
62418 }
62419 this.pRotateDirectionX = rotateDirectionX;
62420 startAngleX = wSAX - 180;
62421
62422 // Y-axis is identical to X-axis except for changing some names.
62423 var wRY = this.rotationY + 180;
62424 var wPRY = this.pRotationY + 180;
62425 var wSAY = startAngleY + 180;
62426 if ((wRY - wPRY > 0 && wRY - wPRY < 270) || wRY - wPRY < -270) {
62427 rotateDirectionY = 'clockwise';
62428 } else if (wRY - wPRY < 0 || wRY - this.pRotationY > 270) {
62429 rotateDirectionY = 'counter-clockwise';
62430 }
62431 if (rotateDirectionY !== this.pRotateDirectionY) {
62432 wSAY = wRY;
62433 }
62434 if (Math.abs(wRY - wSAY) > 90 && Math.abs(wRY - wSAY) < 270) {
62435 wSAY = wRY;
62436 this._setProperty('turnAxis', 'Y');
62437 deviceTurned();
62438 }
62439 this.pRotateDirectionY = rotateDirectionY;
62440 startAngleY = wSAY - 180;
62441
62442 // Z-axis is already in the range 0 to 360
62443 // so no conversion is needed.
62444 if (
62445 (this.rotationZ - this.pRotationZ > 0 &&
62446 this.rotationZ - this.pRotationZ < 270) ||
62447 this.rotationZ - this.pRotationZ < -270
62448 ) {
62449 rotateDirectionZ = 'clockwise';
62450 } else if (
62451 this.rotationZ - this.pRotationZ < 0 ||
62452 this.rotationZ - this.pRotationZ > 270
62453 ) {
62454 rotateDirectionZ = 'counter-clockwise';
62455 }
62456 if (rotateDirectionZ !== this.pRotateDirectionZ) {
62457 startAngleZ = this.rotationZ;
62458 }
62459 if (
62460 Math.abs(this.rotationZ - startAngleZ) > 90 &&
62461 Math.abs(this.rotationZ - startAngleZ) < 270
62462 ) {
62463 startAngleZ = this.rotationZ;
62464 this._setProperty('turnAxis', 'Z');
62465 deviceTurned();
62466 }
62467 this.pRotateDirectionZ = rotateDirectionZ;
62468 this._setProperty('turnAxis', undefined);
62469 }
62470 var deviceShaken = this.deviceShaken || window.deviceShaken;
62471 if (typeof deviceShaken === 'function') {
62472 var accelerationChangeX;
62473 var accelerationChangeY;
62474 // Add accelerationChangeZ if acceleration change on Z is needed
62475 if (this.pAccelerationX !== null) {
62476 accelerationChangeX = Math.abs(this.accelerationX - this.pAccelerationX);
62477 accelerationChangeY = Math.abs(this.accelerationY - this.pAccelerationY);
62478 }
62479 if (accelerationChangeX + accelerationChangeY > shake_threshold) {
62480 deviceShaken();
62481 }
62482 }
62483 };
62484 var _default = _main.default;
62485 exports.default = _default;
62486 },
62487 { '../core/constants': 43, '../core/main': 54 }
62488 ],
62489 72: [
62490 function(_dereq_, module, exports) {
62491 'use strict';
62492 Object.defineProperty(exports, '__esModule', { value: true });
62493 exports.default = void 0;
62494
62495 var _main = _interopRequireDefault(_dereq_('../core/main'));
62496 function _interopRequireDefault(obj) {
62497 return obj && obj.__esModule ? obj : { default: obj };
62498 }
62499 /**
62500 * @module Events
62501 * @submodule Keyboard
62502 * @for p5
62503 * @requires core
62504 */ /**
62505 * The boolean system variable <a href="#/p5/keyIsPressed">keyIsPressed</a> is true if any key is pressed
62506 * and false if no keys are pressed.
62507 *
62508 * @property {Boolean} keyIsPressed
62509 * @readOnly
62510 * @example
62511 * <div>
62512 * <code>
62513 * function draw() {
62514 * if (keyIsPressed === true) {
62515 * fill(0);
62516 * } else {
62517 * fill(255);
62518 * }
62519 * rect(25, 25, 50, 50);
62520 * }
62521 * </code>
62522 * </div>
62523 *
62524 * @alt
62525 * 50x50 white rect that turns black on keypress.
62526 */ _main.default.prototype.isKeyPressed = false;
62527 _main.default.prototype.keyIsPressed = false; // khan
62528 /**
62529 * The system variable key always contains the value of the most recent
62530 * key on the keyboard that was typed. To get the proper capitalization, it
62531 * is best to use it within <a href="#/p5/keyTyped">keyTyped()</a>. For non-ASCII keys, use the <a href="#/p5/keyCode">keyCode</a>
62532 * variable.
62533 *
62534 * @property {String} key
62535 * @readOnly
62536 * @example
62537 * <div><code>
62538 * // Click any key to display it!
62539 * // (Not Guaranteed to be Case Sensitive)
62540 * function setup() {
62541 * fill(245, 123, 158);
62542 * textSize(50);
62543 * }
62544 *
62545 * function draw() {
62546 * background(200);
62547 * text(key, 33, 65); // Display last key pressed.
62548 * }
62549 * </code></div>
62550 *
62551 * @alt
62552 * canvas displays any key value that is pressed in pink font.
62553 */
62554 _main.default.prototype.key = '';
62555
62556 /**
62557 * The variable keyCode is used to detect special keys such as BACKSPACE,
62558 * DELETE, ENTER, RETURN, TAB, ESCAPE, SHIFT, CONTROL, OPTION, ALT, UP_ARROW,
62559 * DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW.
62560 * You can also check for custom keys by looking up the keyCode of any key
62561 * on a site like this: <a href="http://keycode.info/">keycode.info</a>.
62562 *
62563 * @property {Integer} keyCode
62564 * @readOnly
62565 * @example
62566 * <div><code>
62567 * let fillVal = 126;
62568 * function draw() {
62569 * fill(fillVal);
62570 * rect(25, 25, 50, 50);
62571 * }
62572 *
62573 * function keyPressed() {
62574 * if (keyCode === UP_ARROW) {
62575 * fillVal = 255;
62576 * } else if (keyCode === DOWN_ARROW) {
62577 * fillVal = 0;
62578 * }
62579 * return false; // prevent default
62580 * }
62581 * </code></div>
62582 * <div><code>
62583 * function draw() {}
62584 * function keyPressed() {
62585 * background('yellow');
62586 * text(`${key} ${keyCode}`, 10, 40);
62587 * print(key, ' ', keyCode);
62588 * return false; // prevent default
62589 * }
62590 * </code></div>
62591 * @alt
62592 * Grey rect center. turns white when up arrow pressed and black when down
62593 * Display key pressed and its keyCode in a yellow box
62594 */
62595 _main.default.prototype.keyCode = 0;
62596
62597 /**
62598 * The <a href="#/p5/keyPressed">keyPressed()</a> function is called once every time a key is pressed. The
62599 * keyCode for the key that was pressed is stored in the <a href="#/p5/keyCode">keyCode</a> variable.
62600 *
62601 * For non-ASCII keys, use the keyCode variable. You can check if the keyCode
62602 * equals BACKSPACE, DELETE, ENTER, RETURN, TAB, ESCAPE, SHIFT, CONTROL,
62603 * OPTION, ALT, UP_ARROW, DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW.
62604 *
62605 * For ASCII keys, the key that was pressed is stored in the key variable. However, it
62606 * does not distinguish between uppercase and lowercase. For this reason, it
62607 * is recommended to use <a href="#/p5/keyTyped">keyTyped()</a> to read the key variable, in which the
62608 * case of the variable will be distinguished.
62609 *
62610 * Because of how operating systems handle key repeats, holding down a key
62611 * may cause multiple calls to <a href="#/p5/keyTyped">keyTyped()</a> (and <a href="#/p5/keyReleased">keyReleased()</a> as well). The
62612 * rate of repeat is set by the operating system and how each computer is
62613 * configured.<br><br>
62614 * Browsers may have different default
62615 * behaviors attached to various key events. To prevent any default
62616 * behavior for this event, add "return false" to the end of the method.
62617 *
62618 * @method keyPressed
62619 * @example
62620 * <div>
62621 * <code>
62622 * let value = 0;
62623 * function draw() {
62624 * fill(value);
62625 * rect(25, 25, 50, 50);
62626 * }
62627 * function keyPressed() {
62628 * if (value === 0) {
62629 * value = 255;
62630 * } else {
62631 * value = 0;
62632 * }
62633 * }
62634 * </code>
62635 * </div>
62636 * <div>
62637 * <code>
62638 * let value = 0;
62639 * function draw() {
62640 * fill(value);
62641 * rect(25, 25, 50, 50);
62642 * }
62643 * function keyPressed() {
62644 * if (keyCode === LEFT_ARROW) {
62645 * value = 255;
62646 * } else if (keyCode === RIGHT_ARROW) {
62647 * value = 0;
62648 * }
62649 * }
62650 * </code>
62651 * </div>
62652 * <div class="norender">
62653 * <code>
62654 * function keyPressed() {
62655 * // Do something
62656 * return false; // prevent any default behaviour
62657 * }
62658 * </code>
62659 * </div>
62660 *
62661 * @alt
62662 * black rect center. turns white when key pressed and black when released
62663 * black rect center. turns white when left arrow pressed and black when right.
62664 */
62665 _main.default.prototype._onkeydown = function(e) {
62666 if (this._downKeys[e.which]) {
62667 // prevent multiple firings
62668 return;
62669 }
62670 this._setProperty('isKeyPressed', true);
62671 this._setProperty('keyIsPressed', true);
62672 this._setProperty('keyCode', e.which);
62673 this._downKeys[e.which] = true;
62674 this._setProperty('key', e.key || String.fromCharCode(e.which) || e.which);
62675 var keyPressed = this.keyPressed || window.keyPressed;
62676 if (typeof keyPressed === 'function' && !e.charCode) {
62677 var executeDefault = keyPressed(e);
62678 if (executeDefault === false) {
62679 e.preventDefault();
62680 }
62681 }
62682 };
62683 /**
62684 * The <a href="#/p5/keyReleased">keyReleased()</a> function is called once every time a key is released.
62685 * See <a href="#/p5/key">key</a> and <a href="#/p5/keyCode">keyCode</a> for more information.<br><br>
62686 * Browsers may have different default
62687 * behaviors attached to various key events. To prevent any default
62688 * behavior for this event, add "return false" to the end of the method.
62689 *
62690 * @method keyReleased
62691 * @example
62692 * <div>
62693 * <code>
62694 * let value = 0;
62695 * function draw() {
62696 * fill(value);
62697 * rect(25, 25, 50, 50);
62698 * }
62699 * function keyReleased() {
62700 * if (value === 0) {
62701 * value = 255;
62702 * } else {
62703 * value = 0;
62704 * }
62705 * return false; // prevent any default behavior
62706 * }
62707 * </code>
62708 * </div>
62709 *
62710 * @alt
62711 * black rect center. turns white when key pressed and black when pressed again
62712 */
62713 _main.default.prototype._onkeyup = function(e) {
62714 var keyReleased = this.keyReleased || window.keyReleased;
62715 this._downKeys[e.which] = false;
62716
62717 if (!this._areDownKeys()) {
62718 this._setProperty('isKeyPressed', false);
62719 this._setProperty('keyIsPressed', false);
62720 }
62721
62722 this._setProperty('_lastKeyCodeTyped', null);
62723
62724 this._setProperty('key', e.key || String.fromCharCode(e.which) || e.which);
62725 this._setProperty('keyCode', e.which);
62726 if (typeof keyReleased === 'function') {
62727 var executeDefault = keyReleased(e);
62728 if (executeDefault === false) {
62729 e.preventDefault();
62730 }
62731 }
62732 };
62733
62734 /**
62735 * The <a href="#/p5/keyTyped">keyTyped()</a> function is called once every time a key is pressed, but
62736 * action keys such as Backspace, Delete, Ctrl, Shift, and Alt are ignored. If you are trying to detect
62737 * a keyCode for one of these keys, use the <a href="#/p5/keyPressed">keyPressed()</a> function instead.
62738 * The most recent key typed will be stored in the key variable.
62739 *
62740 * Because of how operating systems handle key repeats, holding down a key
62741 * will cause multiple calls to <a href="#/p5/keyTyped">keyTyped()</a> (and <a href="#/p5/keyReleased">keyReleased()</a> as well). The
62742 * rate of repeat is set by the operating system and how each computer is
62743 * configured.<br><br>
62744 * Browsers may have different default behaviors attached to various key
62745 * events. To prevent any default behavior for this event, add "return false"
62746 * to the end of the method.
62747 *
62748 * @method keyTyped
62749 * @example
62750 * <div>
62751 * <code>
62752 * let value = 0;
62753 * function draw() {
62754 * fill(value);
62755 * rect(25, 25, 50, 50);
62756 * }
62757 * function keyTyped() {
62758 * if (key === 'a') {
62759 * value = 255;
62760 * } else if (key === 'b') {
62761 * value = 0;
62762 * }
62763 * // uncomment to prevent any default behavior
62764 * // return false;
62765 * }
62766 * </code>
62767 * </div>
62768 *
62769 * @alt
62770 * black rect center. turns white when 'a' key typed and black when 'b' pressed
62771 */
62772 _main.default.prototype._onkeypress = function(e) {
62773 if (e.which === this._lastKeyCodeTyped) {
62774 // prevent multiple firings
62775 return;
62776 }
62777 this._setProperty('_lastKeyCodeTyped', e.which); // track last keyCode
62778 this._setProperty('key', String.fromCharCode(e.which));
62779 var keyTyped = this.keyTyped || window.keyTyped;
62780 if (typeof keyTyped === 'function') {
62781 var executeDefault = keyTyped(e);
62782 if (executeDefault === false) {
62783 e.preventDefault();
62784 }
62785 }
62786 };
62787 /**
62788 * The onblur function is called when the user is no longer focused
62789 * on the p5 element. Because the keyup events will not fire if the user is
62790 * not focused on the element we must assume all keys currently down have
62791 * been released.
62792 */
62793 _main.default.prototype._onblur = function(e) {
62794 this._downKeys = {};
62795 };
62796
62797 /**
62798 * The <a href="#/p5/keyIsDown">keyIsDown()</a> function checks if the key is currently down, i.e. pressed.
62799 * It can be used if you have an object that moves, and you want several keys
62800 * to be able to affect its behaviour simultaneously, such as moving a
62801 * sprite diagonally. You can put in any number representing the keyCode of
62802 * the key, or use any of the variable <a href="#/p5/keyCode">keyCode</a> names listed
62803 * <a href="http://p5js.org/reference/#p5/keyCode">here</a>.
62804 *
62805 * @method keyIsDown
62806 * @param {Number} code The key to check for.
62807 * @return {Boolean} whether key is down or not
62808 * @example
62809 * <div><code>
62810 * let x = 100;
62811 * let y = 100;
62812 *
62813 * function setup() {
62814 * createCanvas(512, 512);
62815 * fill(255, 0, 0);
62816 * }
62817 *
62818 * function draw() {
62819 * if (keyIsDown(LEFT_ARROW)) {
62820 * x -= 5;
62821 * }
62822 *
62823 * if (keyIsDown(RIGHT_ARROW)) {
62824 * x += 5;
62825 * }
62826 *
62827 * if (keyIsDown(UP_ARROW)) {
62828 * y -= 5;
62829 * }
62830 *
62831 * if (keyIsDown(DOWN_ARROW)) {
62832 * y += 5;
62833 * }
62834 *
62835 * clear();
62836 * ellipse(x, y, 50, 50);
62837 * }
62838 * </code></div>
62839 *
62840 * <div><code>
62841 * let diameter = 50;
62842 *
62843 * function setup() {
62844 * createCanvas(512, 512);
62845 * }
62846 *
62847 * function draw() {
62848 * // 107 and 187 are keyCodes for "+"
62849 * if (keyIsDown(107) || keyIsDown(187)) {
62850 * diameter += 1;
62851 * }
62852 *
62853 * // 109 and 189 are keyCodes for "-"
62854 * if (keyIsDown(109) || keyIsDown(189)) {
62855 * diameter -= 1;
62856 * }
62857 *
62858 * clear();
62859 * fill(255, 0, 0);
62860 * ellipse(50, 50, diameter, diameter);
62861 * }
62862 * </code></div>
62863 *
62864 * @alt
62865 * 50x50 red ellipse moves left, right, up and down with arrow presses.
62866 * 50x50 red ellipse gets bigger or smaller when + or - are pressed.
62867 */
62868 _main.default.prototype.keyIsDown = function(code) {
62869 _main.default._validateParameters('keyIsDown', arguments);
62870 return this._downKeys[code] || false;
62871 };
62872
62873 /**
62874 * The _areDownKeys function returns a boolean true if any keys pressed
62875 * and a false if no keys are currently pressed.
62876
62877 * Helps avoid instances where multiple keys are pressed simultaneously and
62878 * releasing a single key will then switch the
62879 * keyIsPressed property to true.
62880 * @private
62881 **/
62882 _main.default.prototype._areDownKeys = function() {
62883 for (var key in this._downKeys) {
62884 if (this._downKeys.hasOwnProperty(key) && this._downKeys[key] === true) {
62885 return true;
62886 }
62887 }
62888 return false;
62889 };
62890 var _default = _main.default;
62891 exports.default = _default;
62892 },
62893 { '../core/main': 54 }
62894 ],
62895 73: [
62896 function(_dereq_, module, exports) {
62897 'use strict';
62898 function _typeof(obj) {
62899 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
62900 _typeof = function _typeof(obj) {
62901 return typeof obj;
62902 };
62903 } else {
62904 _typeof = function _typeof(obj) {
62905 return obj &&
62906 typeof Symbol === 'function' &&
62907 obj.constructor === Symbol &&
62908 obj !== Symbol.prototype
62909 ? 'symbol'
62910 : typeof obj;
62911 };
62912 }
62913 return _typeof(obj);
62914 }
62915 Object.defineProperty(exports, '__esModule', { value: true });
62916 exports.default = void 0;
62917
62918 var _main = _interopRequireDefault(_dereq_('../core/main'));
62919 var constants = _interopRequireWildcard(_dereq_('../core/constants'));
62920 function _getRequireWildcardCache() {
62921 if (typeof WeakMap !== 'function') return null;
62922 var cache = new WeakMap();
62923 _getRequireWildcardCache = function _getRequireWildcardCache() {
62924 return cache;
62925 };
62926 return cache;
62927 }
62928 function _interopRequireWildcard(obj) {
62929 if (obj && obj.__esModule) {
62930 return obj;
62931 }
62932 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) {
62933 return { default: obj };
62934 }
62935 var cache = _getRequireWildcardCache();
62936 if (cache && cache.has(obj)) {
62937 return cache.get(obj);
62938 }
62939 var newObj = {};
62940 var hasPropertyDescriptor =
62941 Object.defineProperty && Object.getOwnPropertyDescriptor;
62942 for (var key in obj) {
62943 if (Object.prototype.hasOwnProperty.call(obj, key)) {
62944 var desc = hasPropertyDescriptor
62945 ? Object.getOwnPropertyDescriptor(obj, key)
62946 : null;
62947 if (desc && (desc.get || desc.set)) {
62948 Object.defineProperty(newObj, key, desc);
62949 } else {
62950 newObj[key] = obj[key];
62951 }
62952 }
62953 }
62954 newObj.default = obj;
62955 if (cache) {
62956 cache.set(obj, newObj);
62957 }
62958 return newObj;
62959 }
62960 function _interopRequireDefault(obj) {
62961 return obj && obj.__esModule ? obj : { default: obj };
62962 }
62963 /**
62964 * @module Events
62965 * @submodule Mouse
62966 * @for p5
62967 * @requires core
62968 * @requires constants
62969 */ /**
62970 *
62971 * The variable movedX contains the horizontal movement of the mouse since the last frame
62972 * @property {Number} movedX
62973 * @readOnly
62974 * @example
62975 * <div class="notest">
62976 * <code>
62977 * let x = 50;
62978 * function setup() {
62979 * rectMode(CENTER);
62980 * }
62981 *
62982 * function draw() {
62983 * if (x > 48) {
62984 * x -= 2;
62985 * } else if (x < 48) {
62986 * x += 2;
62987 * }
62988 * x += floor(movedX / 5);
62989 * background(237, 34, 93);
62990 * fill(0);
62991 * rect(x, 50, 50, 50);
62992 * }
62993 * </code>
62994 * </div>
62995 * @alt
62996 * box moves left and right according to mouse movement then slowly back towards the center
62997 */ _main.default.prototype.movedX = 0;
62998 /**
62999 * The variable movedY contains the vertical movement of the mouse since the last frame
63000 * @property {Number} movedY
63001 * @readOnly
63002 * @example
63003 * <div class="notest">
63004 * <code>
63005 * let y = 50;
63006 * function setup() {
63007 * rectMode(CENTER);
63008 * }
63009 *
63010 * function draw() {
63011 * if (y > 48) {
63012 * y -= 2;
63013 * } else if (y < 48) {
63014 * y += 2;
63015 * }
63016 * y += floor(movedY / 5);
63017 * background(237, 34, 93);
63018 * fill(0);
63019 * rect(y, 50, 50, 50);
63020 * }
63021 * </code>
63022 * </div>
63023 * @alt
63024 * box moves up and down according to mouse movement then slowly back towards the center
63025 */ _main.default.prototype.movedY = 0;
63026 /*
63027 * This is a flag which is false until the first time
63028 * we receive a mouse event. The pmouseX and pmouseY
63029 * values will match the mouseX and mouseY values until
63030 * this interaction takes place.
63031 */
63032 _main.default.prototype._hasMouseInteracted = false;
63033
63034 /**
63035 * The system variable mouseX always contains the current horizontal
63036 * position of the mouse, relative to (0, 0) of the canvas. The value at
63037 * the top-left corner is (0, 0) for 2-D and (-width/2, -height/2) for WebGL.
63038 * If touch is used instead of mouse input, mouseX will hold the x value
63039 * of the most recent touch point.
63040 *
63041 * @property {Number} mouseX
63042 * @readOnly
63043 *
63044 * @example
63045 * <div>
63046 * <code>
63047 * // Move the mouse across the canvas
63048 * function draw() {
63049 * background(244, 248, 252);
63050 * line(mouseX, 0, mouseX, 100);
63051 * }
63052 * </code>
63053 * </div>
63054 *
63055 * @alt
63056 * horizontal black line moves left and right with mouse x-position
63057 */
63058 _main.default.prototype.mouseX = 0;
63059
63060 /**
63061 * The system variable mouseY always contains the current vertical
63062 * position of the mouse, relative to (0, 0) of the canvas. The value at
63063 * the top-left corner is (0, 0) for 2-D and (-width/2, -height/2) for WebGL.
63064 * If touch is used instead of mouse input, mouseY will hold the y value
63065 * of the most recent touch point.
63066 *
63067 * @property {Number} mouseY
63068 * @readOnly
63069 *
63070 * @example
63071 * <div>
63072 * <code>
63073 * // Move the mouse across the canvas
63074 * function draw() {
63075 * background(244, 248, 252);
63076 * line(0, mouseY, 100, mouseY);
63077 * }
63078 * </code>
63079 * </div>
63080 *
63081 * @alt
63082 * vertical black line moves up and down with mouse y-position
63083 */
63084 _main.default.prototype.mouseY = 0;
63085
63086 /**
63087 * The system variable pmouseX always contains the horizontal position of
63088 * the mouse or finger in the frame previous to the current frame, relative to
63089 * (0, 0) of the canvas. The value at the top-left corner is (0, 0) for 2-D and
63090 * (-width/2, -height/2) for WebGL. Note: pmouseX will be reset to the current mouseX
63091 * value at the start of each touch event.
63092 *
63093 * @property {Number} pmouseX
63094 * @readOnly
63095 *
63096 * @example
63097 * <div>
63098 * <code>
63099 * // Move the mouse across the canvas to leave a trail
63100 * function setup() {
63101 * //slow down the frameRate to make it more visible
63102 * frameRate(10);
63103 * }
63104 *
63105 * function draw() {
63106 * background(244, 248, 252);
63107 * line(mouseX, mouseY, pmouseX, pmouseY);
63108 * print(pmouseX + ' -> ' + mouseX);
63109 * }
63110 * </code>
63111 * </div>
63112 *
63113 * @alt
63114 * line trail is created from cursor movements. faster movement make longer line.
63115 */
63116 _main.default.prototype.pmouseX = 0;
63117
63118 /**
63119 * The system variable pmouseY always contains the vertical position of
63120 * the mouse or finger in the frame previous to the current frame, relative to
63121 * (0, 0) of the canvas. The value at the top-left corner is (0, 0) for 2-D and
63122 * (-width/2, -height/2) for WebGL. Note: pmouseY will be reset to the current mouseY
63123 * value at the start of each touch event.
63124 *
63125 * @property {Number} pmouseY
63126 * @readOnly
63127 *
63128 * @example
63129 * <div>
63130 * <code>
63131 * function draw() {
63132 * background(237, 34, 93);
63133 * fill(0);
63134 * //draw a square only if the mouse is not moving
63135 * if (mouseY === pmouseY && mouseX === pmouseX) {
63136 * rect(20, 20, 60, 60);
63137 * }
63138 *
63139 * print(pmouseY + ' -> ' + mouseY);
63140 * }
63141 * </code>
63142 * </div>
63143 *
63144 * @alt
63145 * 60x60 black rect center, fuchsia background. rect flickers on mouse movement
63146 */
63147 _main.default.prototype.pmouseY = 0;
63148
63149 /**
63150 * The system variable winMouseX always contains the current horizontal
63151 * position of the mouse, relative to (0, 0) of the window.
63152 *
63153 * @property {Number} winMouseX
63154 * @readOnly
63155 *
63156 * @example
63157 * <div>
63158 * <code>
63159 * let myCanvas;
63160 *
63161 * function setup() {
63162 * //use a variable to store a pointer to the canvas
63163 * myCanvas = createCanvas(100, 100);
63164 * let body = document.getElementsByTagName('body')[0];
63165 * myCanvas.parent(body);
63166 * }
63167 *
63168 * function draw() {
63169 * background(237, 34, 93);
63170 * fill(0);
63171 *
63172 * //move the canvas to the horizontal mouse position
63173 * //relative to the window
63174 * myCanvas.position(winMouseX + 1, windowHeight / 2);
63175 *
63176 * //the y of the square is relative to the canvas
63177 * rect(20, mouseY, 60, 60);
63178 * }
63179 * </code>
63180 * </div>
63181 *
63182 * @alt
63183 * 60x60 black rect y moves with mouse y and fuchsia canvas moves with mouse x
63184 */
63185 _main.default.prototype.winMouseX = 0;
63186
63187 /**
63188 * The system variable winMouseY always contains the current vertical
63189 * position of the mouse, relative to (0, 0) of the window.
63190 *
63191 * @property {Number} winMouseY
63192 * @readOnly
63193 *
63194 * @example
63195 * <div>
63196 * <code>
63197 * let myCanvas;
63198 *
63199 * function setup() {
63200 * //use a variable to store a pointer to the canvas
63201 * myCanvas = createCanvas(100, 100);
63202 * let body = document.getElementsByTagName('body')[0];
63203 * myCanvas.parent(body);
63204 * }
63205 *
63206 * function draw() {
63207 * background(237, 34, 93);
63208 * fill(0);
63209 *
63210 * //move the canvas to the vertical mouse position
63211 * //relative to the window
63212 * myCanvas.position(windowWidth / 2, winMouseY + 1);
63213 *
63214 * //the x of the square is relative to the canvas
63215 * rect(mouseX, 20, 60, 60);
63216 * }
63217 * </code>
63218 * </div>
63219 *
63220 * @alt
63221 * 60x60 black rect x moves with mouse x and fuchsia canvas y moves with mouse y
63222 */
63223 _main.default.prototype.winMouseY = 0;
63224
63225 /**
63226 * The system variable pwinMouseX always contains the horizontal position
63227 * of the mouse in the frame previous to the current frame, relative to
63228 * (0, 0) of the window. Note: pwinMouseX will be reset to the current winMouseX
63229 * value at the start of each touch event.
63230 *
63231 * @property {Number} pwinMouseX
63232 * @readOnly
63233 *
63234 * @example
63235 * <div>
63236 * <code>
63237 * let myCanvas;
63238 *
63239 * function setup() {
63240 * //use a variable to store a pointer to the canvas
63241 * myCanvas = createCanvas(100, 100);
63242 * noStroke();
63243 * fill(237, 34, 93);
63244 * }
63245 *
63246 * function draw() {
63247 * clear();
63248 * //the difference between previous and
63249 * //current x position is the horizontal mouse speed
63250 * let speed = abs(winMouseX - pwinMouseX);
63251 * //change the size of the circle
63252 * //according to the horizontal speed
63253 * ellipse(50, 50, 10 + speed * 5, 10 + speed * 5);
63254 * //move the canvas to the mouse position
63255 * myCanvas.position(winMouseX + 1, winMouseY + 1);
63256 * }
63257 * </code>
63258 * </div>
63259 *
63260 * @alt
63261 * fuchsia ellipse moves with mouse x and y. Grows and shrinks with mouse speed
63262 */
63263 _main.default.prototype.pwinMouseX = 0;
63264
63265 /**
63266 * The system variable pwinMouseY always contains the vertical position of
63267 * the mouse in the frame previous to the current frame, relative to (0, 0)
63268 * of the window. Note: pwinMouseY will be reset to the current winMouseY
63269 * value at the start of each touch event.
63270 *
63271 * @property {Number} pwinMouseY
63272 * @readOnly
63273 *
63274 * @example
63275 * <div>
63276 * <code>
63277 * let myCanvas;
63278 *
63279 * function setup() {
63280 * //use a variable to store a pointer to the canvas
63281 * myCanvas = createCanvas(100, 100);
63282 * noStroke();
63283 * fill(237, 34, 93);
63284 * }
63285 *
63286 * function draw() {
63287 * clear();
63288 * //the difference between previous and
63289 * //current y position is the vertical mouse speed
63290 * let speed = abs(winMouseY - pwinMouseY);
63291 * //change the size of the circle
63292 * //according to the vertical speed
63293 * ellipse(50, 50, 10 + speed * 5, 10 + speed * 5);
63294 * //move the canvas to the mouse position
63295 * myCanvas.position(winMouseX + 1, winMouseY + 1);
63296 * }
63297 * </code>
63298 * </div>
63299 *
63300 * @alt
63301 * fuchsia ellipse moves with mouse x and y. Grows and shrinks with mouse speed
63302 */
63303 _main.default.prototype.pwinMouseY = 0;
63304
63305 /**
63306 * Processing automatically tracks if the mouse button is pressed and which
63307 * button is pressed. The value of the system variable mouseButton is either
63308 * LEFT, RIGHT, or CENTER depending on which button was pressed last.
63309 * Warning: different browsers may track mouseButton differently.
63310 *
63311 * @property {Constant} mouseButton
63312 * @readOnly
63313 *
63314 * @example
63315 * <div>
63316 * <code>
63317 * function draw() {
63318 * background(237, 34, 93);
63319 * fill(0);
63320 *
63321 * if (mouseIsPressed) {
63322 * if (mouseButton === LEFT) {
63323 * ellipse(50, 50, 50, 50);
63324 * }
63325 * if (mouseButton === RIGHT) {
63326 * rect(25, 25, 50, 50);
63327 * }
63328 * if (mouseButton === CENTER) {
63329 * triangle(23, 75, 50, 20, 78, 75);
63330 * }
63331 * }
63332 *
63333 * print(mouseButton);
63334 * }
63335 * </code>
63336 * </div>
63337 *
63338 * @alt
63339 * 50x50 black ellipse appears on center of fuchsia canvas on mouse click/press.
63340 */
63341 _main.default.prototype.mouseButton = 0;
63342
63343 /**
63344 * The boolean system variable mouseIsPressed is true if the mouse is pressed
63345 * and false if not.
63346 *
63347 * @property {Boolean} mouseIsPressed
63348 * @readOnly
63349 *
63350 * @example
63351 * <div>
63352 * <code>
63353 * function draw() {
63354 * background(237, 34, 93);
63355 * fill(0);
63356 *
63357 * if (mouseIsPressed) {
63358 * ellipse(50, 50, 50, 50);
63359 * } else {
63360 * rect(25, 25, 50, 50);
63361 * }
63362 *
63363 * print(mouseIsPressed);
63364 * }
63365 * </code>
63366 * </div>
63367 *
63368 * @alt
63369 * black 50x50 rect becomes ellipse with mouse click/press. fuchsia background.
63370 */
63371 _main.default.prototype.mouseIsPressed = false;
63372
63373 _main.default.prototype._updateNextMouseCoords = function(e) {
63374 if (this._curElement !== null && (!e.touches || e.touches.length > 0)) {
63375 var mousePos = getMousePos(this._curElement.elt, this.width, this.height, e);
63376
63377 this._setProperty('movedX', e.movementX);
63378 this._setProperty('movedY', e.movementY);
63379 this._setProperty('mouseX', mousePos.x);
63380 this._setProperty('mouseY', mousePos.y);
63381 this._setProperty('winMouseX', mousePos.winX);
63382 this._setProperty('winMouseY', mousePos.winY);
63383 }
63384 if (!this._hasMouseInteracted) {
63385 // For first draw, make previous and next equal
63386 this._updateMouseCoords();
63387 this._setProperty('_hasMouseInteracted', true);
63388 }
63389 };
63390
63391 _main.default.prototype._updateMouseCoords = function() {
63392 this._setProperty('pmouseX', this.mouseX);
63393 this._setProperty('pmouseY', this.mouseY);
63394 this._setProperty('pwinMouseX', this.winMouseX);
63395 this._setProperty('pwinMouseY', this.winMouseY);
63396
63397 this._setProperty('_pmouseWheelDeltaY', this._mouseWheelDeltaY);
63398 };
63399
63400 function getMousePos(canvas, w, h, evt) {
63401 if (evt && !evt.clientX) {
63402 // use touches if touch and not mouse
63403 if (evt.touches) {
63404 evt = evt.touches[0];
63405 } else if (evt.changedTouches) {
63406 evt = evt.changedTouches[0];
63407 }
63408 }
63409 var rect = canvas.getBoundingClientRect();
63410 var sx = canvas.scrollWidth / w || 1;
63411 var sy = canvas.scrollHeight / h || 1;
63412 return {
63413 x: (evt.clientX - rect.left) / sx,
63414 y: (evt.clientY - rect.top) / sy,
63415 winX: evt.clientX,
63416 winY: evt.clientY,
63417 id: evt.identifier
63418 };
63419 }
63420
63421 _main.default.prototype._setMouseButton = function(e) {
63422 if (e.button === 1) {
63423 this._setProperty('mouseButton', constants.CENTER);
63424 } else if (e.button === 2) {
63425 this._setProperty('mouseButton', constants.RIGHT);
63426 } else {
63427 this._setProperty('mouseButton', constants.LEFT);
63428 }
63429 };
63430
63431 /**
63432 * The <a href="#/p5/mouseMoved">mouseMoved()</a> function is called every time the mouse moves and a mouse
63433 * button is not pressed.<br><br>
63434 * Browsers may have different default
63435 * behaviors attached to various mouse events. To prevent any default
63436 * behavior for this event, add "return false" to the end of the method.
63437 *
63438 * @method mouseMoved
63439 * @param {Object} [event] optional MouseEvent callback argument.
63440 * @example
63441 * <div>
63442 * <code>
63443 * // Move the mouse across the page
63444 * // to change its value
63445 *
63446 * let value = 0;
63447 * function draw() {
63448 * fill(value);
63449 * rect(25, 25, 50, 50);
63450 * }
63451 * function mouseMoved() {
63452 * value = value + 5;
63453 * if (value > 255) {
63454 * value = 0;
63455 * }
63456 * }
63457 * </code>
63458 * </div>
63459 *
63460 * <div class="norender">
63461 * <code>
63462 * function mouseMoved() {
63463 * ellipse(mouseX, mouseY, 5, 5);
63464 * // prevent default
63465 * return false;
63466 * }
63467 * </code>
63468 * </div>
63469 *
63470 * <div class="norender">
63471 * <code>
63472 * // returns a MouseEvent object
63473 * // as a callback argument
63474 * function mouseMoved(event) {
63475 * console.log(event);
63476 * }
63477 * </code>
63478 * </div>
63479 *
63480 * @alt
63481 * black 50x50 rect becomes lighter with mouse movements until white then resets
63482 * no image displayed
63483 */
63484
63485 /**
63486 * The <a href="#/p5/mouseDragged">mouseDragged()</a> function is called once every time the mouse moves and
63487 * a mouse button is pressed. If no <a href="#/p5/mouseDragged">mouseDragged()</a> function is defined, the
63488 * <a href="#/p5/touchMoved">touchMoved()</a> function will be called instead if it is defined.<br><br>
63489 * Browsers may have different default
63490 * behaviors attached to various mouse events. To prevent any default
63491 * behavior for this event, add "return false" to the end of the method.
63492 *
63493 * @method mouseDragged
63494 * @param {Object} [event] optional MouseEvent callback argument.
63495 * @example
63496 * <div>
63497 * <code>
63498 * // Drag the mouse across the page
63499 * // to change its value
63500 *
63501 * let value = 0;
63502 * function draw() {
63503 * fill(value);
63504 * rect(25, 25, 50, 50);
63505 * }
63506 * function mouseDragged() {
63507 * value = value + 5;
63508 * if (value > 255) {
63509 * value = 0;
63510 * }
63511 * }
63512 * </code>
63513 * </div>
63514 *
63515 * <div class="norender">
63516 * <code>
63517 * function mouseDragged() {
63518 * ellipse(mouseX, mouseY, 5, 5);
63519 * // prevent default
63520 * return false;
63521 * }
63522 * </code>
63523 * </div>
63524 *
63525 * <div class="norender">
63526 * <code>
63527 * // returns a MouseEvent object
63528 * // as a callback argument
63529 * function mouseDragged(event) {
63530 * console.log(event);
63531 * }
63532 * </code>
63533 * </div>
63534 *
63535 * @alt
63536 * black 50x50 rect turns lighter with mouse click and drag until white, resets
63537 * no image displayed
63538 */
63539 _main.default.prototype._onmousemove = function(e) {
63540 var context = this._isGlobal ? window : this;
63541 var executeDefault;
63542 this._updateNextMouseCoords(e);
63543 if (!this.mouseIsPressed) {
63544 if (typeof context.mouseMoved === 'function') {
63545 executeDefault = context.mouseMoved(e);
63546 if (executeDefault === false) {
63547 e.preventDefault();
63548 }
63549 }
63550 } else {
63551 if (typeof context.mouseDragged === 'function') {
63552 executeDefault = context.mouseDragged(e);
63553 if (executeDefault === false) {
63554 e.preventDefault();
63555 }
63556 } else if (typeof context.touchMoved === 'function') {
63557 executeDefault = context.touchMoved(e);
63558 if (executeDefault === false) {
63559 e.preventDefault();
63560 }
63561 }
63562 }
63563 };
63564
63565 /**
63566 * The <a href="#/p5/mousePressed">mousePressed()</a> function is called once after every time a mouse button
63567 * is pressed. The mouseButton variable (see the related reference entry)
63568 * can be used to determine which button has been pressed. If no
63569 * <a href="#/p5/mousePressed">mousePressed()</a> function is defined, the <a href="#/p5/touchStarted">touchStarted()</a> function will be
63570 * called instead if it is defined.<br><br>
63571 * Browsers may have different default
63572 * behaviors attached to various mouse events. To prevent any default
63573 * behavior for this event, add "return false" to the end of the method.
63574 *
63575 * @method mousePressed
63576 * @param {Object} [event] optional MouseEvent callback argument.
63577 * @example
63578 * <div>
63579 * <code>
63580 * // Click within the image to change
63581 * // the value of the rectangle
63582 *
63583 * let value = 0;
63584 * function draw() {
63585 * fill(value);
63586 * rect(25, 25, 50, 50);
63587 * }
63588 * function mousePressed() {
63589 * if (value === 0) {
63590 * value = 255;
63591 * } else {
63592 * value = 0;
63593 * }
63594 * }
63595 * </code>
63596 * </div>
63597 *
63598 * <div class="norender">
63599 * <code>
63600 * function mousePressed() {
63601 * ellipse(mouseX, mouseY, 5, 5);
63602 * // prevent default
63603 * return false;
63604 * }
63605 * </code>
63606 * </div>
63607 *
63608 * <div class="norender">
63609 * <code>
63610 * // returns a MouseEvent object
63611 * // as a callback argument
63612 * function mousePressed(event) {
63613 * console.log(event);
63614 * }
63615 * </code>
63616 * </div>
63617 *
63618 * @alt
63619 * black 50x50 rect turns white with mouse click/press.
63620 * no image displayed
63621 */
63622 _main.default.prototype._onmousedown = function(e) {
63623 var context = this._isGlobal ? window : this;
63624 var executeDefault;
63625 this._setProperty('mouseIsPressed', true);
63626 this._setMouseButton(e);
63627 this._updateNextMouseCoords(e);
63628
63629 if (typeof context.mousePressed === 'function') {
63630 executeDefault = context.mousePressed(e);
63631 if (executeDefault === false) {
63632 e.preventDefault();
63633 }
63634 // only safari needs this manual fallback for consistency
63635 } else if (
63636 navigator.userAgent.toLowerCase().includes('safari') &&
63637 typeof context.touchStarted === 'function'
63638 ) {
63639 executeDefault = context.touchStarted(e);
63640 if (executeDefault === false) {
63641 e.preventDefault();
63642 }
63643 }
63644 };
63645
63646 /**
63647 * The <a href="#/p5/mouseReleased">mouseReleased()</a> function is called every time a mouse button is
63648 * released. If no <a href="#/p5/mouseReleased">mouseReleased()</a> function is defined, the <a href="#/p5/touchEnded">touchEnded()</a>
63649 * function will be called instead if it is defined.<br><br>
63650 * Browsers may have different default
63651 * behaviors attached to various mouse events. To prevent any default
63652 * behavior for this event, add "return false" to the end of the method.
63653 *
63654 * @method mouseReleased
63655 * @param {Object} [event] optional MouseEvent callback argument.
63656 * @example
63657 * <div>
63658 * <code>
63659 * // Click within the image to change
63660 * // the value of the rectangle
63661 * // after the mouse has been clicked
63662 *
63663 * let value = 0;
63664 * function draw() {
63665 * fill(value);
63666 * rect(25, 25, 50, 50);
63667 * }
63668 * function mouseReleased() {
63669 * if (value === 0) {
63670 * value = 255;
63671 * } else {
63672 * value = 0;
63673 * }
63674 * }
63675 * </code>
63676 * </div>
63677 *
63678 * <div class="norender">
63679 * <code>
63680 * function mouseReleased() {
63681 * ellipse(mouseX, mouseY, 5, 5);
63682 * // prevent default
63683 * return false;
63684 * }
63685 * </code>
63686 * </div>
63687 *
63688 * <div class="norender">
63689 * <code>
63690 * // returns a MouseEvent object
63691 * // as a callback argument
63692 * function mouseReleased(event) {
63693 * console.log(event);
63694 * }
63695 * </code>
63696 * </div>
63697 *
63698 * @alt
63699 * black 50x50 rect turns white with mouse click/press.
63700 * no image displayed
63701 */
63702 _main.default.prototype._onmouseup = function(e) {
63703 var context = this._isGlobal ? window : this;
63704 var executeDefault;
63705 this._setProperty('mouseIsPressed', false);
63706 if (typeof context.mouseReleased === 'function') {
63707 executeDefault = context.mouseReleased(e);
63708 if (executeDefault === false) {
63709 e.preventDefault();
63710 }
63711 } else if (typeof context.touchEnded === 'function') {
63712 executeDefault = context.touchEnded(e);
63713 if (executeDefault === false) {
63714 e.preventDefault();
63715 }
63716 }
63717 };
63718
63719 _main.default.prototype._ondragend = _main.default.prototype._onmouseup;
63720 _main.default.prototype._ondragover = _main.default.prototype._onmousemove;
63721
63722 /**
63723 * The <a href="#/p5/mouseClicked">mouseClicked()</a> function is called once after a mouse button has been
63724 * pressed and then released.<br><br>
63725 * Browsers handle clicks differently, so this function is only guaranteed to be
63726 * run when the left mouse button is clicked. To handle other mouse buttons
63727 * being pressed or released, see <a href="#/p5/mousePressed">mousePressed()</a> or <a href="#/p5/mouseReleased">mouseReleased()</a>.<br><br>
63728 * Browsers may have different default
63729 * behaviors attached to various mouse events. To prevent any default
63730 * behavior for this event, add "return false" to the end of the method.
63731 *
63732 * @method mouseClicked
63733 * @param {Object} [event] optional MouseEvent callback argument.
63734 * @example
63735 * <div>
63736 * <code>
63737 * // Click within the image to change
63738 * // the value of the rectangle
63739 * // after the mouse has been clicked
63740 *
63741 * let value = 0;
63742 * function draw() {
63743 * fill(value);
63744 * rect(25, 25, 50, 50);
63745 * }
63746 *
63747 * function mouseClicked() {
63748 * if (value === 0) {
63749 * value = 255;
63750 * } else {
63751 * value = 0;
63752 * }
63753 * }
63754 * </code>
63755 * </div>
63756 *
63757 * <div class="norender">
63758 * <code>
63759 * function mouseClicked() {
63760 * ellipse(mouseX, mouseY, 5, 5);
63761 * // prevent default
63762 * return false;
63763 * }
63764 * </code>
63765 * </div>
63766 *
63767 * <div class="norender">
63768 * <code>
63769 * // returns a MouseEvent object
63770 * // as a callback argument
63771 * function mouseClicked(event) {
63772 * console.log(event);
63773 * }
63774 * </code>
63775 * </div>
63776 *
63777 * @alt
63778 * black 50x50 rect turns white with mouse click/press.
63779 * no image displayed
63780 */
63781 _main.default.prototype._onclick = function(e) {
63782 var context = this._isGlobal ? window : this;
63783 if (typeof context.mouseClicked === 'function') {
63784 var executeDefault = context.mouseClicked(e);
63785 if (executeDefault === false) {
63786 e.preventDefault();
63787 }
63788 }
63789 };
63790
63791 /**
63792 * The <a href="#/p5/doubleClicked">doubleClicked()</a> function is executed every time a event
63793 * listener has detected a dblclick event which is a part of the
63794 * DOM L3 specification. The doubleClicked event is fired when a
63795 * pointing device button (usually a mouse's primary button)
63796 * is clicked twice on a single element. For more info on the
63797 * dblclick event refer to mozilla's documentation here:
63798 * https://developer.mozilla.org/en-US/docs/Web/Events/dblclick
63799 *
63800 * @method doubleClicked
63801 * @param {Object} [event] optional MouseEvent callback argument.
63802 * @example
63803 * <div>
63804 * <code>
63805 * // Click within the image to change
63806 * // the value of the rectangle
63807 * // after the mouse has been double clicked
63808 *
63809 * let value = 0;
63810 * function draw() {
63811 * fill(value);
63812 * rect(25, 25, 50, 50);
63813 * }
63814 *
63815 * function doubleClicked() {
63816 * if (value === 0) {
63817 * value = 255;
63818 * } else {
63819 * value = 0;
63820 * }
63821 * }
63822 * </code>
63823 * </div>
63824 *
63825 * <div class="norender">
63826 * <code>
63827 * function doubleClicked() {
63828 * ellipse(mouseX, mouseY, 5, 5);
63829 * // prevent default
63830 * return false;
63831 * }
63832 * </code>
63833 * </div>
63834 *
63835 * <div class="norender">
63836 * <code>
63837 * // returns a MouseEvent object
63838 * // as a callback argument
63839 * function doubleClicked(event) {
63840 * console.log(event);
63841 * }
63842 * </code>
63843 * </div>
63844 *
63845 * @alt
63846 * black 50x50 rect turns white with mouse doubleClick/press.
63847 * no image displayed
63848 */
63849
63850 _main.default.prototype._ondblclick = function(e) {
63851 var context = this._isGlobal ? window : this;
63852 if (typeof context.doubleClicked === 'function') {
63853 var executeDefault = context.doubleClicked(e);
63854 if (executeDefault === false) {
63855 e.preventDefault();
63856 }
63857 }
63858 };
63859
63860 /**
63861 * For use with WebGL orbitControl.
63862 * @property {Number} _mouseWheelDeltaY
63863 * @readOnly
63864 * @private
63865 */
63866 _main.default.prototype._mouseWheelDeltaY = 0;
63867
63868 /**
63869 * For use with WebGL orbitControl.
63870 * @property {Number} _pmouseWheelDeltaY
63871 * @readOnly
63872 * @private
63873 */
63874 _main.default.prototype._pmouseWheelDeltaY = 0;
63875
63876 /**
63877 * The function <a href="#/p5/mouseWheel">mouseWheel()</a> is executed every time a vertical mouse wheel
63878 * event is detected either triggered by an actual mouse wheel or by a
63879 * touchpad.<br><br>
63880 * The event.delta property returns the amount the mouse wheel
63881 * have scrolled. The values can be positive or negative depending on the
63882 * scroll direction (on OS X with "natural" scrolling enabled, the signs
63883 * are inverted).<br><br>
63884 * Browsers may have different default behaviors attached to various
63885 * mouse events. To prevent any default behavior for this event, add
63886 * "return false" to the end of the method.<br><br>
63887 * Due to the current support of the "wheel" event on Safari, the function
63888 * may only work as expected if "return false" is included while using Safari.
63889 *
63890 * @method mouseWheel
63891 * @param {Object} [event] optional WheelEvent callback argument.
63892 *
63893 * @example
63894 * <div>
63895 * <code>
63896 * let pos = 25;
63897 *
63898 * function draw() {
63899 * background(237, 34, 93);
63900 * fill(0);
63901 * rect(25, pos, 50, 50);
63902 * }
63903 *
63904 * function mouseWheel(event) {
63905 * print(event.delta);
63906 * //move the square according to the vertical scroll amount
63907 * pos += event.delta;
63908 * //uncomment to block page scrolling
63909 * //return false;
63910 * }
63911 * </code>
63912 * </div>
63913 *
63914 * @alt
63915 * black 50x50 rect moves up and down with vertical scroll. fuchsia background
63916 */
63917 _main.default.prototype._onwheel = function(e) {
63918 var context = this._isGlobal ? window : this;
63919 this._setProperty('_mouseWheelDeltaY', e.deltaY);
63920 if (typeof context.mouseWheel === 'function') {
63921 e.delta = e.deltaY;
63922 var executeDefault = context.mouseWheel(e);
63923 if (executeDefault === false) {
63924 e.preventDefault();
63925 }
63926 }
63927 };
63928
63929 /**
63930 * The function <a href="#/p5/requestPointerLock">requestPointerLock()</a>
63931 * locks the pointer to its current position and makes it invisible.
63932 * Use <a href="#/p5/movedX">movedX</a> and <a href="#/p5/movedY">movedY</a> to get the difference the mouse was moved since
63933 * the last call of draw.
63934 * Note that not all browsers support this feature.
63935 * This enables you to create experiences that aren't limited by the mouse moving out of the screen
63936 * even if it is repeatedly moved into one direction.
63937 * For example, a first person perspective experience.
63938 *
63939 * @method requestPointerLock
63940 * @example
63941 * <div class="notest">
63942 * <code>
63943 * let cam;
63944 * function setup() {
63945 * createCanvas(100, 100, WEBGL);
63946 * requestPointerLock();
63947 * cam = createCamera();
63948 * }
63949 *
63950 * function draw() {
63951 * background(255);
63952 * cam.pan(-movedX * 0.001);
63953 * cam.tilt(movedY * 0.001);
63954 * sphere(25);
63955 * }
63956 * </code>
63957 * </div>
63958 *
63959 * @alt
63960 * 3D scene moves according to mouse mouse movement in a first person perspective
63961 */
63962 _main.default.prototype.requestPointerLock = function() {
63963 // pointer lock object forking for cross browser
63964 var canvas = this._curElement.elt;
63965 canvas.requestPointerLock =
63966 canvas.requestPointerLock || canvas.mozRequestPointerLock;
63967 if (!canvas.requestPointerLock) {
63968 console.log('requestPointerLock is not implemented in this browser');
63969 return false;
63970 }
63971 canvas.requestPointerLock();
63972 return true;
63973 };
63974
63975 /**
63976 * The function <a href="#/p5/exitPointerLock">exitPointerLock()</a>
63977 * exits a previously triggered <a href="#/p5/requestPointerLock">pointer Lock</a>
63978 * for example to make ui elements usable etc
63979 *
63980 * @method exitPointerLock
63981 * @example
63982 * <div class="notest">
63983 * <code>
63984 * //click the canvas to lock the pointer
63985 * //click again to exit (otherwise escape)
63986 * let locked = false;
63987 * function draw() {
63988 * background(237, 34, 93);
63989 * }
63990 * function mouseClicked() {
63991 * if (!locked) {
63992 * locked = true;
63993 * requestPointerLock();
63994 * } else {
63995 * exitPointerLock();
63996 * locked = false;
63997 * }
63998 * }
63999 * </code>
64000 * </div>
64001 *
64002 * @alt
64003 * cursor gets locked / unlocked on mouse-click
64004 */
64005 _main.default.prototype.exitPointerLock = function() {
64006 document.exitPointerLock();
64007 };
64008 var _default = _main.default;
64009 exports.default = _default;
64010 },
64011 { '../core/constants': 43, '../core/main': 54 }
64012 ],
64013 74: [
64014 function(_dereq_, module, exports) {
64015 'use strict';
64016 Object.defineProperty(exports, '__esModule', { value: true });
64017 exports.default = void 0;
64018
64019 var _main = _interopRequireDefault(_dereq_('../core/main'));
64020 function _interopRequireDefault(obj) {
64021 return obj && obj.__esModule ? obj : { default: obj };
64022 }
64023 /**
64024 * @module Events
64025 * @submodule Touch
64026 * @for p5
64027 * @requires core
64028 */ /**
64029 * The system variable touches[] contains an array of the positions of all
64030 * current touch points, relative to (0, 0) of the canvas, and IDs identifying a
64031 * unique touch as it moves. Each element in the array is an object with x, y,
64032 * and id properties.
64033 *
64034 * The touches[] array is not supported on Safari and IE on touch-based
64035 * desktops (laptops).
64036 *
64037 * @property {Object[]} touches
64038 * @readOnly
64039 *
64040 * @example
64041 * <div>
64042 * <code>
64043 * // On a touchscreen device, touch
64044 * // the canvas using one or more fingers
64045 * // at the same time
64046 * function draw() {
64047 * clear();
64048 * let display = touches.length + ' touches';
64049 * text(display, 5, 10);
64050 * }
64051 * </code>
64052 * </div>
64053 *
64054 * @alt
64055 * Number of touches currently registered are displayed on the canvas
64056 */ _main.default.prototype.touches = [];
64057 _main.default.prototype._updateTouchCoords = function(e) {
64058 if (this._curElement !== null) {
64059 var touches = [];
64060 for (var i = 0; i < e.touches.length; i++) {
64061 touches[i] = getTouchInfo(
64062 this._curElement.elt,
64063 this.width,
64064 this.height,
64065 e,
64066 i
64067 );
64068 }
64069 this._setProperty('touches', touches);
64070 }
64071 };
64072
64073 function getTouchInfo(canvas, w, h, e) {
64074 var i = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0;
64075 var rect = canvas.getBoundingClientRect();
64076 var sx = canvas.scrollWidth / w || 1;
64077 var sy = canvas.scrollHeight / h || 1;
64078 var touch = e.touches[i] || e.changedTouches[i];
64079 return {
64080 x: (touch.clientX - rect.left) / sx,
64081 y: (touch.clientY - rect.top) / sy,
64082 winX: touch.clientX,
64083 winY: touch.clientY,
64084 id: touch.identifier
64085 };
64086 }
64087
64088 /**
64089 * The touchStarted() function is called once after every time a touch is
64090 * registered. If no <a href="#/p5/touchStarted">touchStarted()</a> function is defined, the <a href="#/p5/mousePressed">mousePressed()</a>
64091 * function will be called instead if it is defined.<br><br>
64092 * Browsers may have different default behaviors attached to various touch
64093 * events. To prevent any default behavior for this event, add "return false"
64094 * to the end of the method.
64095 *
64096 * @method touchStarted
64097 * @param {Object} [event] optional TouchEvent callback argument.
64098 * @example
64099 * <div>
64100 * <code>
64101 * // Touch within the image to change
64102 * // the value of the rectangle
64103 *
64104 * let value = 0;
64105 * function draw() {
64106 * fill(value);
64107 * rect(25, 25, 50, 50);
64108 * }
64109 * function touchStarted() {
64110 * if (value === 0) {
64111 * value = 255;
64112 * } else {
64113 * value = 0;
64114 * }
64115 * }
64116 * </code>
64117 * </div>
64118 *
64119 * <div class="norender">
64120 * <code>
64121 * function touchStarted() {
64122 * ellipse(mouseX, mouseY, 5, 5);
64123 * // prevent default
64124 * return false;
64125 * }
64126 * </code>
64127 * </div>
64128 *
64129 * <div class="norender">
64130 * <code>
64131 * // returns a TouchEvent object
64132 * // as a callback argument
64133 * function touchStarted(event) {
64134 * console.log(event);
64135 * }
64136 * </code>
64137 * </div>
64138 *
64139 * @alt
64140 * 50x50 black rect turns white with touch event.
64141 * no image displayed
64142 */
64143 _main.default.prototype._ontouchstart = function(e) {
64144 var context = this._isGlobal ? window : this;
64145 var executeDefault;
64146 this._setProperty('mouseIsPressed', true);
64147 this._updateTouchCoords(e);
64148 this._updateNextMouseCoords(e);
64149 this._updateMouseCoords(); // reset pmouseXY at the start of each touch event
64150
64151 if (typeof context.touchStarted === 'function') {
64152 executeDefault = context.touchStarted(e);
64153 if (executeDefault === false) {
64154 e.preventDefault();
64155 }
64156 // only safari needs this manual fallback for consistency
64157 } else if (
64158 navigator.userAgent.toLowerCase().includes('safari') &&
64159 typeof context.mousePressed === 'function'
64160 ) {
64161 executeDefault = context.mousePressed(e);
64162 if (executeDefault === false) {
64163 e.preventDefault();
64164 }
64165 }
64166 };
64167
64168 /**
64169 * The <a href="#/p5/touchMoved">touchMoved()</a> function is called every time a touch move is registered.
64170 * If no <a href="#/p5/touchMoved">touchMoved()</a> function is defined, the <a href="#/p5/mouseDragged">mouseDragged()</a> function will
64171 * be called instead if it is defined.<br><br>
64172 * Browsers may have different default behaviors attached to various touch
64173 * events. To prevent any default behavior for this event, add "return false"
64174 * to the end of the method.
64175 *
64176 * @method touchMoved
64177 * @param {Object} [event] optional TouchEvent callback argument.
64178 * @example
64179 * <div>
64180 * <code>
64181 * // Move your finger across the page
64182 * // to change its value
64183 *
64184 * let value = 0;
64185 * function draw() {
64186 * fill(value);
64187 * rect(25, 25, 50, 50);
64188 * }
64189 * function touchMoved() {
64190 * value = value + 5;
64191 * if (value > 255) {
64192 * value = 0;
64193 * }
64194 * }
64195 * </code>
64196 * </div>
64197 *
64198 * <div class="norender">
64199 * <code>
64200 * function touchMoved() {
64201 * ellipse(mouseX, mouseY, 5, 5);
64202 * // prevent default
64203 * return false;
64204 * }
64205 * </code>
64206 * </div>
64207 *
64208 * <div class="norender">
64209 * <code>
64210 * // returns a TouchEvent object
64211 * // as a callback argument
64212 * function touchMoved(event) {
64213 * console.log(event);
64214 * }
64215 * </code>
64216 * </div>
64217 *
64218 * @alt
64219 * 50x50 black rect turns lighter with touch until white. resets
64220 * no image displayed
64221 */
64222 _main.default.prototype._ontouchmove = function(e) {
64223 var context = this._isGlobal ? window : this;
64224 var executeDefault;
64225 this._updateTouchCoords(e);
64226 this._updateNextMouseCoords(e);
64227 if (typeof context.touchMoved === 'function') {
64228 executeDefault = context.touchMoved(e);
64229 if (executeDefault === false) {
64230 e.preventDefault();
64231 }
64232 } else if (typeof context.mouseDragged === 'function') {
64233 executeDefault = context.mouseDragged(e);
64234 if (executeDefault === false) {
64235 e.preventDefault();
64236 }
64237 }
64238 };
64239
64240 /**
64241 * The <a href="#/p5/touchEnded">touchEnded()</a> function is called every time a touch ends. If no
64242 * <a href="#/p5/touchEnded">touchEnded()</a> function is defined, the <a href="#/p5/mouseReleased">mouseReleased()</a> function will be
64243 * called instead if it is defined.<br><br>
64244 * Browsers may have different default behaviors attached to various touch
64245 * events. To prevent any default behavior for this event, add "return false"
64246 * to the end of the method.
64247 *
64248 * @method touchEnded
64249 * @param {Object} [event] optional TouchEvent callback argument.
64250 * @example
64251 * <div>
64252 * <code>
64253 * // Release touch within the image to
64254 * // change the value of the rectangle
64255 *
64256 * let value = 0;
64257 * function draw() {
64258 * fill(value);
64259 * rect(25, 25, 50, 50);
64260 * }
64261 * function touchEnded() {
64262 * if (value === 0) {
64263 * value = 255;
64264 * } else {
64265 * value = 0;
64266 * }
64267 * }
64268 * </code>
64269 * </div>
64270 *
64271 * <div class="norender">
64272 * <code>
64273 * function touchEnded() {
64274 * ellipse(mouseX, mouseY, 5, 5);
64275 * // prevent default
64276 * return false;
64277 * }
64278 * </code>
64279 * </div>
64280 *
64281 * <div class="norender">
64282 * <code>
64283 * // returns a TouchEvent object
64284 * // as a callback argument
64285 * function touchEnded(event) {
64286 * console.log(event);
64287 * }
64288 * </code>
64289 * </div>
64290 *
64291 * @alt
64292 * 50x50 black rect turns white with touch.
64293 * no image displayed
64294 */
64295 _main.default.prototype._ontouchend = function(e) {
64296 this._setProperty('mouseIsPressed', false);
64297 this._updateTouchCoords(e);
64298 this._updateNextMouseCoords(e);
64299 var context = this._isGlobal ? window : this;
64300 var executeDefault;
64301 if (typeof context.touchEnded === 'function') {
64302 executeDefault = context.touchEnded(e);
64303 if (executeDefault === false) {
64304 e.preventDefault();
64305 }
64306 } else if (typeof context.mouseReleased === 'function') {
64307 executeDefault = context.mouseReleased(e);
64308 if (executeDefault === false) {
64309 e.preventDefault();
64310 }
64311 }
64312 };
64313 var _default = _main.default;
64314 exports.default = _default;
64315 },
64316 { '../core/main': 54 }
64317 ],
64318 75: [
64319 function(_dereq_, module, exports) {
64320 'use strict';
64321 Object.defineProperty(exports, '__esModule', { value: true });
64322 exports.default = void 0; /*global ImageData:false */
64323
64324 /**
64325 * This module defines the filters for use with image buffers.
64326 *
64327 * This module is basically a collection of functions stored in an object
64328 * as opposed to modules. The functions are destructive, modifying
64329 * the passed in canvas rather than creating a copy.
64330 *
64331 * Generally speaking users of this module will use the Filters.apply method
64332 * on a canvas to create an effect.
64333 *
64334 * A number of functions are borrowed/adapted from
64335 * http://www.html5rocks.com/en/tutorials/canvas/imagefilters/
64336 * or the java processing implementation.
64337 */
64338
64339 var Filters = {};
64340
64341 /*
64342 * Helper functions
64343 */
64344
64345 /**
64346 * Returns the pixel buffer for a canvas
64347 *
64348 * @private
64349 *
64350 * @param {Canvas|ImageData} canvas the canvas to get pixels from
64351 * @return {Uint8ClampedArray} a one-dimensional array containing
64352 * the data in thc RGBA order, with integer
64353 * values between 0 and 255
64354 */
64355 Filters._toPixels = function(canvas) {
64356 if (canvas instanceof ImageData) {
64357 return canvas.data;
64358 } else {
64359 return canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height)
64360 .data;
64361 }
64362 };
64363
64364 /**
64365 * Returns a 32 bit number containing ARGB data at ith pixel in the
64366 * 1D array containing pixels data.
64367 *
64368 * @private
64369 *
64370 * @param {Uint8ClampedArray} data array returned by _toPixels()
64371 * @param {Integer} i index of a 1D Image Array
64372 * @return {Integer} 32 bit integer value representing
64373 * ARGB value.
64374 */
64375 Filters._getARGB = function(data, i) {
64376 var offset = i * 4;
64377 return (
64378 ((data[offset + 3] << 24) & 0xff000000) |
64379 ((data[offset] << 16) & 0x00ff0000) |
64380 ((data[offset + 1] << 8) & 0x0000ff00) |
64381 (data[offset + 2] & 0x000000ff)
64382 );
64383 };
64384
64385 /**
64386 * Modifies pixels RGBA values to values contained in the data object.
64387 *
64388 * @private
64389 *
64390 * @param {Uint8ClampedArray} pixels array returned by _toPixels()
64391 * @param {Int32Array} data source 1D array where each value
64392 * represents ARGB values
64393 */
64394 Filters._setPixels = function(pixels, data) {
64395 var offset = 0;
64396 for (var i = 0, al = pixels.length; i < al; i++) {
64397 offset = i * 4;
64398 pixels[offset + 0] = (data[i] & 0x00ff0000) >>> 16;
64399 pixels[offset + 1] = (data[i] & 0x0000ff00) >>> 8;
64400 pixels[offset + 2] = data[i] & 0x000000ff;
64401 pixels[offset + 3] = (data[i] & 0xff000000) >>> 24;
64402 }
64403 };
64404
64405 /**
64406 * Returns the ImageData object for a canvas
64407 * https://developer.mozilla.org/en-US/docs/Web/API/ImageData
64408 *
64409 * @private
64410 *
64411 * @param {Canvas|ImageData} canvas canvas to get image data from
64412 * @return {ImageData} Holder of pixel data (and width and
64413 * height) for a canvas
64414 */
64415 Filters._toImageData = function(canvas) {
64416 if (canvas instanceof ImageData) {
64417 return canvas;
64418 } else {
64419 return canvas
64420 .getContext('2d')
64421 .getImageData(0, 0, canvas.width, canvas.height);
64422 }
64423 };
64424
64425 /**
64426 * Returns a blank ImageData object.
64427 *
64428 * @private
64429 *
64430 * @param {Integer} width
64431 * @param {Integer} height
64432 * @return {ImageData}
64433 */
64434 Filters._createImageData = function(width, height) {
64435 Filters._tmpCanvas = document.createElement('canvas');
64436 Filters._tmpCtx = Filters._tmpCanvas.getContext('2d');
64437 return this._tmpCtx.createImageData(width, height);
64438 };
64439
64440 /**
64441 * Applys a filter function to a canvas.
64442 *
64443 * The difference between this and the actual filter functions defined below
64444 * is that the filter functions generally modify the pixel buffer but do
64445 * not actually put that data back to the canvas (where it would actually
64446 * update what is visible). By contrast this method does make the changes
64447 * actually visible in the canvas.
64448 *
64449 * The apply method is the method that callers of this module would generally
64450 * use. It has been separated from the actual filters to support an advanced
64451 * use case of creating a filter chain that executes without actually updating
64452 * the canvas in between everystep.
64453 *
64454 * @private
64455 * @param {HTMLCanvasElement} canvas [description]
64456 * @param {function(ImageData,Object)} func [description]
64457 * @param {Object} filterParam [description]
64458 */
64459 Filters.apply = function(canvas, func, filterParam) {
64460 var pixelsState = canvas.getContext('2d');
64461 var imageData = pixelsState.getImageData(0, 0, canvas.width, canvas.height);
64462
64463 //Filters can either return a new ImageData object, or just modify
64464 //the one they received.
64465 var newImageData = func(imageData, filterParam);
64466 if (newImageData instanceof ImageData) {
64467 pixelsState.putImageData(
64468 newImageData,
64469 0,
64470 0,
64471 0,
64472 0,
64473 canvas.width,
64474 canvas.height
64475 );
64476 } else {
64477 pixelsState.putImageData(imageData, 0, 0, 0, 0, canvas.width, canvas.height);
64478 }
64479 };
64480
64481 /*
64482 * Filters
64483 */
64484
64485 /**
64486 * Converts the image to black and white pixels depending if they are above or
64487 * below the threshold defined by the level parameter. The parameter must be
64488 * between 0.0 (black) and 1.0 (white). If no level is specified, 0.5 is used.
64489 *
64490 * Borrowed from http://www.html5rocks.com/en/tutorials/canvas/imagefilters/
64491 *
64492 * @private
64493 * @param {Canvas} canvas
64494 * @param {Float} level
64495 */
64496 Filters.threshold = function(canvas, level) {
64497 var pixels = Filters._toPixels(canvas);
64498
64499 if (level === undefined) {
64500 level = 0.5;
64501 }
64502 var thresh = Math.floor(level * 255);
64503
64504 for (var i = 0; i < pixels.length; i += 4) {
64505 var r = pixels[i];
64506 var g = pixels[i + 1];
64507 var b = pixels[i + 2];
64508 var gray = 0.2126 * r + 0.7152 * g + 0.0722 * b;
64509 var val = void 0;
64510 if (gray >= thresh) {
64511 val = 255;
64512 } else {
64513 val = 0;
64514 }
64515 pixels[i] = pixels[i + 1] = pixels[i + 2] = val;
64516 }
64517 };
64518
64519 /**
64520 * Converts any colors in the image to grayscale equivalents.
64521 * No parameter is used.
64522 *
64523 * Borrowed from http://www.html5rocks.com/en/tutorials/canvas/imagefilters/
64524 *
64525 * @private
64526 * @param {Canvas} canvas
64527 */
64528 Filters.gray = function(canvas) {
64529 var pixels = Filters._toPixels(canvas);
64530
64531 for (var i = 0; i < pixels.length; i += 4) {
64532 var r = pixels[i];
64533 var g = pixels[i + 1];
64534 var b = pixels[i + 2];
64535
64536 // CIE luminance for RGB
64537 var gray = 0.2126 * r + 0.7152 * g + 0.0722 * b;
64538 pixels[i] = pixels[i + 1] = pixels[i + 2] = gray;
64539 }
64540 };
64541
64542 /**
64543 * Sets the alpha channel to entirely opaque. No parameter is used.
64544 *
64545 * @private
64546 * @param {Canvas} canvas
64547 */
64548 Filters.opaque = function(canvas) {
64549 var pixels = Filters._toPixels(canvas);
64550
64551 for (var i = 0; i < pixels.length; i += 4) {
64552 pixels[i + 3] = 255;
64553 }
64554
64555 return pixels;
64556 };
64557
64558 /**
64559 * Sets each pixel to its inverse value. No parameter is used.
64560 * @private
64561 * @param {Canvas} canvas
64562 */
64563 Filters.invert = function(canvas) {
64564 var pixels = Filters._toPixels(canvas);
64565
64566 for (var i = 0; i < pixels.length; i += 4) {
64567 pixels[i] = 255 - pixels[i];
64568 pixels[i + 1] = 255 - pixels[i + 1];
64569 pixels[i + 2] = 255 - pixels[i + 2];
64570 }
64571 };
64572
64573 /**
64574 * Limits each channel of the image to the number of colors specified as
64575 * the parameter. The parameter can be set to values between 2 and 255, but
64576 * results are most noticeable in the lower ranges.
64577 *
64578 * Adapted from java based processing implementation
64579 *
64580 * @private
64581 * @param {Canvas} canvas
64582 * @param {Integer} level
64583 */
64584 Filters.posterize = function(canvas, level) {
64585 var pixels = Filters._toPixels(canvas);
64586
64587 if (level < 2 || level > 255) {
64588 throw new Error(
64589 'Level must be greater than 2 and less than 255 for posterize'
64590 );
64591 }
64592
64593 var levels1 = level - 1;
64594 for (var i = 0; i < pixels.length; i += 4) {
64595 var rlevel = pixels[i];
64596 var glevel = pixels[i + 1];
64597 var blevel = pixels[i + 2];
64598
64599 pixels[i] = ((rlevel * level) >> 8) * 255 / levels1;
64600 pixels[i + 1] = ((glevel * level) >> 8) * 255 / levels1;
64601 pixels[i + 2] = ((blevel * level) >> 8) * 255 / levels1;
64602 }
64603 };
64604
64605 /**
64606 * reduces the bright areas in an image
64607 * @private
64608 * @param {Canvas} canvas
64609 */
64610 Filters.dilate = function(canvas) {
64611 var pixels = Filters._toPixels(canvas);
64612 var currIdx = 0;
64613 var maxIdx = pixels.length ? pixels.length / 4 : 0;
64614 var out = new Int32Array(maxIdx);
64615 var currRowIdx, maxRowIdx, colOrig, colOut, currLum;
64616
64617 var idxRight, idxLeft, idxUp, idxDown;
64618 var colRight, colLeft, colUp, colDown;
64619 var lumRight, lumLeft, lumUp, lumDown;
64620
64621 while (currIdx < maxIdx) {
64622 currRowIdx = currIdx;
64623 maxRowIdx = currIdx + canvas.width;
64624 while (currIdx < maxRowIdx) {
64625 colOrig = colOut = Filters._getARGB(pixels, currIdx);
64626 idxLeft = currIdx - 1;
64627 idxRight = currIdx + 1;
64628 idxUp = currIdx - canvas.width;
64629 idxDown = currIdx + canvas.width;
64630
64631 if (idxLeft < currRowIdx) {
64632 idxLeft = currIdx;
64633 }
64634 if (idxRight >= maxRowIdx) {
64635 idxRight = currIdx;
64636 }
64637 if (idxUp < 0) {
64638 idxUp = 0;
64639 }
64640 if (idxDown >= maxIdx) {
64641 idxDown = currIdx;
64642 }
64643 colUp = Filters._getARGB(pixels, idxUp);
64644 colLeft = Filters._getARGB(pixels, idxLeft);
64645 colDown = Filters._getARGB(pixels, idxDown);
64646 colRight = Filters._getARGB(pixels, idxRight);
64647
64648 //compute luminance
64649 currLum =
64650 77 * ((colOrig >> 16) & 0xff) +
64651 151 * ((colOrig >> 8) & 0xff) +
64652 28 * (colOrig & 0xff);
64653 lumLeft =
64654 77 * ((colLeft >> 16) & 0xff) +
64655 151 * ((colLeft >> 8) & 0xff) +
64656 28 * (colLeft & 0xff);
64657 lumRight =
64658 77 * ((colRight >> 16) & 0xff) +
64659 151 * ((colRight >> 8) & 0xff) +
64660 28 * (colRight & 0xff);
64661 lumUp =
64662 77 * ((colUp >> 16) & 0xff) +
64663 151 * ((colUp >> 8) & 0xff) +
64664 28 * (colUp & 0xff);
64665 lumDown =
64666 77 * ((colDown >> 16) & 0xff) +
64667 151 * ((colDown >> 8) & 0xff) +
64668 28 * (colDown & 0xff);
64669
64670 if (lumLeft > currLum) {
64671 colOut = colLeft;
64672 currLum = lumLeft;
64673 }
64674 if (lumRight > currLum) {
64675 colOut = colRight;
64676 currLum = lumRight;
64677 }
64678 if (lumUp > currLum) {
64679 colOut = colUp;
64680 currLum = lumUp;
64681 }
64682 if (lumDown > currLum) {
64683 colOut = colDown;
64684 currLum = lumDown;
64685 }
64686 out[currIdx++] = colOut;
64687 }
64688 }
64689 Filters._setPixels(pixels, out);
64690 };
64691
64692 /**
64693 * increases the bright areas in an image
64694 * @private
64695 * @param {Canvas} canvas
64696 */
64697 Filters.erode = function(canvas) {
64698 var pixels = Filters._toPixels(canvas);
64699 var currIdx = 0;
64700 var maxIdx = pixels.length ? pixels.length / 4 : 0;
64701 var out = new Int32Array(maxIdx);
64702 var currRowIdx, maxRowIdx, colOrig, colOut, currLum;
64703 var idxRight, idxLeft, idxUp, idxDown;
64704 var colRight, colLeft, colUp, colDown;
64705 var lumRight, lumLeft, lumUp, lumDown;
64706
64707 while (currIdx < maxIdx) {
64708 currRowIdx = currIdx;
64709 maxRowIdx = currIdx + canvas.width;
64710 while (currIdx < maxRowIdx) {
64711 colOrig = colOut = Filters._getARGB(pixels, currIdx);
64712 idxLeft = currIdx - 1;
64713 idxRight = currIdx + 1;
64714 idxUp = currIdx - canvas.width;
64715 idxDown = currIdx + canvas.width;
64716
64717 if (idxLeft < currRowIdx) {
64718 idxLeft = currIdx;
64719 }
64720 if (idxRight >= maxRowIdx) {
64721 idxRight = currIdx;
64722 }
64723 if (idxUp < 0) {
64724 idxUp = 0;
64725 }
64726 if (idxDown >= maxIdx) {
64727 idxDown = currIdx;
64728 }
64729 colUp = Filters._getARGB(pixels, idxUp);
64730 colLeft = Filters._getARGB(pixels, idxLeft);
64731 colDown = Filters._getARGB(pixels, idxDown);
64732 colRight = Filters._getARGB(pixels, idxRight);
64733
64734 //compute luminance
64735 currLum =
64736 77 * ((colOrig >> 16) & 0xff) +
64737 151 * ((colOrig >> 8) & 0xff) +
64738 28 * (colOrig & 0xff);
64739 lumLeft =
64740 77 * ((colLeft >> 16) & 0xff) +
64741 151 * ((colLeft >> 8) & 0xff) +
64742 28 * (colLeft & 0xff);
64743 lumRight =
64744 77 * ((colRight >> 16) & 0xff) +
64745 151 * ((colRight >> 8) & 0xff) +
64746 28 * (colRight & 0xff);
64747 lumUp =
64748 77 * ((colUp >> 16) & 0xff) +
64749 151 * ((colUp >> 8) & 0xff) +
64750 28 * (colUp & 0xff);
64751 lumDown =
64752 77 * ((colDown >> 16) & 0xff) +
64753 151 * ((colDown >> 8) & 0xff) +
64754 28 * (colDown & 0xff);
64755
64756 if (lumLeft < currLum) {
64757 colOut = colLeft;
64758 currLum = lumLeft;
64759 }
64760 if (lumRight < currLum) {
64761 colOut = colRight;
64762 currLum = lumRight;
64763 }
64764 if (lumUp < currLum) {
64765 colOut = colUp;
64766 currLum = lumUp;
64767 }
64768 if (lumDown < currLum) {
64769 colOut = colDown;
64770 currLum = lumDown;
64771 }
64772
64773 out[currIdx++] = colOut;
64774 }
64775 }
64776 Filters._setPixels(pixels, out);
64777 };
64778
64779 // BLUR
64780
64781 // internal kernel stuff for the gaussian blur filter
64782 var blurRadius;
64783 var blurKernelSize;
64784 var blurKernel;
64785 var blurMult;
64786
64787 /*
64788 * Port of https://github.com/processing/processing/blob/
64789 * main/core/src/processing/core/PImage.java#L1250
64790 *
64791 * Optimized code for building the blur kernel.
64792 * further optimized blur code (approx. 15% for radius=20)
64793 * bigger speed gains for larger radii (~30%)
64794 * added support for various image types (ALPHA, RGB, ARGB)
64795 * [toxi 050728]
64796 */
64797 function buildBlurKernel(r) {
64798 var radius = (r * 3.5) | 0;
64799 radius = radius < 1 ? 1 : radius < 248 ? radius : 248;
64800
64801 if (blurRadius !== radius) {
64802 blurRadius = radius;
64803 blurKernelSize = (1 + blurRadius) << 1;
64804 blurKernel = new Int32Array(blurKernelSize);
64805 blurMult = new Array(blurKernelSize);
64806 for (var l = 0; l < blurKernelSize; l++) {
64807 blurMult[l] = new Int32Array(256);
64808 }
64809
64810 var bk, bki;
64811 var bm, bmi;
64812
64813 for (var i = 1, radiusi = radius - 1; i < radius; i++) {
64814 blurKernel[radius + i] = blurKernel[radiusi] = bki = radiusi * radiusi;
64815 bm = blurMult[radius + i];
64816 bmi = blurMult[radiusi--];
64817 for (var j = 0; j < 256; j++) {
64818 bm[j] = bmi[j] = bki * j;
64819 }
64820 }
64821 bk = blurKernel[radius] = radius * radius;
64822 bm = blurMult[radius];
64823
64824 for (var k = 0; k < 256; k++) {
64825 bm[k] = bk * k;
64826 }
64827 }
64828 }
64829
64830 // Port of https://github.com/processing/processing/blob/
64831 // main/core/src/processing/core/PImage.java#L1433
64832 function blurARGB(canvas, radius) {
64833 var pixels = Filters._toPixels(canvas);
64834 var width = canvas.width;
64835 var height = canvas.height;
64836 var numPackedPixels = width * height;
64837 var argb = new Int32Array(numPackedPixels);
64838 for (var j = 0; j < numPackedPixels; j++) {
64839 argb[j] = Filters._getARGB(pixels, j);
64840 }
64841 var sum, cr, cg, cb, ca;
64842 var read, ri, ym, ymi, bk0;
64843 var a2 = new Int32Array(numPackedPixels);
64844 var r2 = new Int32Array(numPackedPixels);
64845 var g2 = new Int32Array(numPackedPixels);
64846 var b2 = new Int32Array(numPackedPixels);
64847 var yi = 0;
64848 buildBlurKernel(radius);
64849 var x, y, i;
64850 var bm;
64851 for (y = 0; y < height; y++) {
64852 for (x = 0; x < width; x++) {
64853 cb = cg = cr = ca = sum = 0;
64854 read = x - blurRadius;
64855 if (read < 0) {
64856 bk0 = -read;
64857 read = 0;
64858 } else {
64859 if (read >= width) {
64860 break;
64861 }
64862 bk0 = 0;
64863 }
64864 for (i = bk0; i < blurKernelSize; i++) {
64865 if (read >= width) {
64866 break;
64867 }
64868 var c = argb[read + yi];
64869 bm = blurMult[i];
64870 ca += bm[(c & -16777216) >>> 24];
64871 cr += bm[(c & 16711680) >> 16];
64872 cg += bm[(c & 65280) >> 8];
64873 cb += bm[c & 255];
64874 sum += blurKernel[i];
64875 read++;
64876 }
64877 ri = yi + x;
64878 a2[ri] = ca / sum;
64879 r2[ri] = cr / sum;
64880 g2[ri] = cg / sum;
64881 b2[ri] = cb / sum;
64882 }
64883 yi += width;
64884 }
64885 yi = 0;
64886 ym = -blurRadius;
64887 ymi = ym * width;
64888 for (y = 0; y < height; y++) {
64889 for (x = 0; x < width; x++) {
64890 cb = cg = cr = ca = sum = 0;
64891 if (ym < 0) {
64892 bk0 = ri = -ym;
64893 read = x;
64894 } else {
64895 if (ym >= height) {
64896 break;
64897 }
64898 bk0 = 0;
64899 ri = ym;
64900 read = x + ymi;
64901 }
64902 for (i = bk0; i < blurKernelSize; i++) {
64903 if (ri >= height) {
64904 break;
64905 }
64906 bm = blurMult[i];
64907 ca += bm[a2[read]];
64908 cr += bm[r2[read]];
64909 cg += bm[g2[read]];
64910 cb += bm[b2[read]];
64911 sum += blurKernel[i];
64912 ri++;
64913 read += width;
64914 }
64915 argb[x + yi] =
64916 ((ca / sum) << 24) | ((cr / sum) << 16) | ((cg / sum) << 8) | (cb / sum);
64917 }
64918 yi += width;
64919 ymi += width;
64920 ym++;
64921 }
64922 Filters._setPixels(pixels, argb);
64923 }
64924
64925 Filters.blur = function(canvas, radius) {
64926 blurARGB(canvas, radius);
64927 };
64928 var _default = Filters;
64929 exports.default = _default;
64930 },
64931 {}
64932 ],
64933 76: [
64934 function(_dereq_, module, exports) {
64935 'use strict';
64936 Object.defineProperty(exports, '__esModule', { value: true });
64937 exports.default = void 0;
64938
64939 var _main = _interopRequireDefault(_dereq_('../core/main'));
64940 var _omggif = _interopRequireDefault(_dereq_('omggif'));
64941 function _interopRequireDefault(obj) {
64942 return obj && obj.__esModule ? obj : { default: obj };
64943 }
64944 function _toConsumableArray(arr) {
64945 return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread();
64946 }
64947 function _nonIterableSpread() {
64948 throw new TypeError('Invalid attempt to spread non-iterable instance');
64949 }
64950 function _iterableToArray(iter) {
64951 if (
64952 Symbol.iterator in Object(iter) ||
64953 Object.prototype.toString.call(iter) === '[object Arguments]'
64954 )
64955 return Array.from(iter);
64956 }
64957 function _arrayWithoutHoles(arr) {
64958 if (Array.isArray(arr)) {
64959 for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) {
64960 arr2[i] = arr[i];
64961 }
64962 return arr2;
64963 }
64964 }
64965
64966 /**
64967 * Creates a new <a href="#/p5.Image">p5.Image</a> (the datatype for storing images). This provides a
64968 * fresh buffer of pixels to play with. Set the size of the buffer with the
64969 * width and height parameters.
64970 *
64971 * .<a href="#/p5.Image/pixels">pixels</a> gives access to an array containing the values for all the pixels
64972 * in the display window.
64973 * These values are numbers. This array is the size (including an appropriate
64974 * factor for the <a href="#/p5/pixelDensity">pixelDensity</a>) of the display window x4,
64975 * representing the R, G, B, A values in order for each pixel, moving from
64976 * left to right across each row, then down each column. See .<a href="#/p5.Image/pixels">pixels</a> for
64977 * more info. It may also be simpler to use <a href="#/p5.Image/set">set()</a> or <a href="#/p5.Image/get">get()</a>.
64978 *
64979 * Before accessing the pixels of an image, the data must loaded with the
64980 * <a href="#/p5.Image/loadPixels">loadPixels()</a> function. After the array data has been modified, the
64981 * <a href="#/p5.Image/updatePixels">updatePixels()</a> function must be run to update the changes.
64982 *
64983 * @method createImage
64984 * @param {Integer} width width in pixels
64985 * @param {Integer} height height in pixels
64986 * @return {p5.Image} the <a href="#/p5.Image">p5.Image</a> object
64987 * @example
64988 * <div>
64989 * <code>
64990 * let img = createImage(66, 66);
64991 * img.loadPixels();
64992 * for (let i = 0; i < img.width; i++) {
64993 * for (let j = 0; j < img.height; j++) {
64994 * img.set(i, j, color(0, 90, 102));
64995 * }
64996 * }
64997 * img.updatePixels();
64998 * image(img, 17, 17);
64999 * </code>
65000 * </div>
65001 *
65002 * <div>
65003 * <code>
65004 * let img = createImage(66, 66);
65005 * img.loadPixels();
65006 * for (let i = 0; i < img.width; i++) {
65007 * for (let j = 0; j < img.height; j++) {
65008 * img.set(i, j, color(0, 90, 102, (i % img.width) * 2));
65009 * }
65010 * }
65011 * img.updatePixels();
65012 * image(img, 17, 17);
65013 * image(img, 34, 34);
65014 * </code>
65015 * </div>
65016 *
65017 * <div>
65018 * <code>
65019 * let pink = color(255, 102, 204);
65020 * let img = createImage(66, 66);
65021 * img.loadPixels();
65022 * let d = pixelDensity();
65023 * let halfImage = 4 * (img.width * d) * (img.height / 2 * d);
65024 * for (let i = 0; i < halfImage; i += 4) {
65025 * img.pixels[i] = red(pink);
65026 * img.pixels[i + 1] = green(pink);
65027 * img.pixels[i + 2] = blue(pink);
65028 * img.pixels[i + 3] = alpha(pink);
65029 * }
65030 * img.updatePixels();
65031 * image(img, 17, 17);
65032 * </code>
65033 * </div>
65034 *
65035 * @alt
65036 * 66x66 dark turquoise rect in center of canvas.
65037 * 2 gradated dark turquoise rects fade left. 1 center 1 bottom right of canvas
65038 * no image displayed
65039 */
65040 _main.default.prototype.createImage = function(width, height) {
65041 _main.default._validateParameters('createImage', arguments);
65042 return new _main.default.Image(width, height);
65043 };
65044
65045 /**
65046 * Save the current canvas as an image. The browser will either save the
65047 * file immediately, or prompt the user with a dialogue window.
65048 *
65049 * @method saveCanvas
65050 * @param {p5.Element|HTMLCanvasElement} selectedCanvas a variable
65051 * representing a specific html5 canvas (optional)
65052 * @param {String} [filename]
65053 * @param {String} [extension] 'jpg' or 'png'
65054 *
65055 * @example
65056 * <div class='norender notest'><code>
65057 * function setup() {
65058 * let c = createCanvas(100, 100);
65059 * background(255, 0, 0);
65060 * saveCanvas(c, 'myCanvas', 'jpg');
65061 * }
65062 * </code></div>
65063 * <div class='norender notest'><code>
65064 * // note that this example has the same result as above
65065 * // if no canvas is specified, defaults to main canvas
65066 * function setup() {
65067 * let c = createCanvas(100, 100);
65068 * background(255, 0, 0);
65069 * saveCanvas('myCanvas', 'jpg');
65070 *
65071 * // all of the following are valid
65072 * saveCanvas(c, 'myCanvas', 'jpg');
65073 * saveCanvas(c, 'myCanvas.jpg');
65074 * saveCanvas(c, 'myCanvas');
65075 * saveCanvas(c);
65076 * saveCanvas('myCanvas', 'png');
65077 * saveCanvas('myCanvas');
65078 * saveCanvas();
65079 * }
65080 * </code></div>
65081 *
65082 * @alt
65083 * no image displayed
65084 * no image displayed
65085 * no image displayed
65086 */
65087 /**
65088 * @method saveCanvas
65089 * @param {String} [filename]
65090 * @param {String} [extension]
65091 */
65092 _main.default.prototype.saveCanvas = function() {
65093 _main.default._validateParameters('saveCanvas', arguments);
65094
65095 // copy arguments to array
65096 var args = [].slice.call(arguments);
65097 var htmlCanvas, filename, extension;
65098
65099 if (arguments[0] instanceof HTMLCanvasElement) {
65100 htmlCanvas = arguments[0];
65101 args.shift();
65102 } else if (arguments[0] instanceof _main.default.Element) {
65103 htmlCanvas = arguments[0].elt;
65104 args.shift();
65105 } else {
65106 htmlCanvas = this._curElement && this._curElement.elt;
65107 }
65108
65109 if (args.length >= 1) {
65110 filename = args[0];
65111 }
65112 if (args.length >= 2) {
65113 extension = args[1];
65114 }
65115
65116 extension =
65117 extension ||
65118 _main.default.prototype._checkFileExtension(filename, extension)[1] ||
65119 'png';
65120
65121 var mimeType;
65122 switch (extension) {
65123 default:
65124 //case 'png':
65125 mimeType = 'image/png';
65126 break;
65127 case 'jpeg':
65128 case 'jpg':
65129 mimeType = 'image/jpeg';
65130 break;
65131 }
65132
65133 htmlCanvas.toBlob(function(blob) {
65134 _main.default.prototype.downloadFile(blob, filename, extension);
65135 }, mimeType);
65136 };
65137
65138 _main.default.prototype.saveGif = function(pImg, filename) {
65139 var props = pImg.gifProperties;
65140
65141 //convert loopLimit back into Netscape Block formatting
65142 var loopLimit = props.loopLimit;
65143 if (loopLimit === 1) {
65144 loopLimit = null;
65145 } else if (loopLimit === null) {
65146 loopLimit = 0;
65147 }
65148 var buffer = new Uint8Array(pImg.width * pImg.height * props.numFrames);
65149
65150 var allFramesPixelColors = [];
65151
65152 // Used to determine the occurrence of unique palettes and the frames
65153 // which use them
65154 var paletteFreqsAndFrames = {};
65155
65156 // Pass 1:
65157 //loop over frames and get the frequency of each palette
65158 for (var i = 0; i < props.numFrames; i++) {
65159 var paletteSet = new Set();
65160 var data = props.frames[i].image.data;
65161 var dataLength = data.length;
65162 // The color for each pixel in this frame ( for easier lookup later )
65163 var pixelColors = new Uint32Array(pImg.width * pImg.height);
65164 for (var j = 0, k = 0; j < dataLength; j += 4, k++) {
65165 var r = data[j + 0];
65166 var g = data[j + 1];
65167 var b = data[j + 2];
65168 var color = (r << 16) | (g << 8) | (b << 0);
65169 paletteSet.add(color);
65170
65171 // What color does this pixel have in this frame ?
65172 pixelColors[k] = color;
65173 }
65174
65175 // A way to put use the entire palette as an object key
65176 var paletteStr = _toConsumableArray(paletteSet)
65177 .sort()
65178 .toString();
65179 if (paletteFreqsAndFrames[paletteStr] === undefined) {
65180 paletteFreqsAndFrames[paletteStr] = { freq: 1, frames: [i] };
65181 } else {
65182 paletteFreqsAndFrames[paletteStr].freq += 1;
65183 paletteFreqsAndFrames[paletteStr].frames.push(i);
65184 }
65185
65186 allFramesPixelColors.push(pixelColors);
65187 }
65188
65189 var framesUsingGlobalPalette = [];
65190
65191 // Now to build the global palette
65192 // Sort all the unique palettes in descending order of their occurence
65193 var palettesSortedByFreq = Object.keys(paletteFreqsAndFrames).sort(function(
65194 a,
65195 b
65196 ) {
65197 return paletteFreqsAndFrames[b].freq - paletteFreqsAndFrames[a].freq;
65198 });
65199
65200 // The initial global palette is the one with the most occurence
65201 var globalPalette = palettesSortedByFreq[0].split(',').map(function(a) {
65202 return parseInt(a);
65203 });
65204
65205 framesUsingGlobalPalette = framesUsingGlobalPalette.concat(
65206 paletteFreqsAndFrames[globalPalette].frames
65207 );
65208
65209 var globalPaletteSet = new Set(globalPalette);
65210
65211 // Build a more complete global palette
65212 // Iterate over the remaining palettes in the order of
65213 // their occurence and see if the colors in this palette which are
65214 // not in the global palette can be added there, while keeping the length
65215 // of the global palette <= 256
65216 for (var _i = 1; _i < palettesSortedByFreq.length; _i++) {
65217 var palette = palettesSortedByFreq[_i].split(',').map(function(a) {
65218 return parseInt(a);
65219 });
65220
65221 var difference = palette.filter(function(x) {
65222 return !globalPaletteSet.has(x);
65223 });
65224 if (globalPalette.length + difference.length <= 256) {
65225 for (var _j = 0; _j < difference.length; _j++) {
65226 globalPalette.push(difference[_j]);
65227 globalPaletteSet.add(difference[_j]);
65228 }
65229
65230 // All frames using this palette now use the global palette
65231 framesUsingGlobalPalette = framesUsingGlobalPalette.concat(
65232 paletteFreqsAndFrames[palettesSortedByFreq[_i]].frames
65233 );
65234 }
65235 }
65236
65237 framesUsingGlobalPalette = new Set(framesUsingGlobalPalette);
65238
65239 // Build a lookup table of the index of each color in the global palette
65240 // Maps a color to its index
65241 var globalIndicesLookup = {};
65242 for (var _i2 = 0; _i2 < globalPalette.length; _i2++) {
65243 if (!globalIndicesLookup[globalPalette[_i2]]) {
65244 globalIndicesLookup[globalPalette[_i2]] = _i2;
65245 }
65246 }
65247
65248 // force palette to be power of 2
65249 var powof2 = 1;
65250 while (powof2 < globalPalette.length) {
65251 powof2 <<= 1;
65252 }
65253 globalPalette.length = powof2;
65254
65255 // global opts
65256 var opts = {
65257 loop: loopLimit,
65258 palette: new Uint32Array(globalPalette)
65259 };
65260
65261 var gifWriter = new _omggif.default.GifWriter(
65262 buffer,
65263 pImg.width,
65264 pImg.height,
65265 opts
65266 );
65267 var previousFrame = {};
65268
65269 // Pass 2
65270 // Determine if the frame needs a local palette
65271 // Also apply transparency optimization. This function will often blow up
65272 // the size of a GIF if not for transparency. If a pixel in one frame has
65273 // the same color in the previous frame, that pixel can be marked as
65274 // transparent. We decide one particular color as transparent and make all
65275 // transparent pixels take this color. This helps in later in compression.
65276 var _loop = function _loop(_i3) {
65277 var localPaletteRequired = !framesUsingGlobalPalette.has(_i3);
65278 var palette = localPaletteRequired ? [] : globalPalette;
65279 var pixelPaletteIndex = new Uint8Array(pImg.width * pImg.height);
65280
65281 // Lookup table mapping color to its indices
65282 var colorIndicesLookup = {};
65283
65284 // All the colors that cannot be marked transparent in this frame
65285 var cannotBeTransparent = new Set();
65286
65287 for (var _k = 0; _k < allFramesPixelColors[_i3].length; _k++) {
65288 var _color = allFramesPixelColors[_i3][_k];
65289 if (localPaletteRequired) {
65290 if (colorIndicesLookup[_color] === undefined) {
65291 colorIndicesLookup[_color] = palette.length;
65292 palette.push(_color);
65293 }
65294 pixelPaletteIndex[_k] = colorIndicesLookup[_color];
65295 } else {
65296 pixelPaletteIndex[_k] = globalIndicesLookup[_color];
65297 }
65298
65299 if (_i3 > 0) {
65300 // If even one pixel of this color has changed in this frame
65301 // from the previous frame, we cannot mark it as transparent
65302 if (allFramesPixelColors[_i3 - 1][_k] !== _color) {
65303 cannotBeTransparent.add(_color);
65304 }
65305 }
65306 }
65307
65308 var frameOpts = {};
65309
65310 // Transparency optimization
65311 var canBeTransparent = palette.filter(function(a) {
65312 return !cannotBeTransparent.has(a);
65313 });
65314 if (canBeTransparent.length > 0) {
65315 // Select a color to mark as transparent
65316 var transparent = canBeTransparent[0];
65317 var transparentIndex = localPaletteRequired
65318 ? colorIndicesLookup[transparent]
65319 : globalIndicesLookup[transparent];
65320 if (_i3 > 0) {
65321 for (var _k2 = 0; _k2 < allFramesPixelColors[_i3].length; _k2++) {
65322 // If this pixel in this frame has the same color in previous frame
65323 if (
65324 allFramesPixelColors[_i3 - 1][_k2] === allFramesPixelColors[_i3][_k2]
65325 ) {
65326 pixelPaletteIndex[_k2] = transparentIndex;
65327 }
65328 }
65329 frameOpts.transparent = transparentIndex;
65330 // If this frame has any transparency, do not dispose the previous frame
65331 previousFrame.frameOpts.disposal = 1;
65332 }
65333 }
65334 frameOpts.delay = props.frames[_i3].delay / 10; // Move timing back into GIF formatting
65335 if (localPaletteRequired) {
65336 // force palette to be power of 2
65337 var _powof = 1;
65338 while (_powof < palette.length) {
65339 _powof <<= 1;
65340 }
65341 palette.length = _powof;
65342 frameOpts.palette = new Uint32Array(palette);
65343 }
65344 if (_i3 > 0) {
65345 // add the frame that came before the current one
65346 gifWriter.addFrame(
65347 0,
65348 0,
65349 pImg.width,
65350 pImg.height,
65351 previousFrame.pixelPaletteIndex,
65352 previousFrame.frameOpts
65353 );
65354 }
65355 // previous frame object should now have details of this frame
65356 previousFrame = {
65357 pixelPaletteIndex: pixelPaletteIndex,
65358 frameOpts: frameOpts
65359 };
65360 };
65361 for (var _i3 = 0; _i3 < props.numFrames; _i3++) {
65362 _loop(_i3);
65363 }
65364
65365 previousFrame.frameOpts.disposal = 1;
65366 // add the last frame
65367 gifWriter.addFrame(
65368 0,
65369 0,
65370 pImg.width,
65371 pImg.height,
65372 previousFrame.pixelPaletteIndex,
65373 previousFrame.frameOpts
65374 );
65375
65376 var extension = 'gif';
65377 var blob = new Blob([buffer.slice(0, gifWriter.end())], {
65378 type: 'image/gif'
65379 });
65380
65381 _main.default.prototype.downloadFile(blob, filename, extension);
65382 };
65383
65384 /**
65385 * Capture a sequence of frames that can be used to create a movie.
65386 * Accepts a callback. For example, you may wish to send the frames
65387 * to a server where they can be stored or converted into a movie.
65388 * If no callback is provided, the browser will pop up save dialogues in an
65389 * attempt to download all of the images that have just been created. With the
65390 * callback provided the image data isn't saved by default but instead passed
65391 * as an argument to the callback function as an array of objects, with the
65392 * size of array equal to the total number of frames.
65393 *
65394 * Note that <a href="#/p5.Image/saveFrames">saveFrames()</a> will only save the first 15 frames of an animation.
65395 * To export longer animations, you might look into a library like
65396 * <a href="https://github.com/spite/ccapture.js/">ccapture.js</a>.
65397 *
65398 * @method saveFrames
65399 * @param {String} filename
65400 * @param {String} extension 'jpg' or 'png'
65401 * @param {Number} duration Duration in seconds to save the frames for.
65402 * @param {Number} framerate Framerate to save the frames in.
65403 * @param {function(Array)} [callback] A callback function that will be executed
65404 to handle the image data. This function
65405 should accept an array as argument. The
65406 array will contain the specified number of
65407 frames of objects. Each object has three
65408 properties: imageData - an
65409 image/octet-stream, filename and extension.
65410 * @example
65411 * <div><code>
65412 * function draw() {
65413 * background(mouseX);
65414 * }
65415 *
65416 * function mousePressed() {
65417 * saveFrames('out', 'png', 1, 25, data => {
65418 * print(data);
65419 * });
65420 * }
65421 </code></div>
65422 *
65423 * @alt
65424 * canvas background goes from light to dark with mouse x.
65425 */
65426 _main.default.prototype.saveFrames = function(
65427 fName,
65428 ext,
65429 _duration,
65430 _fps,
65431 callback
65432 ) {
65433 _main.default._validateParameters('saveFrames', arguments);
65434 var duration = _duration || 3;
65435 duration = _main.default.prototype.constrain(duration, 0, 15);
65436 duration = duration * 1000;
65437 var fps = _fps || 15;
65438 fps = _main.default.prototype.constrain(fps, 0, 22);
65439 var count = 0;
65440
65441 var makeFrame = _main.default.prototype._makeFrame;
65442 var cnv = this._curElement.elt;
65443 var frames = [];
65444 var frameFactory = setInterval(function() {
65445 frames.push(makeFrame(fName + count, ext, cnv));
65446 count++;
65447 }, 1000 / fps);
65448
65449 setTimeout(function() {
65450 clearInterval(frameFactory);
65451 if (callback) {
65452 callback(frames);
65453 } else {
65454 var _iteratorNormalCompletion = true;
65455 var _didIteratorError = false;
65456 var _iteratorError = undefined;
65457 try {
65458 for (
65459 var _iterator = frames[Symbol.iterator](), _step;
65460 !(_iteratorNormalCompletion = (_step = _iterator.next()).done);
65461 _iteratorNormalCompletion = true
65462 ) {
65463 var f = _step.value;
65464 _main.default.prototype.downloadFile(f.imageData, f.filename, f.ext);
65465 }
65466 } catch (err) {
65467 _didIteratorError = true;
65468 _iteratorError = err;
65469 } finally {
65470 try {
65471 if (!_iteratorNormalCompletion && _iterator.return != null) {
65472 _iterator.return();
65473 }
65474 } finally {
65475 if (_didIteratorError) {
65476 throw _iteratorError;
65477 }
65478 }
65479 }
65480 }
65481 frames = []; // clear frames
65482 }, duration + 0.01);
65483 };
65484
65485 _main.default.prototype._makeFrame = function(filename, extension, _cnv) {
65486 var cnv;
65487 if (this) {
65488 cnv = this._curElement.elt;
65489 } else {
65490 cnv = _cnv;
65491 }
65492 var mimeType;
65493 if (!extension) {
65494 extension = 'png';
65495 mimeType = 'image/png';
65496 } else {
65497 switch (extension.toLowerCase()) {
65498 case 'png':
65499 mimeType = 'image/png';
65500 break;
65501 case 'jpeg':
65502 mimeType = 'image/jpeg';
65503 break;
65504 case 'jpg':
65505 mimeType = 'image/jpeg';
65506 break;
65507 default:
65508 mimeType = 'image/png';
65509 break;
65510 }
65511 }
65512 var downloadMime = 'image/octet-stream';
65513 var imageData = cnv.toDataURL(mimeType);
65514 imageData = imageData.replace(mimeType, downloadMime);
65515
65516 var thisFrame = {};
65517 thisFrame.imageData = imageData;
65518 thisFrame.filename = filename;
65519 thisFrame.ext = extension;
65520 return thisFrame;
65521 };
65522 var _default = _main.default;
65523 exports.default = _default;
65524 },
65525 { '../core/main': 54, omggif: 33 }
65526 ],
65527 77: [
65528 function(_dereq_, module, exports) {
65529 'use strict';
65530 function _typeof(obj) {
65531 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
65532 _typeof = function _typeof(obj) {
65533 return typeof obj;
65534 };
65535 } else {
65536 _typeof = function _typeof(obj) {
65537 return obj &&
65538 typeof Symbol === 'function' &&
65539 obj.constructor === Symbol &&
65540 obj !== Symbol.prototype
65541 ? 'symbol'
65542 : typeof obj;
65543 };
65544 }
65545 return _typeof(obj);
65546 }
65547 Object.defineProperty(exports, '__esModule', { value: true });
65548 exports.default = void 0;
65549
65550 var _main = _interopRequireDefault(_dereq_('../core/main'));
65551 var _filters = _interopRequireDefault(_dereq_('./filters'));
65552 var _helpers = _interopRequireDefault(_dereq_('../core/helpers'));
65553 var constants = _interopRequireWildcard(_dereq_('../core/constants'));
65554 var _omggif = _interopRequireDefault(_dereq_('omggif'));
65555
65556 _dereq_('../core/friendly_errors/validate_params');
65557 _dereq_('../core/friendly_errors/file_errors');
65558 _dereq_('../core/friendly_errors/fes_core');
65559 function _getRequireWildcardCache() {
65560 if (typeof WeakMap !== 'function') return null;
65561 var cache = new WeakMap();
65562 _getRequireWildcardCache = function _getRequireWildcardCache() {
65563 return cache;
65564 };
65565 return cache;
65566 }
65567 function _interopRequireWildcard(obj) {
65568 if (obj && obj.__esModule) {
65569 return obj;
65570 }
65571 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) {
65572 return { default: obj };
65573 }
65574 var cache = _getRequireWildcardCache();
65575 if (cache && cache.has(obj)) {
65576 return cache.get(obj);
65577 }
65578 var newObj = {};
65579 var hasPropertyDescriptor =
65580 Object.defineProperty && Object.getOwnPropertyDescriptor;
65581 for (var key in obj) {
65582 if (Object.prototype.hasOwnProperty.call(obj, key)) {
65583 var desc = hasPropertyDescriptor
65584 ? Object.getOwnPropertyDescriptor(obj, key)
65585 : null;
65586 if (desc && (desc.get || desc.set)) {
65587 Object.defineProperty(newObj, key, desc);
65588 } else {
65589 newObj[key] = obj[key];
65590 }
65591 }
65592 }
65593 newObj.default = obj;
65594 if (cache) {
65595 cache.set(obj, newObj);
65596 }
65597 return newObj;
65598 }
65599 function _interopRequireDefault(obj) {
65600 return obj && obj.__esModule ? obj : { default: obj };
65601 }
65602 /**
65603 * @module Image
65604 * @submodule Loading & Displaying
65605 * @for p5
65606 * @requires core
65607 */ /**
65608 * Loads an image from a path and creates a <a href="#/p5.Image">p5.Image</a> from it.
65609 *
65610 * The image may not be immediately available for rendering
65611 * If you want to ensure that the image is ready before doing
65612 * anything with it, place the <a href="#/p5/loadImage">loadImage()</a> call in <a href="#/p5/preload">preload()</a>.
65613 * You may also supply a callback function to handle the image when it's ready.
65614 *
65615 * The path to the image should be relative to the HTML file
65616 * that links in your sketch. Loading an image from a URL or other
65617 * remote location may be blocked due to your browser's built-in
65618 * security.
65619
65620 * You can also pass in a string of a base64 encoded image as an alternative to the file path.
65621 * Remember to add "data:image/png;base64," in front of the string.
65622 *
65623 * @method loadImage
65624 * @param {String} path Path of the image to be loaded
65625 * @param {function(p5.Image)} [successCallback] Function to be called once
65626 * the image is loaded. Will be passed the
65627 * <a href="#/p5.Image">p5.Image</a>.
65628 * @param {function(Event)} [failureCallback] called with event error if
65629 * the image fails to load.
65630 * @return {p5.Image} the <a href="#/p5.Image">p5.Image</a> object
65631 * @example
65632 * <div>
65633 * <code>
65634 * let img;
65635 * function preload() {
65636 * img = loadImage('assets/laDefense.jpg');
65637 * }
65638 * function setup() {
65639 * image(img, 0, 0);
65640 * }
65641 * </code>
65642 * </div>
65643 * <div>
65644 * <code>
65645 * function setup() {
65646 * // here we use a callback to display the image after loading
65647 * loadImage('assets/laDefense.jpg', img => {
65648 * image(img, 0, 0);
65649 * });
65650 * }
65651 * </code>
65652 * </div>
65653 *
65654 * @alt
65655 * image of the underside of a white umbrella and grided ceililng above
65656 * image of the underside of a white umbrella and grided ceililng above
65657 */ _main.default.prototype.loadImage = function(
65658 path,
65659 successCallback,
65660 failureCallback
65661 ) {
65662 _main.default._validateParameters('loadImage', arguments);
65663 var pImg = new _main.default.Image(1, 1, this);
65664 var self = this;
65665
65666 var req = new Request(path, {
65667 method: 'GET',
65668 mode: 'cors'
65669 });
65670
65671 fetch(path, req).then(function(response) {
65672 // GIF section
65673 var contentType = response.headers.get('content-type');
65674 if (contentType === null) {
65675 console.warn(
65676 'The image you loaded does not have a Content-Type header. If you are using the online editor consider reuploading the asset.'
65677 );
65678 }
65679 if (contentType && contentType.includes('image/gif')) {
65680 response.arrayBuffer().then(
65681 function(arrayBuffer) {
65682 if (arrayBuffer) {
65683 var byteArray = new Uint8Array(arrayBuffer);
65684 _createGif(
65685 byteArray,
65686 pImg,
65687 successCallback,
65688 failureCallback,
65689 function(pImg) {
65690 self._decrementPreload();
65691 }.bind(self)
65692 );
65693 }
65694 },
65695 function(e) {
65696 if (typeof failureCallback === 'function') {
65697 failureCallback(e);
65698 } else {
65699 console.error(e);
65700 }
65701 }
65702 );
65703 } else {
65704 // Non-GIF Section
65705 var img = new Image();
65706
65707 img.onload = function() {
65708 pImg.width = pImg.canvas.width = img.width;
65709 pImg.height = pImg.canvas.height = img.height;
65710
65711 // Draw the image into the backing canvas of the p5.Image
65712 pImg.drawingContext.drawImage(img, 0, 0);
65713 pImg.modified = true;
65714 if (typeof successCallback === 'function') {
65715 successCallback(pImg);
65716 }
65717 self._decrementPreload();
65718 };
65719
65720 img.onerror = function(e) {
65721 _main.default._friendlyFileLoadError(0, img.src);
65722 if (typeof failureCallback === 'function') {
65723 failureCallback(e);
65724 } else {
65725 console.error(e);
65726 }
65727 };
65728
65729 // Set crossOrigin in case image is served with CORS headers.
65730 // This will let us draw to the canvas without tainting it.
65731 // See https://developer.mozilla.org/en-US/docs/HTML/CORS_Enabled_Image
65732 // When using data-uris the file will be loaded locally
65733 // so we don't need to worry about crossOrigin with base64 file types.
65734 if (path.indexOf('data:image/') !== 0) {
65735 img.crossOrigin = 'Anonymous';
65736 }
65737 // start loading the image
65738 img.src = path;
65739 }
65740 pImg.modified = true;
65741 });
65742 return pImg;
65743 };
65744
65745 /**
65746 * Helper function for loading GIF-based images
65747 */
65748 function _createGif(
65749 arrayBuffer,
65750 pImg,
65751 successCallback,
65752 failureCallback,
65753 finishCallback
65754 ) {
65755 var gifReader = new _omggif.default.GifReader(arrayBuffer);
65756 pImg.width = pImg.canvas.width = gifReader.width;
65757 pImg.height = pImg.canvas.height = gifReader.height;
65758 var frames = [];
65759 var numFrames = gifReader.numFrames();
65760 var framePixels = new Uint8ClampedArray(pImg.width * pImg.height * 4);
65761 if (numFrames > 1) {
65762 var loadGIFFrameIntoImage = function loadGIFFrameIntoImage(
65763 frameNum,
65764 gifReader
65765 ) {
65766 try {
65767 gifReader.decodeAndBlitFrameRGBA(frameNum, framePixels);
65768 } catch (e) {
65769 _main.default._friendlyFileLoadError(8, pImg.src);
65770 if (typeof failureCallback === 'function') {
65771 failureCallback(e);
65772 } else {
65773 console.error(e);
65774 }
65775 }
65776 };
65777 for (var j = 0; j < numFrames; j++) {
65778 var frameInfo = gifReader.frameInfo(j);
65779 // Some GIFs are encoded so that they expect the previous frame
65780 // to be under the current frame. This can occur at a sub-frame level
65781 // There are possible disposal codes but I didn't encounter any
65782 if (gifReader.frameInfo(j).disposal === 1 && j > 0) {
65783 pImg.drawingContext.putImageData(frames[j - 1].image, 0, 0);
65784 } else {
65785 pImg.drawingContext.clearRect(0, 0, pImg.width, pImg.height);
65786 framePixels = new Uint8ClampedArray(pImg.width * pImg.height * 4);
65787 }
65788 loadGIFFrameIntoImage(j, gifReader);
65789 var imageData = new ImageData(framePixels, pImg.width, pImg.height);
65790 pImg.drawingContext.putImageData(imageData, 0, 0);
65791 frames.push({
65792 image: pImg.drawingContext.getImageData(0, 0, pImg.width, pImg.height),
65793 delay: frameInfo.delay * 10 //GIF stores delay in one-hundredth of a second, shift to ms
65794 });
65795 }
65796
65797 //Uses Netscape block encoding
65798 //to repeat forever, this will be 0
65799 //to repeat just once, this will be null
65800 //to repeat N times (1<N), should contain integer for loop number
65801 //this is changed to more usable values for us
65802 //to repeat forever, loopCount = null
65803 //everything else is just the number of loops
65804 var loopLimit = gifReader.loopCount();
65805 if (loopLimit === null) {
65806 loopLimit = 1;
65807 } else if (loopLimit === 0) {
65808 loopLimit = null;
65809 }
65810
65811 pImg.gifProperties = {
65812 displayIndex: 0,
65813 loopLimit: loopLimit,
65814 loopCount: 0,
65815 frames: frames,
65816 numFrames: numFrames,
65817 playing: true,
65818 timeDisplayed: 0
65819 };
65820 }
65821
65822 if (typeof successCallback === 'function') {
65823 successCallback(pImg);
65824 }
65825 finishCallback();
65826 }
65827
65828 /**
65829 * Validates clipping params. Per drawImage spec sWidth and sHight cannot be
65830 * negative or greater than image intrinsic width and height
65831 * @private
65832 * @param {Number} sVal
65833 * @param {Number} iVal
65834 * @returns {Number}
65835 * @private
65836 */
65837 function _sAssign(sVal, iVal) {
65838 if (sVal > 0 && sVal < iVal) {
65839 return sVal;
65840 } else {
65841 return iVal;
65842 }
65843 }
65844
65845 /**
65846 * Draw an image to the p5.js canvas.
65847 *
65848 * This function can be used with different numbers of parameters. The
65849 * simplest use requires only three parameters: img, x, and y—where (x, y) is
65850 * the position of the image. Two more parameters can optionally be added to
65851 * specify the width and height of the image.
65852 *
65853 * This function can also be used with all eight Number parameters. To
65854 * differentiate between all these parameters, p5.js uses the language of
65855 * "destination rectangle" (which corresponds to "dx", "dy", etc.) and "source
65856 * image" (which corresponds to "sx", "sy", etc.) below. Specifying the
65857 * "source image" dimensions can be useful when you want to display a
65858 * subsection of the source image instead of the whole thing. Here's a diagram
65859 * to explain further:
65860 * <img src="assets/drawImage.png"></img>
65861 *
65862 * @method image
65863 * @param {p5.Image|p5.Element} img the image to display
65864 * @param {Number} x the x-coordinate of the top-left corner of the image
65865 * @param {Number} y the y-coordinate of the top-left corner of the image
65866 * @param {Number} [width] the width to draw the image
65867 * @param {Number} [height] the height to draw the image
65868 * @example
65869 * <div>
65870 * <code>
65871 * let img;
65872 * function preload() {
65873 * img = loadImage('assets/laDefense.jpg');
65874 * }
65875 * function setup() {
65876 * // Top-left corner of the img is at (0, 0)
65877 * // Width and height are the img's original width and height
65878 * image(img, 0, 0);
65879 * }
65880 * </code>
65881 * </div>
65882 * <div>
65883 * <code>
65884 * let img;
65885 * function preload() {
65886 * img = loadImage('assets/laDefense.jpg');
65887 * }
65888 * function setup() {
65889 * background(50);
65890 * // Top-left corner of the img is at (10, 10)
65891 * // Width and height are 50 x 50
65892 * image(img, 10, 10, 50, 50);
65893 * }
65894 * </code>
65895 * </div>
65896 * <div>
65897 * <code>
65898 * function setup() {
65899 * // Here, we use a callback to display the image after loading
65900 * loadImage('assets/laDefense.jpg', img => {
65901 * image(img, 0, 0);
65902 * });
65903 * }
65904 * </code>
65905 * </div>
65906 * <div>
65907 * <code>
65908 * let img;
65909 * function preload() {
65910 * img = loadImage('assets/gradient.png');
65911 * }
65912 * function setup() {
65913 * // 1. Background image
65914 * // Top-left corner of the img is at (0, 0)
65915 * // Width and height are the img's original width and height, 100 x 100
65916 * image(img, 0, 0);
65917 * // 2. Top right image
65918 * // Top-left corner of destination rectangle is at (50, 0)
65919 * // Destination rectangle width and height are 40 x 20
65920 * // The next parameters are relative to the source image:
65921 * // - Starting at position (50, 50) on the source image, capture a 50 x 50
65922 * // subsection
65923 * // - Draw this subsection to fill the dimensions of the destination rectangle
65924 * image(img, 50, 0, 40, 20, 50, 50, 50, 50);
65925 * }
65926 * </code>
65927 * </div>
65928 * @alt
65929 * image of the underside of a white umbrella and gridded ceiling above
65930 * image of the underside of a white umbrella and gridded ceiling above
65931 */
65932 /**
65933 * @method image
65934 * @param {p5.Image|p5.Element} img
65935 * @param {Number} dx the x-coordinate of the destination
65936 * rectangle in which to draw the source image
65937 * @param {Number} dy the y-coordinate of the destination
65938 * rectangle in which to draw the source image
65939 * @param {Number} dWidth the width of the destination rectangle
65940 * @param {Number} dHeight the height of the destination rectangle
65941 * @param {Number} sx the x-coordinate of the subsection of the source
65942 * image to draw into the destination rectangle
65943 * @param {Number} sy the y-coordinate of the subsection of the source
65944 * image to draw into the destination rectangle
65945 * @param {Number} [sWidth] the width of the subsection of the
65946 * source image to draw into the destination
65947 * rectangle
65948 * @param {Number} [sHeight] the height of the subsection of the
65949 * source image to draw into the destination rectangle
65950 */
65951 _main.default.prototype.image = function(
65952 img,
65953 dx,
65954 dy,
65955 dWidth,
65956 dHeight,
65957 sx,
65958 sy,
65959 sWidth,
65960 sHeight
65961 ) {
65962 // set defaults per spec: https://goo.gl/3ykfOq
65963
65964 _main.default._validateParameters('image', arguments);
65965
65966 var defW = img.width;
65967 var defH = img.height;
65968
65969 if (img.elt && img.elt.videoWidth && !img.canvas) {
65970 // video no canvas
65971 defW = img.elt.videoWidth;
65972 defH = img.elt.videoHeight;
65973 }
65974
65975 var _dx = dx;
65976 var _dy = dy;
65977 var _dw = dWidth || defW;
65978 var _dh = dHeight || defH;
65979 var _sx = sx || 0;
65980 var _sy = sy || 0;
65981 var _sw = sWidth || defW;
65982 var _sh = sHeight || defH;
65983
65984 _sw = _sAssign(_sw, defW);
65985 _sh = _sAssign(_sh, defH);
65986
65987 // This part needs cleanup and unit tests
65988 // see issues https://github.com/processing/p5.js/issues/1741
65989 // and https://github.com/processing/p5.js/issues/1673
65990 var pd = 1;
65991
65992 if (img.elt && !img.canvas && img.elt.style.width) {
65993 //if img is video and img.elt.size() has been used and
65994 //no width passed to image()
65995 if (img.elt.videoWidth && !dWidth) {
65996 pd = img.elt.videoWidth;
65997 } else {
65998 //all other cases
65999 pd = img.elt.width;
66000 }
66001 pd /= parseInt(img.elt.style.width, 10);
66002 }
66003
66004 _sx *= pd;
66005 _sy *= pd;
66006 _sh *= pd;
66007 _sw *= pd;
66008
66009 var vals = _helpers.default.modeAdjust(
66010 _dx,
66011 _dy,
66012 _dw,
66013 _dh,
66014 this._renderer._imageMode
66015 );
66016
66017 // tint the image if there is a tint
66018 this._renderer.image(img, _sx, _sy, _sw, _sh, vals.x, vals.y, vals.w, vals.h);
66019 };
66020
66021 /**
66022 * Sets the fill value for displaying images. Images can be tinted to
66023 * specified colors or made transparent by including an alpha value.
66024 *
66025 * To apply transparency to an image without affecting its color, use
66026 * white as the tint color and specify an alpha value. For instance,
66027 * tint(255, 128) will make an image 50% transparent (assuming the default
66028 * alpha range of 0-255, which can be changed with <a href="#/p5/colorMode">colorMode()</a>).
66029 *
66030 * The value for the gray parameter must be less than or equal to the current
66031 * maximum value as specified by <a href="#/p5/colorMode">colorMode()</a>. The default maximum value is
66032 * 255.
66033 *
66034 * @method tint
66035 * @param {Number} v1 red or hue value relative to
66036 * the current color range
66037 * @param {Number} v2 green or saturation value
66038 * relative to the current color range
66039 * @param {Number} v3 blue or brightness value
66040 * relative to the current color range
66041 * @param {Number} [alpha]
66042 *
66043 * @example
66044 * <div>
66045 * <code>
66046 * let img;
66047 * function preload() {
66048 * img = loadImage('assets/laDefense.jpg');
66049 * }
66050 * function setup() {
66051 * image(img, 0, 0);
66052 * tint(0, 153, 204); // Tint blue
66053 * image(img, 50, 0);
66054 * }
66055 * </code>
66056 * </div>
66057 *
66058 * <div>
66059 * <code>
66060 * let img;
66061 * function preload() {
66062 * img = loadImage('assets/laDefense.jpg');
66063 * }
66064 * function setup() {
66065 * image(img, 0, 0);
66066 * tint(0, 153, 204, 126); // Tint blue and set transparency
66067 * image(img, 50, 0);
66068 * }
66069 * </code>
66070 * </div>
66071 *
66072 * <div>
66073 * <code>
66074 * let img;
66075 * function preload() {
66076 * img = loadImage('assets/laDefense.jpg');
66077 * }
66078 * function setup() {
66079 * image(img, 0, 0);
66080 * tint(255, 126); // Apply transparency without changing color
66081 * image(img, 50, 0);
66082 * }
66083 * </code>
66084 * </div>
66085 *
66086 * @alt
66087 * 2 side by side images of umbrella and ceiling, one image with blue tint
66088 * Images of umbrella and ceiling, one half of image with blue tint
66089 * 2 side by side images of umbrella and ceiling, one image translucent
66090 */
66091
66092 /**
66093 * @method tint
66094 * @param {String} value a color string
66095 */
66096
66097 /**
66098 * @method tint
66099 * @param {Number} gray a gray value
66100 * @param {Number} [alpha]
66101 */
66102
66103 /**
66104 * @method tint
66105 * @param {Number[]} values an array containing the red,green,blue &
66106 * and alpha components of the color
66107 */
66108
66109 /**
66110 * @method tint
66111 * @param {p5.Color} color the tint color
66112 */
66113 _main.default.prototype.tint = function() {
66114 for (
66115 var _len = arguments.length, args = new Array(_len), _key = 0;
66116 _key < _len;
66117 _key++
66118 ) {
66119 args[_key] = arguments[_key];
66120 }
66121 _main.default._validateParameters('tint', args);
66122 var c = this.color.apply(this, args);
66123 this._renderer._tint = c.levels;
66124 };
66125
66126 /**
66127 * Removes the current fill value for displaying images and reverts to
66128 * displaying images with their original hues.
66129 *
66130 * @method noTint
66131 * @example
66132 * <div>
66133 * <code>
66134 * let img;
66135 * function preload() {
66136 * img = loadImage('assets/bricks.jpg');
66137 * }
66138 * function setup() {
66139 * tint(0, 153, 204); // Tint blue
66140 * image(img, 0, 0);
66141 * noTint(); // Disable tint
66142 * image(img, 50, 0);
66143 * }
66144 * </code>
66145 * </div>
66146 *
66147 * @alt
66148 * 2 side by side images of bricks, left image with blue tint
66149 */
66150 _main.default.prototype.noTint = function() {
66151 this._renderer._tint = null;
66152 };
66153
66154 /**
66155 * Apply the current tint color to the input image, return the resulting
66156 * canvas.
66157 *
66158 * @private
66159 * @param {p5.Image} The image to be tinted
66160 * @return {canvas} The resulting tinted canvas
66161 */
66162 _main.default.prototype._getTintedImageCanvas = function(img) {
66163 if (!img.canvas) {
66164 return img;
66165 }
66166 var pixels = _filters.default._toPixels(img.canvas);
66167 var tmpCanvas = document.createElement('canvas');
66168 tmpCanvas.width = img.canvas.width;
66169 tmpCanvas.height = img.canvas.height;
66170 var tmpCtx = tmpCanvas.getContext('2d');
66171 var id = tmpCtx.createImageData(img.canvas.width, img.canvas.height);
66172 var newPixels = id.data;
66173
66174 for (var i = 0; i < pixels.length; i += 4) {
66175 var r = pixels[i];
66176 var g = pixels[i + 1];
66177 var b = pixels[i + 2];
66178 var a = pixels[i + 3];
66179
66180 newPixels[i] = r * this._renderer._tint[0] / 255;
66181 newPixels[i + 1] = g * this._renderer._tint[1] / 255;
66182 newPixels[i + 2] = b * this._renderer._tint[2] / 255;
66183 newPixels[i + 3] = a * this._renderer._tint[3] / 255;
66184 }
66185
66186 tmpCtx.putImageData(id, 0, 0);
66187 return tmpCanvas;
66188 };
66189
66190 /**
66191 * Set image mode. Modifies the location from which images are drawn by
66192 * changing the way in which parameters given to <a href="#/p5/image">image()</a> are interpreted.
66193 * The default mode is imageMode(CORNER), which interprets the second and
66194 * third parameters of <a href="#/p5/image">image()</a> as the upper-left corner of the image. If
66195 * two additional parameters are specified, they are used to set the image's
66196 * width and height.
66197 *
66198 * imageMode(CORNERS) interprets the second and third parameters of <a href="#/p5/image">image()</a>
66199 * as the location of one corner, and the fourth and fifth parameters as the
66200 * opposite corner.
66201 *
66202 * imageMode(CENTER) interprets the second and third parameters of <a href="#/p5/image">image()</a>
66203 * as the image's center point. If two additional parameters are specified,
66204 * they are used to set the image's width and height.
66205 *
66206 * @method imageMode
66207 * @param {Constant} mode either CORNER, CORNERS, or CENTER
66208 * @example
66209 *
66210 * <div>
66211 * <code>
66212 * let img;
66213 * function preload() {
66214 * img = loadImage('assets/bricks.jpg');
66215 * }
66216 * function setup() {
66217 * imageMode(CORNER);
66218 * image(img, 10, 10, 50, 50);
66219 * }
66220 * </code>
66221 * </div>
66222 *
66223 * <div>
66224 * <code>
66225 * let img;
66226 * function preload() {
66227 * img = loadImage('assets/bricks.jpg');
66228 * }
66229 * function setup() {
66230 * imageMode(CORNERS);
66231 * image(img, 10, 10, 90, 40);
66232 * }
66233 * </code>
66234 * </div>
66235 *
66236 * <div>
66237 * <code>
66238 * let img;
66239 * function preload() {
66240 * img = loadImage('assets/bricks.jpg');
66241 * }
66242 * function setup() {
66243 * imageMode(CENTER);
66244 * image(img, 50, 50, 80, 80);
66245 * }
66246 * </code>
66247 * </div>
66248 *
66249 * @alt
66250 * small square image of bricks
66251 * horizontal rectangle image of bricks
66252 * large square image of bricks
66253 */
66254 _main.default.prototype.imageMode = function(m) {
66255 _main.default._validateParameters('imageMode', arguments);
66256 if (
66257 m === constants.CORNER ||
66258 m === constants.CORNERS ||
66259 m === constants.CENTER
66260 ) {
66261 this._renderer._imageMode = m;
66262 }
66263 };
66264 var _default = _main.default;
66265 exports.default = _default;
66266 },
66267 {
66268 '../core/constants': 43,
66269 '../core/friendly_errors/fes_core': 46,
66270 '../core/friendly_errors/file_errors': 47,
66271 '../core/friendly_errors/validate_params': 49,
66272 '../core/helpers': 50,
66273 '../core/main': 54,
66274 './filters': 75,
66275 omggif: 33
66276 }
66277 ],
66278 78: [
66279 function(_dereq_, module, exports) {
66280 'use strict';
66281 Object.defineProperty(exports, '__esModule', { value: true });
66282 exports.default = void 0;
66283
66284 var _main = _interopRequireDefault(_dereq_('../core/main'));
66285 var _filters = _interopRequireDefault(_dereq_('./filters'));
66286 function _interopRequireDefault(obj) {
66287 return obj && obj.__esModule ? obj : { default: obj };
66288 }
66289 /**
66290 * @module Image
66291 * @submodule Image
66292 * @requires core
66293 * @requires constants
66294 * @requires filters
66295 */ /**
66296 * This module defines the <a href="#/p5.Image">p5.Image</a> class and P5 methods for
66297 * drawing images to the main display canvas.
66298 */ /*
66299 * Class methods
66300 */ /**
66301 * Creates a new <a href="#/p5.Image">p5.Image</a>. A <a href="#/p5.Image">p5.Image</a> is a canvas backed representation of an
66302 * image.
66303 *
66304 * p5 can display .gif, .jpg and .png images. Images may be displayed
66305 * in 2D and 3D space. Before an image is used, it must be loaded with the
66306 * <a href="#/p5/loadImage">loadImage()</a> function. The <a href="#/p5.Image">p5.Image</a> class contains fields for the width and
66307 * height of the image, as well as an array called <a href="#/p5.Image/pixels">pixels[]</a> that contains the
66308 * values for every pixel in the image.
66309 *
66310 * The methods described below allow easy access to the image's pixels and
66311 * alpha channel and simplify the process of compositing.
66312 *
66313 * Before using the <a href="#/p5.Image/pixels">pixels[]</a> array, be sure to use the <a href="#/p5.Image/loadPixels">loadPixels()</a> method on
66314 * the image to make sure that the pixel data is properly loaded.
66315 * @example
66316 * <div><code>
66317 * function setup() {
66318 * let img = createImage(100, 100); // same as new p5.Image(100, 100);
66319 * img.loadPixels();
66320 * createCanvas(100, 100);
66321 * background(0);
66322 *
66323 * // helper for writing color to array
66324 * function writeColor(image, x, y, red, green, blue, alpha) {
66325 * let index = (x + y * width) * 4;
66326 * image.pixels[index] = red;
66327 * image.pixels[index + 1] = green;
66328 * image.pixels[index + 2] = blue;
66329 * image.pixels[index + 3] = alpha;
66330 * }
66331 *
66332 * let x, y;
66333 * // fill with random colors
66334 * for (y = 0; y < img.height; y++) {
66335 * for (x = 0; x < img.width; x++) {
66336 * let red = random(255);
66337 * let green = random(255);
66338 * let blue = random(255);
66339 * let alpha = 255;
66340 * writeColor(img, x, y, red, green, blue, alpha);
66341 * }
66342 * }
66343 *
66344 * // draw a red line
66345 * y = 0;
66346 * for (x = 0; x < img.width; x++) {
66347 * writeColor(img, x, y, 255, 0, 0, 255);
66348 * }
66349 *
66350 * // draw a green line
66351 * y = img.height - 1;
66352 * for (x = 0; x < img.width; x++) {
66353 * writeColor(img, x, y, 0, 255, 0, 255);
66354 * }
66355 *
66356 * img.updatePixels();
66357 * image(img, 0, 0);
66358 * }
66359 * </code></div>
66360 *
66361 * @class p5.Image
66362 * @constructor
66363 * @param {Number} width
66364 * @param {Number} height
66365 */ _main.default.Image = function(width, height) {
66366 /**
66367 * Image width.
66368 * @property {Number} width
66369 * @readOnly
66370 * @example
66371 * <div><code>
66372 * let img;
66373 * function preload() {
66374 * img = loadImage('assets/rockies.jpg');
66375 * }
66376 *
66377 * function setup() {
66378 * createCanvas(100, 100);
66379 * image(img, 0, 0);
66380 * for (let i = 0; i < img.width; i++) {
66381 * let c = img.get(i, img.height / 2);
66382 * stroke(c);
66383 * line(i, height / 2, i, height);
66384 * }
66385 * }
66386 * </code></div>
66387 *
66388 * @alt
66389 * rocky mountains in top and horizontal lines in corresponding colors in bottom.
66390 *
66391 */ this.width = width;
66392 /**
66393 * Image height.
66394 * @property {Number} height
66395 * @readOnly
66396 * @example
66397 * <div><code>
66398 * let img;
66399 * function preload() {
66400 * img = loadImage('assets/rockies.jpg');
66401 * }
66402 *
66403 * function setup() {
66404 * createCanvas(100, 100);
66405 * image(img, 0, 0);
66406 * for (let i = 0; i < img.height; i++) {
66407 * let c = img.get(img.width / 2, i);
66408 * stroke(c);
66409 * line(0, i, width / 2, i);
66410 * }
66411 * }
66412 * </code></div>
66413 *
66414 * @alt
66415 * rocky mountains on right and vertical lines in corresponding colors on left.
66416 *
66417 */ this.height = height;
66418 this.canvas = document.createElement('canvas');
66419 this.canvas.width = this.width;
66420 this.canvas.height = this.height;
66421 this.drawingContext = this.canvas.getContext('2d');
66422 this._pixelsState = this;
66423 this._pixelDensity = 1;
66424 //Object for working with GIFs, defaults to null
66425 this.gifProperties = null;
66426 //For WebGL Texturing only: used to determine whether to reupload texture to GPU
66427 this._modified = false;
66428 /**
66429 * Array containing the values for all the pixels in the display window.
66430 * These values are numbers. This array is the size (include an appropriate
66431 * factor for pixelDensity) of the display window x4,
66432 * representing the R, G, B, A values in order for each pixel, moving from
66433 * left to right across each row, then down each column. Retina and other
66434 * high density displays may have more pixels (by a factor of
66435 * pixelDensity^2).
66436 * For example, if the image is 100x100 pixels, there will be 40,000. With
66437 * pixelDensity = 2, there will be 160,000. The first four values
66438 * (indices 0-3) in the array will be the R, G, B, A values of the pixel at
66439 * (0, 0). The second four values (indices 4-7) will contain the R, G, B, A
66440 * values of the pixel at (1, 0). More generally, to set values for a pixel
66441 * at (x, y):
66442 * ```javascript
66443 * let d = pixelDensity();
66444 * for (let i = 0; i < d; i++) {
66445 * for (let j = 0; j < d; j++) {
66446 * // loop over
66447 * index = 4 * ((y * d + j) * width * d + (x * d + i));
66448 * pixels[index] = r;
66449 * pixels[index+1] = g;
66450 * pixels[index+2] = b;
66451 * pixels[index+3] = a;
66452 * }
66453 * }
66454 * ```
66455 *
66456 * Before accessing this array, the data must loaded with the <a href="#/p5.Image/loadPixels">loadPixels()</a>
66457 * function. After the array data has been modified, the <a href="#/p5.Image/updatePixels">updatePixels()</a>
66458 * function must be run to update the changes.
66459 * @property {Number[]} pixels
66460 * @example
66461 * <div>
66462 * <code>
66463 * let img = createImage(66, 66);
66464 * img.loadPixels();
66465 * for (let i = 0; i < img.width; i++) {
66466 * for (let j = 0; j < img.height; j++) {
66467 * img.set(i, j, color(0, 90, 102));
66468 * }
66469 * }
66470 * img.updatePixels();
66471 * image(img, 17, 17);
66472 * </code>
66473 * </div>
66474 * <div>
66475 * <code>
66476 * let pink = color(255, 102, 204);
66477 * let img = createImage(66, 66);
66478 * img.loadPixels();
66479 * for (let i = 0; i < 4 * (width * height / 2); i += 4) {
66480 * img.pixels[i] = red(pink);
66481 * img.pixels[i + 1] = green(pink);
66482 * img.pixels[i + 2] = blue(pink);
66483 * img.pixels[i + 3] = alpha(pink);
66484 * }
66485 * img.updatePixels();
66486 * image(img, 17, 17);
66487 * </code>
66488 * </div>
66489 *
66490 * @alt
66491 * 66x66 turquoise rect in center of canvas
66492 * 66x66 pink rect in center of canvas
66493 *
66494 */
66495 this.pixels = [];
66496 };
66497
66498 /**
66499 * Helper function for animating GIF-based images with time
66500 */
66501 _main.default.Image.prototype._animateGif = function(pInst) {
66502 var props = this.gifProperties;
66503 if (props.playing) {
66504 props.timeDisplayed += pInst.deltaTime;
66505 var curDelay = props.frames[props.displayIndex].delay;
66506 if (props.timeDisplayed >= curDelay) {
66507 //GIF is bound to 'realtime' so can skip frames
66508 var skips = Math.floor(props.timeDisplayed / curDelay);
66509 props.timeDisplayed = 0;
66510 props.displayIndex += skips;
66511 props.loopCount = Math.floor(props.displayIndex / props.numFrames);
66512 if (props.loopLimit !== null && props.loopCount >= props.loopLimit) {
66513 props.playing = false;
66514 } else {
66515 var ind = props.displayIndex % props.numFrames;
66516 this.drawingContext.putImageData(props.frames[ind].image, 0, 0);
66517 props.displayIndex = ind;
66518 this.setModified(true);
66519 }
66520 }
66521 }
66522 };
66523
66524 /**
66525 * Helper fxn for sharing pixel methods
66526 */
66527 _main.default.Image.prototype._setProperty = function(prop, value) {
66528 this[prop] = value;
66529 this.setModified(true);
66530 };
66531
66532 /**
66533 * Loads the pixels data for this image into the [pixels] attribute.
66534 *
66535 * @method loadPixels
66536 * @example
66537 * <div><code>
66538 * let myImage;
66539 * let halfImage;
66540 *
66541 * function preload() {
66542 * myImage = loadImage('assets/rockies.jpg');
66543 * }
66544 *
66545 * function setup() {
66546 * myImage.loadPixels();
66547 * halfImage = 4 * myImage.width * myImage.height / 2;
66548 * for (let i = 0; i < halfImage; i++) {
66549 * myImage.pixels[i + halfImage] = myImage.pixels[i];
66550 * }
66551 * myImage.updatePixels();
66552 * }
66553 *
66554 * function draw() {
66555 * image(myImage, 0, 0, width, height);
66556 * }
66557 * </code></div>
66558 *
66559 * @alt
66560 * 2 images of rocky mountains vertically stacked
66561 */
66562 _main.default.Image.prototype.loadPixels = function() {
66563 _main.default.Renderer2D.prototype.loadPixels.call(this);
66564 this.setModified(true);
66565 };
66566
66567 /**
66568 * Updates the backing canvas for this image with the contents of
66569 * the [pixels] array.
66570 *
66571 * If this image is an animated GIF then the pixels will be updated
66572 * in the frame that is currently displayed.
66573 *
66574 * @method updatePixels
66575 * @param {Integer} x x-offset of the target update area for the
66576 * underlying canvas
66577 * @param {Integer} y y-offset of the target update area for the
66578 * underlying canvas
66579 * @param {Integer} w height of the target update area for the
66580 * underlying canvas
66581 * @param {Integer} h height of the target update area for the
66582 * underlying canvas
66583 * @example
66584 * <div><code>
66585 * let myImage;
66586 * let halfImage;
66587 *
66588 * function preload() {
66589 * myImage = loadImage('assets/rockies.jpg');
66590 * }
66591 *
66592 * function setup() {
66593 * myImage.loadPixels();
66594 * halfImage = 4 * myImage.width * myImage.height / 2;
66595 * for (let i = 0; i < halfImage; i++) {
66596 * myImage.pixels[i + halfImage] = myImage.pixels[i];
66597 * }
66598 * myImage.updatePixels();
66599 * }
66600 *
66601 * function draw() {
66602 * image(myImage, 0, 0, width, height);
66603 * }
66604 * </code></div>
66605 *
66606 * @alt
66607 * 2 images of rocky mountains vertically stacked
66608 */
66609 /**
66610 * @method updatePixels
66611 */
66612 _main.default.Image.prototype.updatePixels = function(x, y, w, h) {
66613 _main.default.Renderer2D.prototype.updatePixels.call(this, x, y, w, h);
66614 this.setModified(true);
66615 };
66616
66617 /**
66618 * Get a region of pixels from an image.
66619 *
66620 * If no params are passed, the whole image is returned.
66621 * If x and y are the only params passed a single pixel is extracted.
66622 * If all params are passed a rectangle region is extracted and a <a href="#/p5.Image">p5.Image</a>
66623 * is returned.
66624 *
66625 * @method get
66626 * @param {Number} x x-coordinate of the pixel
66627 * @param {Number} y y-coordinate of the pixel
66628 * @param {Number} w width
66629 * @param {Number} h height
66630 * @return {p5.Image} the rectangle <a href="#/p5.Image">p5.Image</a>
66631 * @example
66632 * <div><code>
66633 * let myImage;
66634 * let c;
66635 *
66636 * function preload() {
66637 * myImage = loadImage('assets/rockies.jpg');
66638 * }
66639 *
66640 * function setup() {
66641 * background(myImage);
66642 * noStroke();
66643 * c = myImage.get(60, 90);
66644 * fill(c);
66645 * rect(25, 25, 50, 50);
66646 * }
66647 *
66648 * //get() returns color here
66649 * </code></div>
66650 *
66651 * @alt
66652 * image of rocky mountains with 50x50 green rect in front
66653 */
66654 /**
66655 * @method get
66656 * @return {p5.Image} the whole <a href="#/p5.Image">p5.Image</a>
66657 */
66658 /**
66659 * @method get
66660 * @param {Number} x
66661 * @param {Number} y
66662 * @return {Number[]} color of pixel at x,y in array format [R, G, B, A]
66663 */
66664 _main.default.Image.prototype.get = function(x, y, w, h) {
66665 _main.default._validateParameters('p5.Image.get', arguments);
66666 return _main.default.Renderer2D.prototype.get.apply(this, arguments);
66667 };
66668
66669 _main.default.Image.prototype._getPixel =
66670 _main.default.Renderer2D.prototype._getPixel;
66671
66672 /**
66673 * Set the color of a single pixel or write an image into
66674 * this <a href="#/p5.Image">p5.Image</a>.
66675 *
66676 * Note that for a large number of pixels this will
66677 * be slower than directly manipulating the pixels array
66678 * and then calling <a href="#/p5.Image/updatePixels">updatePixels()</a>.
66679 *
66680 * @method set
66681 * @param {Number} x x-coordinate of the pixel
66682 * @param {Number} y y-coordinate of the pixel
66683 * @param {Number|Number[]|Object} a grayscale value | pixel array |
66684 * a <a href="#/p5.Color">p5.Color</a> | image to copy
66685 * @example
66686 * <div>
66687 * <code>
66688 * let img = createImage(66, 66);
66689 * img.loadPixels();
66690 * for (let i = 0; i < img.width; i++) {
66691 * for (let j = 0; j < img.height; j++) {
66692 * img.set(i, j, color(0, 90, 102, (i % img.width) * 2));
66693 * }
66694 * }
66695 * img.updatePixels();
66696 * image(img, 17, 17);
66697 * image(img, 34, 34);
66698 * </code>
66699 * </div>
66700 *
66701 * @alt
66702 * 2 gradated dark turquoise rects fade left. 1 center 1 bottom right of canvas
66703 */
66704 _main.default.Image.prototype.set = function(x, y, imgOrCol) {
66705 _main.default.Renderer2D.prototype.set.call(this, x, y, imgOrCol);
66706 this.setModified(true);
66707 };
66708
66709 /**
66710 * Resize the image to a new width and height. To make the image scale
66711 * proportionally, use 0 as the value for the wide or high parameter.
66712 * For instance, to make the width of an image 150 pixels, and change
66713 * the height using the same proportion, use resize(150, 0).
66714 *
66715 * @method resize
66716 * @param {Number} width the resized image width
66717 * @param {Number} height the resized image height
66718 * @example
66719 * <div><code>
66720 * let img;
66721 *
66722 * function preload() {
66723 * img = loadImage('assets/rockies.jpg');
66724 * }
66725
66726 * function draw() {
66727 * image(img, 0, 0);
66728 * }
66729 *
66730 * function mousePressed() {
66731 * img.resize(50, 100);
66732 * }
66733 * </code></div>
66734 *
66735 * @alt
66736 * image of rocky mountains. zoomed in
66737 */
66738 _main.default.Image.prototype.resize = function(width, height) {
66739 // Copy contents to a temporary canvas, resize the original
66740 // and then copy back.
66741 //
66742 // There is a faster approach that involves just one copy and swapping the
66743 // this.canvas reference. We could switch to that approach if (as i think
66744 // is the case) there an expectation that the user would not hold a
66745 // reference to the backing canvas of a p5.Image. But since we do not
66746 // enforce that at the moment, I am leaving in the slower, but safer
66747 // implementation.
66748
66749 // auto-resize
66750 if (width === 0 && height === 0) {
66751 width = this.canvas.width;
66752 height = this.canvas.height;
66753 } else if (width === 0) {
66754 width = this.canvas.width * height / this.canvas.height;
66755 } else if (height === 0) {
66756 height = this.canvas.height * width / this.canvas.width;
66757 }
66758
66759 width = Math.floor(width);
66760 height = Math.floor(height);
66761
66762 var tempCanvas = document.createElement('canvas');
66763 tempCanvas.width = width;
66764 tempCanvas.height = height;
66765
66766 if (this.gifProperties) {
66767 var props = this.gifProperties;
66768 //adapted from github.com/LinusU/resize-image-data
66769 var nearestNeighbor = function nearestNeighbor(src, dst) {
66770 var pos = 0;
66771 for (var y = 0; y < dst.height; y++) {
66772 for (var x = 0; x < dst.width; x++) {
66773 var srcX = Math.floor(x * src.width / dst.width);
66774 var srcY = Math.floor(y * src.height / dst.height);
66775 var srcPos = (srcY * src.width + srcX) * 4;
66776 dst.data[pos++] = src.data[srcPos++]; // R
66777 dst.data[pos++] = src.data[srcPos++]; // G
66778 dst.data[pos++] = src.data[srcPos++]; // B
66779 dst.data[pos++] = src.data[srcPos++]; // A
66780 }
66781 }
66782 };
66783 for (var i = 0; i < props.numFrames; i++) {
66784 var resizedImageData = this.drawingContext.createImageData(width, height);
66785
66786 nearestNeighbor(props.frames[i].image, resizedImageData);
66787 props.frames[i].image = resizedImageData;
66788 }
66789 }
66790
66791 // prettier-ignore
66792 tempCanvas.getContext('2d').drawImage(
66793 this.canvas,
66794 0, 0, this.canvas.width, this.canvas.height,
66795 0, 0, tempCanvas.width, tempCanvas.height);
66796
66797 // Resize the original canvas, which will clear its contents
66798 this.canvas.width = this.width = width;
66799 this.canvas.height = this.height = height;
66800
66801 //Copy the image back
66802
66803 // prettier-ignore
66804 this.drawingContext.drawImage(
66805 tempCanvas,
66806 0, 0, width, height,
66807 0, 0, width, height);
66808
66809 if (this.pixels.length > 0) {
66810 this.loadPixels();
66811 }
66812
66813 this.setModified(true);
66814 };
66815
66816 /**
66817 * Copies a region of pixels from one image to another. If no
66818 * srcImage is specified this is used as the source. If the source
66819 * and destination regions aren't the same size, it will
66820 * automatically resize source pixels to fit the specified
66821 * target region.
66822 *
66823 * @method copy
66824 * @param {p5.Image|p5.Element} srcImage source image
66825 * @param {Integer} sx X coordinate of the source's upper left corner
66826 * @param {Integer} sy Y coordinate of the source's upper left corner
66827 * @param {Integer} sw source image width
66828 * @param {Integer} sh source image height
66829 * @param {Integer} dx X coordinate of the destination's upper left corner
66830 * @param {Integer} dy Y coordinate of the destination's upper left corner
66831 * @param {Integer} dw destination image width
66832 * @param {Integer} dh destination image height
66833 * @example
66834 * <div><code>
66835 * let photo;
66836 * let bricks;
66837 * let x;
66838 * let y;
66839 *
66840 * function preload() {
66841 * photo = loadImage('assets/rockies.jpg');
66842 * bricks = loadImage('assets/bricks.jpg');
66843 * }
66844 *
66845 * function setup() {
66846 * x = bricks.width / 2;
66847 * y = bricks.height / 2;
66848 * photo.copy(bricks, 0, 0, x, y, 0, 0, x, y);
66849 * image(photo, 0, 0);
66850 * }
66851 * </code></div>
66852 *
66853 * @alt
66854 * image of rocky mountains and smaller image on top of bricks at top left
66855 */
66856 /**
66857 * @method copy
66858 * @param {Integer} sx
66859 * @param {Integer} sy
66860 * @param {Integer} sw
66861 * @param {Integer} sh
66862 * @param {Integer} dx
66863 * @param {Integer} dy
66864 * @param {Integer} dw
66865 * @param {Integer} dh
66866 */
66867 _main.default.Image.prototype.copy = function() {
66868 for (
66869 var _len = arguments.length, args = new Array(_len), _key = 0;
66870 _key < _len;
66871 _key++
66872 ) {
66873 args[_key] = arguments[_key];
66874 }
66875 _main.default.prototype.copy.apply(this, args);
66876 };
66877
66878 /**
66879 * Masks part of an image from displaying by loading another
66880 * image and using its alpha channel as an alpha channel for
66881 * this image.
66882 *
66883 * @method mask
66884 * @param {p5.Image} srcImage source image
66885 * @example
66886 * <div><code>
66887 * let photo, maskImage;
66888 * function preload() {
66889 * photo = loadImage('assets/rockies.jpg');
66890 * maskImage = loadImage('assets/mask2.png');
66891 * }
66892 *
66893 * function setup() {
66894 * createCanvas(100, 100);
66895 * photo.mask(maskImage);
66896 * image(photo, 0, 0);
66897 * }
66898 * </code></div>
66899 *
66900 * @alt
66901 * image of rocky mountains with white at right
66902 *
66903 * http://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/
66904 */
66905 // TODO: - Accept an array of alpha values.
66906 // - Use other channels of an image. p5 uses the
66907 // blue channel (which feels kind of arbitrary). Note: at the
66908 // moment this method does not match native processing's original
66909 // functionality exactly.
66910 _main.default.Image.prototype.mask = function(p5Image) {
66911 if (p5Image === undefined) {
66912 p5Image = this;
66913 }
66914 var currBlend = this.drawingContext.globalCompositeOperation;
66915
66916 var scaleFactor = 1;
66917 if (p5Image instanceof _main.default.Renderer) {
66918 scaleFactor = p5Image._pInst._pixelDensity;
66919 }
66920
66921 var copyArgs = [
66922 p5Image,
66923 0,
66924 0,
66925 scaleFactor * p5Image.width,
66926 scaleFactor * p5Image.height,
66927 0,
66928 0,
66929 this.width,
66930 this.height
66931 ];
66932
66933 this.drawingContext.globalCompositeOperation = 'destination-in';
66934 _main.default.Image.prototype.copy.apply(this, copyArgs);
66935 this.drawingContext.globalCompositeOperation = currBlend;
66936 this.setModified(true);
66937 };
66938
66939 /**
66940 * Applies an image filter to a <a href="#/p5.Image">p5.Image</a>
66941 *
66942 * @method filter
66943 * @param {Constant} filterType either THRESHOLD, GRAY, OPAQUE, INVERT,
66944 * POSTERIZE, BLUR, ERODE, DILATE or BLUR.
66945 * See Filters.js for docs on
66946 * each available filter
66947 * @param {Number} [filterParam] an optional parameter unique
66948 * to each filter, see above
66949 * @example
66950 * <div><code>
66951 * let photo1;
66952 * let photo2;
66953 *
66954 * function preload() {
66955 * photo1 = loadImage('assets/rockies.jpg');
66956 * photo2 = loadImage('assets/rockies.jpg');
66957 * }
66958 *
66959 * function setup() {
66960 * photo2.filter(GRAY);
66961 * image(photo1, 0, 0);
66962 * image(photo2, width / 2, 0);
66963 * }
66964 * </code></div>
66965 *
66966 * @alt
66967 * 2 images of rocky mountains left one in color, right in black and white
66968 */
66969 _main.default.Image.prototype.filter = function(operation, value) {
66970 _filters.default.apply(this.canvas, _filters.default[operation], value);
66971 this.setModified(true);
66972 };
66973
66974 /**
66975 * Copies a region of pixels from one image to another, using a specified
66976 * blend mode to do the operation.
66977 *
66978 * @method blend
66979 * @param {p5.Image} srcImage source image
66980 * @param {Integer} sx X coordinate of the source's upper left corner
66981 * @param {Integer} sy Y coordinate of the source's upper left corner
66982 * @param {Integer} sw source image width
66983 * @param {Integer} sh source image height
66984 * @param {Integer} dx X coordinate of the destination's upper left corner
66985 * @param {Integer} dy Y coordinate of the destination's upper left corner
66986 * @param {Integer} dw destination image width
66987 * @param {Integer} dh destination image height
66988 * @param {Constant} blendMode the blend mode. either
66989 * BLEND, DARKEST, LIGHTEST, DIFFERENCE,
66990 * MULTIPLY, EXCLUSION, SCREEN, REPLACE, OVERLAY, HARD_LIGHT,
66991 * SOFT_LIGHT, DODGE, BURN, ADD or NORMAL.
66992 *
66993 * Available blend modes are: normal | multiply | screen | overlay |
66994 * darken | lighten | color-dodge | color-burn | hard-light |
66995 * soft-light | difference | exclusion | hue | saturation |
66996 * color | luminosity
66997 *
66998 * http://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/
66999 * @example
67000 * <div><code>
67001 * let mountains;
67002 * let bricks;
67003 *
67004 * function preload() {
67005 * mountains = loadImage('assets/rockies.jpg');
67006 * bricks = loadImage('assets/bricks_third.jpg');
67007 * }
67008 *
67009 * function setup() {
67010 * mountains.blend(bricks, 0, 0, 33, 100, 67, 0, 33, 100, ADD);
67011 * image(mountains, 0, 0);
67012 * image(bricks, 0, 0);
67013 * }
67014 * </code></div>
67015 * <div><code>
67016 * let mountains;
67017 * let bricks;
67018 *
67019 * function preload() {
67020 * mountains = loadImage('assets/rockies.jpg');
67021 * bricks = loadImage('assets/bricks_third.jpg');
67022 * }
67023 *
67024 * function setup() {
67025 * mountains.blend(bricks, 0, 0, 33, 100, 67, 0, 33, 100, DARKEST);
67026 * image(mountains, 0, 0);
67027 * image(bricks, 0, 0);
67028 * }
67029 * </code></div>
67030 * <div><code>
67031 * let mountains;
67032 * let bricks;
67033 *
67034 * function preload() {
67035 * mountains = loadImage('assets/rockies.jpg');
67036 * bricks = loadImage('assets/bricks_third.jpg');
67037 * }
67038 *
67039 * function setup() {
67040 * mountains.blend(bricks, 0, 0, 33, 100, 67, 0, 33, 100, LIGHTEST);
67041 * image(mountains, 0, 0);
67042 * image(bricks, 0, 0);
67043 * }
67044 * </code></div>
67045 *
67046 * @alt
67047 * image of rocky mountains. Brick images on left and right. Right overexposed
67048 * image of rockies. Brickwall images on left and right. Right mortar transparent
67049 * image of rockies. Brickwall images on left and right. Right translucent
67050 */
67051 /**
67052 * @method blend
67053 * @param {Integer} sx
67054 * @param {Integer} sy
67055 * @param {Integer} sw
67056 * @param {Integer} sh
67057 * @param {Integer} dx
67058 * @param {Integer} dy
67059 * @param {Integer} dw
67060 * @param {Integer} dh
67061 * @param {Constant} blendMode
67062 */
67063 _main.default.Image.prototype.blend = function() {
67064 for (
67065 var _len2 = arguments.length, args = new Array(_len2), _key2 = 0;
67066 _key2 < _len2;
67067 _key2++
67068 ) {
67069 args[_key2] = arguments[_key2];
67070 }
67071 _main.default._validateParameters('p5.Image.blend', arguments);
67072 _main.default.prototype.blend.apply(this, args);
67073 this.setModified(true);
67074 };
67075
67076 /**
67077 * helper method for web GL mode to indicate that an image has been
67078 * changed or unchanged since last upload. gl texture upload will
67079 * set this value to false after uploading the texture.
67080 * @method setModified
67081 * @param {boolean} val sets whether or not the image has been
67082 * modified.
67083 * @private
67084 */
67085 _main.default.Image.prototype.setModified = function(val) {
67086 this._modified = val; //enforce boolean?
67087 };
67088
67089 /**
67090 * helper method for web GL mode to figure out if the image
67091 * has been modified and might need to be re-uploaded to texture
67092 * memory between frames.
67093 * @method isModified
67094 * @private
67095 * @return {boolean} a boolean indicating whether or not the
67096 * image has been updated or modified since last texture upload.
67097 */
67098 _main.default.Image.prototype.isModified = function() {
67099 return this._modified;
67100 };
67101
67102 /**
67103 * Saves the image to a file and force the browser to download it.
67104 * Accepts two strings for filename and file extension
67105 * Supports png (default), jpg, and gif
67106 *<br><br>
67107 * Note that the file will only be downloaded as an animated GIF
67108 * if the p5.Image was loaded from a GIF file.
67109 * @method save
67110 * @param {String} filename give your file a name
67111 * @param {String} extension 'png' or 'jpg'
67112 * @example
67113 * <div><code>
67114 * let photo;
67115 *
67116 * function preload() {
67117 * photo = loadImage('assets/rockies.jpg');
67118 * }
67119 *
67120 * function draw() {
67121 * image(photo, 0, 0);
67122 * }
67123 *
67124 * function keyTyped() {
67125 * if (key === 's') {
67126 * photo.save('photo', 'png');
67127 * }
67128 * }
67129 * </code></div>
67130 *
67131 * @alt
67132 * image of rocky mountains.
67133 */
67134 _main.default.Image.prototype.save = function(filename, extension) {
67135 if (this.gifProperties) {
67136 _main.default.prototype.saveGif(this, filename);
67137 } else {
67138 _main.default.prototype.saveCanvas(this.canvas, filename, extension);
67139 }
67140 };
67141
67142 // GIF Section
67143 /**
67144 * Starts an animated GIF over at the beginning state.
67145 *
67146 * @method reset
67147 * @example
67148 * <div><code>
67149 * let gif;
67150 *
67151 * function preload() {
67152 * gif = loadImage('assets/arnott-wallace-wink-loop-once.gif');
67153 * }
67154 *
67155 * function draw() {
67156 * background(255);
67157 * // The GIF file that we loaded only loops once
67158 * // so it freezes on the last frame after playing through
67159 * image(gif, 0, 0);
67160 * }
67161 *
67162 * function mousePressed() {
67163 * // Click to reset the GIF and begin playback from start
67164 * gif.reset();
67165 * }
67166 * </code></div>
67167 * @alt
67168 * Animated image of a cartoon face that winks once and then freezes
67169 * When you click it animates again, winks once and freezes
67170 */
67171 _main.default.Image.prototype.reset = function() {
67172 if (this.gifProperties) {
67173 var props = this.gifProperties;
67174 props.playing = true;
67175 props.timeSinceStart = 0;
67176 props.timeDisplayed = 0;
67177 props.loopCount = 0;
67178 props.displayIndex = 0;
67179 this.drawingContext.putImageData(props.frames[0].image, 0, 0);
67180 }
67181 };
67182
67183 /**
67184 * Gets the index for the frame that is currently visible in an animated GIF.
67185 *
67186 * @method getCurrentFrame
67187 * @return {Number} The index for the currently displaying frame in animated GIF
67188 * @example
67189 * <div><code>
67190 * let gif;
67191 *
67192 * function preload() {
67193 * gif = loadImage('assets/arnott-wallace-eye-loop-forever.gif');
67194 * }
67195 *
67196 * function draw() {
67197 * let frame = gif.getCurrentFrame();
67198 * image(gif, 0, 0);
67199 * text(frame, 10, 90);
67200 * }
67201 * </code></div>
67202 * @alt
67203 * Animated image of a cartoon eye looking around and then
67204 * looking outwards, in the lower-left hand corner a number counts
67205 * up quickly to 124 and then starts back over at 0
67206 */
67207 _main.default.Image.prototype.getCurrentFrame = function() {
67208 if (this.gifProperties) {
67209 var props = this.gifProperties;
67210 return props.displayIndex % props.numFrames;
67211 }
67212 };
67213
67214 /**
67215 * Sets the index of the frame that is currently visible in an animated GIF
67216 *
67217 * @method setFrame
67218 * @param {Number} index the index for the frame that should be displayed
67219 * @example
67220 * <div><code>
67221 * let gif;
67222 *
67223 * function preload() {
67224 * gif = loadImage('assets/arnott-wallace-eye-loop-forever.gif');
67225 * }
67226 *
67227 * // Move your mouse up and down over canvas to see the GIF
67228 * // frames animate
67229 * function draw() {
67230 * gif.pause();
67231 * image(gif, 0, 0);
67232 * // Get the highest frame number which is the number of frames - 1
67233 * let maxFrame = gif.numFrames() - 1;
67234 * // Set the current frame that is mapped to be relative to mouse position
67235 * let frameNumber = floor(map(mouseY, 0, height, 0, maxFrame, true));
67236 * gif.setFrame(frameNumber);
67237 * }
67238 * </code></div>
67239 * @alt
67240 * A still image of a cartoon eye that looks around when you move your mouse
67241 * up and down over the canvas
67242 */
67243 _main.default.Image.prototype.setFrame = function(index) {
67244 if (this.gifProperties) {
67245 var props = this.gifProperties;
67246 if (index < props.numFrames && index >= 0) {
67247 props.timeDisplayed = 0;
67248 props.displayIndex = index;
67249 this.drawingContext.putImageData(props.frames[index].image, 0, 0);
67250 } else {
67251 console.log(
67252 'Cannot set GIF to a frame number that is higher than total number of frames or below zero.'
67253 );
67254 }
67255 }
67256 };
67257
67258 /**
67259 * Returns the number of frames in an animated GIF
67260 *
67261 * @method numFrames
67262 * @return {Number}
67263 * @example The number of frames in the animated GIF
67264 * <div><code>
67265 * let gif;
67266 *
67267 * function preload() {
67268 * gif = loadImage('assets/arnott-wallace-eye-loop-forever.gif');
67269 * }
67270 *
67271 * // Move your mouse up and down over canvas to see the GIF
67272 * // frames animate
67273 * function draw() {
67274 * gif.pause();
67275 * image(gif, 0, 0);
67276 * // Get the highest frame number which is the number of frames - 1
67277 * let maxFrame = gif.numFrames() - 1;
67278 * // Set the current frame that is mapped to be relative to mouse position
67279 * let frameNumber = floor(map(mouseY, 0, height, 0, maxFrame, true));
67280 * gif.setFrame(frameNumber);
67281 * }
67282 * </code></div>
67283 * @alt
67284 * A still image of a cartoon eye that looks around when you move your mouse
67285 * up and down over the canvas
67286 */
67287 _main.default.Image.prototype.numFrames = function() {
67288 if (this.gifProperties) {
67289 return this.gifProperties.numFrames;
67290 }
67291 };
67292
67293 /**
67294 * Plays an animated GIF that was paused with
67295 * <a href="#/p5.Image/pause">pause()</a>
67296 *
67297 * @method play
67298 * @example
67299 * <div><code>
67300 * let gif;
67301 *
67302 * function preload() {
67303 * gif = loadImage('assets/nancy-liang-wind-loop-forever.gif');
67304 * }
67305 *
67306 * function draw() {
67307 * background(255);
67308 * image(gif, 0, 0);
67309 * }
67310 *
67311 * function mousePressed() {
67312 * gif.pause();
67313 * }
67314 *
67315 * function mouseReleased() {
67316 * gif.play();
67317 * }
67318 * </code></div>
67319 * @alt
67320 * An animated GIF of a drawing of small child with
67321 * hair blowing in the wind, when you click the image
67322 * freezes when you release it animates again
67323 */
67324 _main.default.Image.prototype.play = function() {
67325 if (this.gifProperties) {
67326 this.gifProperties.playing = true;
67327 }
67328 };
67329
67330 /**
67331 * Pauses an animated GIF.
67332 *
67333 * @method pause
67334 * @example
67335 * <div><code>
67336 * let gif;
67337 *
67338 * function preload() {
67339 * gif = loadImage('assets/nancy-liang-wind-loop-forever.gif');
67340 * }
67341 *
67342 * function draw() {
67343 * background(255);
67344 * image(gif, 0, 0);
67345 * }
67346 *
67347 * function mousePressed() {
67348 * gif.pause();
67349 * }
67350 *
67351 * function mouseReleased() {
67352 * gif.play();
67353 * }
67354 * </code></div>
67355 * @alt
67356 * An animated GIF of a drawing of small child with
67357 * hair blowing in the wind, when you click the image
67358 * freezes when you release it animates again
67359 */
67360 _main.default.Image.prototype.pause = function() {
67361 if (this.gifProperties) {
67362 this.gifProperties.playing = false;
67363 }
67364 };
67365
67366 /**
67367 * Changes the delay between frames in an animated GIF. There is an optional second parameter that
67368 * indicates an index for a specific frame that should have its delay modified. If no index is given, all frames
67369 * will have the new delay.
67370 *
67371 * @method delay
67372 * @param {Number} d the amount in milliseconds to delay between switching frames
67373 * @param {Number} [index] the index of the frame that should have the new delay value {optional}
67374 * @example
67375 * <div><code>
67376 * let gifFast, gifSlow;
67377 *
67378 * function preload() {
67379 * gifFast = loadImage('assets/arnott-wallace-eye-loop-forever.gif');
67380 * gifSlow = loadImage('assets/arnott-wallace-eye-loop-forever.gif');
67381 * }
67382 *
67383 * function setup() {
67384 * gifFast.resize(width / 2, height / 2);
67385 * gifSlow.resize(width / 2, height / 2);
67386 *
67387 * //Change the delay here
67388 * gifFast.delay(10);
67389 * gifSlow.delay(100);
67390 * }
67391 *
67392 * function draw() {
67393 * background(255);
67394 * image(gifFast, 0, 0);
67395 * image(gifSlow, width / 2, 0);
67396 * }
67397 * </code></div>
67398 * @alt
67399 * Two animated gifs of cartoon eyes looking around
67400 * The gif on the left animates quickly, on the right
67401 * the animation is much slower
67402 */
67403 _main.default.Image.prototype.delay = function(d, index) {
67404 if (this.gifProperties) {
67405 var props = this.gifProperties;
67406 if (index < props.numFrames && index >= 0) {
67407 props.frames[index].delay = d;
67408 } else {
67409 // change all frames
67410 var _iteratorNormalCompletion = true;
67411 var _didIteratorError = false;
67412 var _iteratorError = undefined;
67413 try {
67414 for (
67415 var _iterator = props.frames[Symbol.iterator](), _step;
67416 !(_iteratorNormalCompletion = (_step = _iterator.next()).done);
67417 _iteratorNormalCompletion = true
67418 ) {
67419 var frame = _step.value;
67420 frame.delay = d;
67421 }
67422 } catch (err) {
67423 _didIteratorError = true;
67424 _iteratorError = err;
67425 } finally {
67426 try {
67427 if (!_iteratorNormalCompletion && _iterator.return != null) {
67428 _iterator.return();
67429 }
67430 } finally {
67431 if (_didIteratorError) {
67432 throw _iteratorError;
67433 }
67434 }
67435 }
67436 }
67437 }
67438 };
67439 var _default = _main.default.Image;
67440 exports.default = _default;
67441 },
67442 { '../core/main': 54, './filters': 75 }
67443 ],
67444 79: [
67445 function(_dereq_, module, exports) {
67446 'use strict';
67447 Object.defineProperty(exports, '__esModule', { value: true });
67448 exports.default = void 0;
67449
67450 var _main = _interopRequireDefault(_dereq_('../core/main'));
67451 var _filters = _interopRequireDefault(_dereq_('./filters'));
67452 _dereq_('../color/p5.Color');
67453 function _interopRequireDefault(obj) {
67454 return obj && obj.__esModule ? obj : { default: obj };
67455 }
67456 /**
67457 * @module Image
67458 * @submodule Pixels
67459 * @for p5
67460 * @requires core
67461 */ /**
67462 * <a href='https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference
67463 * /Global_Objects/Uint8ClampedArray' target='_blank'>Uint8ClampedArray</a>
67464 * containing the values for all the pixels in the display window.
67465 * These values are numbers. This array is the size (include an appropriate
67466 * factor for <a href="#/p5/pixelDensity">pixelDensity</a>) of the display window x4,
67467 * representing the R, G, B, A values in order for each pixel, moving from
67468 * left to right across each row, then down each column. Retina and other
67469 * high density displays will have more pixels[] (by a factor of
67470 * pixelDensity^2).
67471 * For example, if the image is 100x100 pixels, there will be 40,000. On a
67472 * retina display, there will be 160,000.
67473 *
67474 * The first four values (indices 0-3) in the array will be the R, G, B, A
67475 * values of the pixel at (0, 0). The second four values (indices 4-7) will
67476 * contain the R, G, B, A values of the pixel at (1, 0). More generally, to
67477 * set values for a pixel at (x, y):
67478 * ```javascript
67479 * let d = pixelDensity();
67480 * for (let i = 0; i < d; i++) {
67481 * for (let j = 0; j < d; j++) {
67482 * // loop over
67483 * index = 4 * ((y * d + j) * width * d + (x * d + i));
67484 * pixels[index] = r;
67485 * pixels[index+1] = g;
67486 * pixels[index+2] = b;
67487 * pixels[index+3] = a;
67488 * }
67489 * }
67490 * ```
67491 * While the above method is complex, it is flexible enough to work with
67492 * any pixelDensity. Note that <a href="#/p5/set">set()</a> will automatically take care of
67493 * setting all the appropriate values in <a href="#/p5/pixels">pixels[]</a> for a given (x, y) at
67494 * any pixelDensity, but the performance may not be as fast when lots of
67495 * modifications are made to the pixel array.
67496 *
67497 * Before accessing this array, the data must loaded with the <a href="#/p5/loadPixels">loadPixels()</a>
67498 * function. After the array data has been modified, the <a href="#/p5/updatePixels">updatePixels()</a>
67499 * function must be run to update the changes.
67500 *
67501 * Note that this is not a standard javascript array. This means that
67502 * standard javascript functions such as <a href="#/p5/slice">slice()</a> or
67503 * <a href="#/p5/arrayCopy">arrayCopy()</a> do not
67504 * work.
67505 *
67506 * @property {Number[]} pixels
67507 * @example
67508 * <div>
67509 * <code>
67510 * let pink = color(255, 102, 204);
67511 * loadPixels();
67512 * let d = pixelDensity();
67513 * let halfImage = 4 * (width * d) * (height / 2 * d);
67514 * for (let i = 0; i < halfImage; i += 4) {
67515 * pixels[i] = red(pink);
67516 * pixels[i + 1] = green(pink);
67517 * pixels[i + 2] = blue(pink);
67518 * pixels[i + 3] = alpha(pink);
67519 * }
67520 * updatePixels();
67521 * </code>
67522 * </div>
67523 *
67524 * @alt
67525 * top half of canvas pink, bottom grey
67526 */ _main.default.prototype.pixels = []; /**
67527 * Copies a region of pixels from one image to another, using a specified
67528 * blend mode to do the operation.
67529 *
67530 * @method blend
67531 * @param {p5.Image} srcImage source image
67532 * @param {Integer} sx X coordinate of the source's upper left corner
67533 * @param {Integer} sy Y coordinate of the source's upper left corner
67534 * @param {Integer} sw source image width
67535 * @param {Integer} sh source image height
67536 * @param {Integer} dx X coordinate of the destination's upper left corner
67537 * @param {Integer} dy Y coordinate of the destination's upper left corner
67538 * @param {Integer} dw destination image width
67539 * @param {Integer} dh destination image height
67540 * @param {Constant} blendMode the blend mode. either
67541 * BLEND, DARKEST, LIGHTEST, DIFFERENCE,
67542 * MULTIPLY, EXCLUSION, SCREEN, REPLACE, OVERLAY, HARD_LIGHT,
67543 * SOFT_LIGHT, DODGE, BURN, ADD or NORMAL.
67544 *
67545 * @example
67546 * <div><code>
67547 * let img0;
67548 * let img1;
67549 *
67550 * function preload() {
67551 * img0 = loadImage('assets/rockies.jpg');
67552 * img1 = loadImage('assets/bricks_third.jpg');
67553 * }
67554 *
67555 * function setup() {
67556 * background(img0);
67557 * image(img1, 0, 0);
67558 * blend(img1, 0, 0, 33, 100, 67, 0, 33, 100, LIGHTEST);
67559 * }
67560 * </code></div>
67561 * <div><code>
67562 * let img0;
67563 * let img1;
67564 *
67565 * function preload() {
67566 * img0 = loadImage('assets/rockies.jpg');
67567 * img1 = loadImage('assets/bricks_third.jpg');
67568 * }
67569 *
67570 * function setup() {
67571 * background(img0);
67572 * image(img1, 0, 0);
67573 * blend(img1, 0, 0, 33, 100, 67, 0, 33, 100, DARKEST);
67574 * }
67575 * </code></div>
67576 * <div><code>
67577 * let img0;
67578 * let img1;
67579 *
67580 * function preload() {
67581 * img0 = loadImage('assets/rockies.jpg');
67582 * img1 = loadImage('assets/bricks_third.jpg');
67583 * }
67584 *
67585 * function setup() {
67586 * background(img0);
67587 * image(img1, 0, 0);
67588 * blend(img1, 0, 0, 33, 100, 67, 0, 33, 100, ADD);
67589 * }
67590 * </code></div>
67591 *
67592 * @alt
67593 * image of rocky mountains. Brick images on left and right. Right overexposed
67594 * image of rockies. Brickwall images on left and right. Right mortar transparent
67595 * image of rockies. Brickwall images on left and right. Right translucent
67596 *
67597 */
67598 /**
67599 * @method blend
67600 * @param {Integer} sx
67601 * @param {Integer} sy
67602 * @param {Integer} sw
67603 * @param {Integer} sh
67604 * @param {Integer} dx
67605 * @param {Integer} dy
67606 * @param {Integer} dw
67607 * @param {Integer} dh
67608 * @param {Constant} blendMode
67609 */
67610 _main.default.prototype.blend = function() {
67611 for (
67612 var _len = arguments.length, args = new Array(_len), _key = 0;
67613 _key < _len;
67614 _key++
67615 ) {
67616 args[_key] = arguments[_key];
67617 }
67618 _main.default._validateParameters('blend', args);
67619 if (this._renderer) {
67620 var _this$_renderer;
67621 (_this$_renderer = this._renderer).blend.apply(_this$_renderer, args);
67622 } else {
67623 _main.default.Renderer2D.prototype.blend.apply(this, args);
67624 }
67625 };
67626
67627 /**
67628 * Copies a region of the canvas to another region of the canvas
67629 * and copies a region of pixels from an image used as the srcImg parameter
67630 * into the canvas srcImage is specified this is used as the source. If
67631 * the source and destination regions aren't the same size, it will
67632 * automatically resize source pixels to fit the specified
67633 * target region.
67634 *
67635 * @method copy
67636 * @param {p5.Image|p5.Element} srcImage source image
67637 * @param {Integer} sx X coordinate of the source's upper left corner
67638 * @param {Integer} sy Y coordinate of the source's upper left corner
67639 * @param {Integer} sw source image width
67640 * @param {Integer} sh source image height
67641 * @param {Integer} dx X coordinate of the destination's upper left corner
67642 * @param {Integer} dy Y coordinate of the destination's upper left corner
67643 * @param {Integer} dw destination image width
67644 * @param {Integer} dh destination image height
67645 *
67646 * @example
67647 * <div><code>
67648 * let img;
67649 *
67650 * function preload() {
67651 * img = loadImage('assets/rockies.jpg');
67652 * }
67653 *
67654 * function setup() {
67655 * background(img);
67656 * copy(img, 7, 22, 10, 10, 35, 25, 50, 50);
67657 * stroke(255);
67658 * noFill();
67659 * // Rectangle shows area being copied
67660 * rect(7, 22, 10, 10);
67661 * }
67662 * </code></div>
67663 *
67664 * @alt
67665 * image of rocky mountains. Brick images on left and right. Right overexposed
67666 * image of rockies. Brickwall images on left and right. Right mortar transparent
67667 * image of rockies. Brickwall images on left and right. Right translucent
67668 */
67669 /**
67670 * @method copy
67671 * @param {Integer} sx
67672 * @param {Integer} sy
67673 * @param {Integer} sw
67674 * @param {Integer} sh
67675 * @param {Integer} dx
67676 * @param {Integer} dy
67677 * @param {Integer} dw
67678 * @param {Integer} dh
67679 */
67680 _main.default.prototype.copy = function() {
67681 for (
67682 var _len2 = arguments.length, args = new Array(_len2), _key2 = 0;
67683 _key2 < _len2;
67684 _key2++
67685 ) {
67686 args[_key2] = arguments[_key2];
67687 }
67688 _main.default._validateParameters('copy', args);
67689
67690 var srcImage, sx, sy, sw, sh, dx, dy, dw, dh;
67691 if (args.length === 9) {
67692 srcImage = args[0];
67693 sx = args[1];
67694 sy = args[2];
67695 sw = args[3];
67696 sh = args[4];
67697 dx = args[5];
67698 dy = args[6];
67699 dw = args[7];
67700 dh = args[8];
67701 } else if (args.length === 8) {
67702 srcImage = this;
67703 sx = args[0];
67704 sy = args[1];
67705 sw = args[2];
67706 sh = args[3];
67707 dx = args[4];
67708 dy = args[5];
67709 dw = args[6];
67710 dh = args[7];
67711 } else {
67712 throw new Error('Signature not supported');
67713 }
67714
67715 _main.default.prototype._copyHelper(
67716 this,
67717 srcImage,
67718 sx,
67719 sy,
67720 sw,
67721 sh,
67722 dx,
67723 dy,
67724 dw,
67725 dh
67726 );
67727 };
67728
67729 _main.default.prototype._copyHelper = function(
67730 dstImage,
67731 srcImage,
67732 sx,
67733 sy,
67734 sw,
67735 sh,
67736 dx,
67737 dy,
67738 dw,
67739 dh
67740 ) {
67741 srcImage.loadPixels();
67742 var s = srcImage.canvas.width / srcImage.width;
67743 // adjust coord system for 3D when renderer
67744 // ie top-left = -width/2, -height/2
67745 var sxMod = 0;
67746 var syMod = 0;
67747 if (srcImage._renderer && srcImage._renderer.isP3D) {
67748 sxMod = srcImage.width / 2;
67749 syMod = srcImage.height / 2;
67750 }
67751 if (dstImage._renderer && dstImage._renderer.isP3D) {
67752 _main.default.RendererGL.prototype.image.call(
67753 dstImage._renderer,
67754 srcImage,
67755 sx + sxMod,
67756 sy + syMod,
67757 sw,
67758 sh,
67759 dx,
67760 dy,
67761 dw,
67762 dh
67763 );
67764 } else {
67765 dstImage.drawingContext.drawImage(
67766 srcImage.canvas,
67767 s * (sx + sxMod),
67768 s * (sy + syMod),
67769 s * sw,
67770 s * sh,
67771 dx,
67772 dy,
67773 dw,
67774 dh
67775 );
67776 }
67777 };
67778
67779 /**
67780 * Applies a filter to the canvas. The presets options are:
67781 *
67782 * THRESHOLD
67783 * Converts the image to black and white pixels depending if they are above or
67784 * below the threshold defined by the level parameter. The parameter must be
67785 * between 0.0 (black) and 1.0 (white). If no level is specified, 0.5 is used.
67786 *
67787 * GRAY
67788 * Converts any colors in the image to grayscale equivalents. No parameter
67789 * is used.
67790 *
67791 * OPAQUE
67792 * Sets the alpha channel to entirely opaque. No parameter is used.
67793 *
67794 * INVERT
67795 * Sets each pixel to its inverse value. No parameter is used.
67796 *
67797 * POSTERIZE
67798 * Limits each channel of the image to the number of colors specified as the
67799 * parameter. The parameter can be set to values between 2 and 255, but
67800 * results are most noticeable in the lower ranges.
67801 *
67802 * BLUR
67803 * Executes a Gaussian blur with the level parameter specifying the extent
67804 * of the blurring. If no parameter is used, the blur is equivalent to
67805 * Gaussian blur of radius 1. Larger values increase the blur.
67806 *
67807 * ERODE
67808 * Reduces the light areas. No parameter is used.
67809 *
67810 * DILATE
67811 * Increases the light areas. No parameter is used.
67812 *
67813 * filter() does not work in WEBGL mode.
67814 * A similar effect can be achieved in WEBGL mode using custom
67815 * shaders. Adam Ferriss has written
67816 * a <a href="https://github.com/aferriss/p5jsShaderExamples"
67817 * target='_blank'>selection of shader examples</a> that contains many
67818 * of the effects present in the filter examples.
67819 *
67820 * @method filter
67821 * @param {Constant} filterType either THRESHOLD, GRAY, OPAQUE, INVERT,
67822 * POSTERIZE, BLUR, ERODE, DILATE or BLUR.
67823 * See Filters.js for docs on
67824 * each available filter
67825 * @param {Number} [filterParam] an optional parameter unique
67826 * to each filter, see above
67827 *
67828 * @example
67829 * <div>
67830 * <code>
67831 * let img;
67832 * function preload() {
67833 * img = loadImage('assets/bricks.jpg');
67834 * }
67835 * function setup() {
67836 * image(img, 0, 0);
67837 * filter(THRESHOLD);
67838 * }
67839 * </code>
67840 * </div>
67841 *
67842 * <div>
67843 * <code>
67844 * let img;
67845 * function preload() {
67846 * img = loadImage('assets/bricks.jpg');
67847 * }
67848 * function setup() {
67849 * image(img, 0, 0);
67850 * filter(GRAY);
67851 * }
67852 * </code>
67853 * </div>
67854 *
67855 * <div>
67856 * <code>
67857 * let img;
67858 * function preload() {
67859 * img = loadImage('assets/bricks.jpg');
67860 * }
67861 * function setup() {
67862 * image(img, 0, 0);
67863 * filter(OPAQUE);
67864 * }
67865 * </code>
67866 * </div>
67867 *
67868 * <div>
67869 * <code>
67870 * let img;
67871 * function preload() {
67872 * img = loadImage('assets/bricks.jpg');
67873 * }
67874 * function setup() {
67875 * image(img, 0, 0);
67876 * filter(INVERT);
67877 * }
67878 * </code>
67879 * </div>
67880 *
67881 * <div>
67882 * <code>
67883 * let img;
67884 * function preload() {
67885 * img = loadImage('assets/bricks.jpg');
67886 * }
67887 * function setup() {
67888 * image(img, 0, 0);
67889 * filter(POSTERIZE, 3);
67890 * }
67891 * </code>
67892 * </div>
67893 *
67894 * <div>
67895 * <code>
67896 * let img;
67897 * function preload() {
67898 * img = loadImage('assets/bricks.jpg');
67899 * }
67900 * function setup() {
67901 * image(img, 0, 0);
67902 * filter(DILATE);
67903 * }
67904 * </code>
67905 * </div>
67906 *
67907 * <div>
67908 * <code>
67909 * let img;
67910 * function preload() {
67911 * img = loadImage('assets/bricks.jpg');
67912 * }
67913 * function setup() {
67914 * image(img, 0, 0);
67915 * filter(BLUR, 3);
67916 * }
67917 * </code>
67918 * </div>
67919 *
67920 * <div>
67921 * <code>
67922 * let img;
67923 * function preload() {
67924 * img = loadImage('assets/bricks.jpg');
67925 * }
67926 * function setup() {
67927 * image(img, 0, 0);
67928 * filter(ERODE);
67929 * }
67930 * </code>
67931 * </div>
67932 *
67933 * @alt
67934 * black and white image of a brick wall.
67935 * greyscale image of a brickwall
67936 * image of a brickwall
67937 * jade colored image of a brickwall
67938 * red and pink image of a brickwall
67939 * image of a brickwall
67940 * blurry image of a brickwall
67941 * image of a brickwall
67942 * image of a brickwall with less detail
67943 */
67944 _main.default.prototype.filter = function(operation, value) {
67945 _main.default._validateParameters('filter', arguments);
67946 if (this.canvas !== undefined) {
67947 _filters.default.apply(this.canvas, _filters.default[operation], value);
67948 } else {
67949 _filters.default.apply(this.elt, _filters.default[operation], value);
67950 }
67951 };
67952
67953 /**
67954 * Get a region of pixels, or a single pixel, from the canvas.
67955 *
67956 * Returns an array of [R,G,B,A] values for any pixel or grabs a section of
67957 * an image. If no parameters are specified, the entire image is returned.
67958 * Use the x and y parameters to get the value of one pixel. Get a section of
67959 * the display window by specifying additional w and h parameters. When
67960 * getting an image, the x and y parameters define the coordinates for the
67961 * upper-left corner of the image, regardless of the current <a href="#/p5/imageMode">imageMode()</a>.
67962 *
67963 * Getting the color of a single pixel with get(x, y) is easy, but not as fast
67964 * as grabbing the data directly from <a href="#/p5/pixels">pixels[]</a>. The equivalent statement to
67965 * get(x, y) using <a href="#/p5/pixels">pixels[]</a> with pixel density d is
67966 * ```javascript
67967 * let x, y, d; // set these to the coordinates
67968 * let off = (y * width + x) * d * 4;
67969 * let components = [
67970 * pixels[off],
67971 * pixels[off + 1],
67972 * pixels[off + 2],
67973 * pixels[off + 3]
67974 * ];
67975 * print(components);
67976 * ```
67977 * See the reference for <a href="#/p5/pixels">pixels[]</a> for more information.
67978 *
67979 * If you want to extract an array of colors or a subimage from an p5.Image object,
67980 * take a look at <a href="#/p5.Image/get">p5.Image.get()</a>
67981 *
67982 * @method get
67983 * @param {Number} x x-coordinate of the pixel
67984 * @param {Number} y y-coordinate of the pixel
67985 * @param {Number} w width
67986 * @param {Number} h height
67987 * @return {p5.Image} the rectangle <a href="#/p5.Image">p5.Image</a>
67988 * @example
67989 * <div>
67990 * <code>
67991 * let img;
67992 * function preload() {
67993 * img = loadImage('assets/rockies.jpg');
67994 * }
67995 * function setup() {
67996 * image(img, 0, 0);
67997 * let c = get();
67998 * image(c, width / 2, 0);
67999 * }
68000 * </code>
68001 * </div>
68002 *
68003 * <div>
68004 * <code>
68005 * let img;
68006 * function preload() {
68007 * img = loadImage('assets/rockies.jpg');
68008 * }
68009 * function setup() {
68010 * image(img, 0, 0);
68011 * let c = get(50, 90);
68012 * fill(c);
68013 * noStroke();
68014 * rect(25, 25, 50, 50);
68015 * }
68016 * </code>
68017 * </div>
68018 *
68019 * @alt
68020 * 2 images of the rocky mountains, side-by-side
68021 * Image of the rocky mountains with 50x50 green rect in center of canvas
68022 */
68023 /**
68024 * @method get
68025 * @return {p5.Image} the whole <a href="#/p5.Image">p5.Image</a>
68026 */
68027 /**
68028 * @method get
68029 * @param {Number} x
68030 * @param {Number} y
68031 * @return {Number[]} color of pixel at x,y in array format [R, G, B, A]
68032 */
68033 _main.default.prototype.get = function(x, y, w, h) {
68034 var _this$_renderer2;
68035 _main.default._validateParameters('get', arguments);
68036 return (_this$_renderer2 = this._renderer).get.apply(
68037 _this$_renderer2,
68038 arguments
68039 );
68040 };
68041
68042 /**
68043 * Loads the pixel data for the display window into the <a href="#/p5/pixels">pixels[]</a> array. This
68044 * function must always be called before reading from or writing to <a href="#/p5/pixels">pixels[]</a>.
68045 * Note that only changes made with <a href="#/p5/set">set()</a> or direct manipulation of <a href="#/p5/pixels">pixels[]</a>
68046 * will occur.
68047 *
68048 * @method loadPixels
68049 * @example
68050 * <div>
68051 * <code>
68052 * let img;
68053 * function preload() {
68054 * img = loadImage('assets/rockies.jpg');
68055 * }
68056 *
68057 * function setup() {
68058 * image(img, 0, 0, width, height);
68059 * let d = pixelDensity();
68060 * let halfImage = 4 * (width * d) * (height * d / 2);
68061 * loadPixels();
68062 * for (let i = 0; i < halfImage; i++) {
68063 * pixels[i + halfImage] = pixels[i];
68064 * }
68065 * updatePixels();
68066 * }
68067 * </code>
68068 * </div>
68069 *
68070 * @alt
68071 * two images of the rocky mountains. one on top, one on bottom of canvas.
68072 */
68073 _main.default.prototype.loadPixels = function() {
68074 for (
68075 var _len3 = arguments.length, args = new Array(_len3), _key3 = 0;
68076 _key3 < _len3;
68077 _key3++
68078 ) {
68079 args[_key3] = arguments[_key3];
68080 }
68081 _main.default._validateParameters('loadPixels', args);
68082 this._renderer.loadPixels();
68083 };
68084
68085 /**
68086 * Changes the color of any pixel, or writes an image directly to the
68087 * display window.
68088 * The x and y parameters specify the pixel to change and the c parameter
68089 * specifies the color value. This can be a <a href="#/p5.Color">p5.Color</a> object, or [R, G, B, A]
68090 * pixel array. It can also be a single grayscale value.
68091 * When setting an image, the x and y parameters define the coordinates for
68092 * the upper-left corner of the image, regardless of the current <a href="#/p5/imageMode">imageMode()</a>.
68093 *
68094 * After using <a href="#/p5/set">set()</a>, you must call <a href="#/p5/updatePixels">updatePixels()</a> for your changes to appear.
68095 * This should be called once all pixels have been set, and must be called before
68096 * calling .<a href="#/p5/get">get()</a> or drawing the image.
68097 *
68098 * Setting the color of a single pixel with set(x, y) is easy, but not as
68099 * fast as putting the data directly into <a href="#/p5/pixels">pixels[]</a>. Setting the <a href="#/p5/pixels">pixels[]</a>
68100 * values directly may be complicated when working with a retina display,
68101 * but will perform better when lots of pixels need to be set directly on
68102 * every loop. See the reference for <a href="#/p5/pixels">pixels[]</a> for more information.
68103 *
68104 * @method set
68105 * @param {Number} x x-coordinate of the pixel
68106 * @param {Number} y y-coordinate of the pixel
68107 * @param {Number|Number[]|Object} c insert a grayscale value | a pixel array |
68108 * a <a href="#/p5.Color">p5.Color</a> object | a <a href="#/p5.Image">p5.Image</a> to copy
68109 * @example
68110 * <div>
68111 * <code>
68112 * let black = color(0);
68113 * set(30, 20, black);
68114 * set(85, 20, black);
68115 * set(85, 75, black);
68116 * set(30, 75, black);
68117 * updatePixels();
68118 * </code>
68119 * </div>
68120 *
68121 * <div>
68122 * <code>
68123 * for (let i = 30; i < width - 15; i++) {
68124 * for (let j = 20; j < height - 25; j++) {
68125 * let c = color(204 - j, 153 - i, 0);
68126 * set(i, j, c);
68127 * }
68128 * }
68129 * updatePixels();
68130 * </code>
68131 * </div>
68132 *
68133 * <div>
68134 * <code>
68135 * let img;
68136 * function preload() {
68137 * img = loadImage('assets/rockies.jpg');
68138 * }
68139 *
68140 * function setup() {
68141 * set(0, 0, img);
68142 * updatePixels();
68143 * line(0, 0, width, height);
68144 * line(0, height, width, 0);
68145 * }
68146 * </code>
68147 * </div>
68148 *
68149 * @alt
68150 * 4 black points in the shape of a square middle-right of canvas.
68151 * square with orangey-brown gradient lightening at bottom right.
68152 * image of the rocky mountains. with lines like an 'x' through the center.
68153 */
68154 _main.default.prototype.set = function(x, y, imgOrCol) {
68155 this._renderer.set(x, y, imgOrCol);
68156 };
68157 /**
68158 * Updates the display window with the data in the <a href="#/p5/pixels">pixels[]</a> array.
68159 * Use in conjunction with <a href="#/p5/loadPixels">loadPixels()</a>. If you're only reading pixels from
68160 * the array, there's no need to call <a href="#/p5/updatePixels">updatePixels()</a> — updating is only
68161 * necessary to apply changes. <a href="#/p5/updatePixels">updatePixels()</a> should be called anytime the
68162 * pixels array is manipulated or <a href="#/p5/set">set()</a> is called, and only changes made with
68163 * <a href="#/p5/set">set()</a> or direct changes to <a href="#/p5/pixels">pixels[]</a> will occur.
68164 *
68165 * @method updatePixels
68166 * @param {Number} [x] x-coordinate of the upper-left corner of region
68167 * to update
68168 * @param {Number} [y] y-coordinate of the upper-left corner of region
68169 * to update
68170 * @param {Number} [w] width of region to update
68171 * @param {Number} [h] height of region to update
68172 * @example
68173 * <div>
68174 * <code>
68175 * let img;
68176 * function preload() {
68177 * img = loadImage('assets/rockies.jpg');
68178 * }
68179 *
68180 * function setup() {
68181 * image(img, 0, 0, width, height);
68182 * let d = pixelDensity();
68183 * let halfImage = 4 * (width * d) * (height * d / 2);
68184 * loadPixels();
68185 * for (let i = 0; i < halfImage; i++) {
68186 * pixels[i + halfImage] = pixels[i];
68187 * }
68188 * updatePixels();
68189 * }
68190 * </code>
68191 * </div>
68192 * @alt
68193 * two images of the rocky mountains. one on top, one on bottom of canvas.
68194 */
68195 _main.default.prototype.updatePixels = function(x, y, w, h) {
68196 _main.default._validateParameters('updatePixels', arguments);
68197 // graceful fail - if loadPixels() or set() has not been called, pixel
68198 // array will be empty, ignore call to updatePixels()
68199 if (this.pixels.length === 0) {
68200 return;
68201 }
68202 this._renderer.updatePixels(x, y, w, h);
68203 };
68204 var _default = _main.default;
68205 exports.default = _default;
68206 },
68207 { '../color/p5.Color': 41, '../core/main': 54, './filters': 75 }
68208 ],
68209 80: [
68210 function(_dereq_, module, exports) {
68211 'use strict';
68212 Object.defineProperty(exports, '__esModule', { value: true });
68213 exports.default = void 0;
68214
68215 var _main = _interopRequireDefault(_dereq_('../core/main'));
68216 _dereq_('whatwg-fetch');
68217 _dereq_('es6-promise/auto');
68218 var _fetchJsonp = _interopRequireDefault(_dereq_('fetch-jsonp'));
68219 var _fileSaver = _interopRequireDefault(_dereq_('file-saver'));
68220 _dereq_('../core/friendly_errors/validate_params');
68221 _dereq_('../core/friendly_errors/file_errors');
68222 _dereq_('../core/friendly_errors/fes_core');
68223 function _interopRequireDefault(obj) {
68224 return obj && obj.__esModule ? obj : { default: obj };
68225 }
68226 function _typeof(obj) {
68227 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
68228 _typeof = function _typeof(obj) {
68229 return typeof obj;
68230 };
68231 } else {
68232 _typeof = function _typeof(obj) {
68233 return obj &&
68234 typeof Symbol === 'function' &&
68235 obj.constructor === Symbol &&
68236 obj !== Symbol.prototype
68237 ? 'symbol'
68238 : typeof obj;
68239 };
68240 }
68241 return _typeof(obj);
68242 }
68243
68244 /**
68245 * Loads a JSON file from a file or a URL, and returns an Object.
68246 * Note that even if the JSON file contains an Array, an Object will be
68247 * returned with index numbers as keys.
68248 *
68249 * This method is asynchronous, meaning it may not finish before the next
68250 * line in your sketch is executed. JSONP is supported via a polyfill and you
68251 * can pass in as the second argument an object with definitions of the json
68252 * callback following the syntax specified <a href="https://github.com/camsong/
68253 * fetch-jsonp">here</a>.
68254 *
68255 * This method is suitable for fetching files up to size of 64MB.
68256 * @method loadJSON
68257 * @param {String} path name of the file or url to load
68258 * @param {Object} [jsonpOptions] options object for jsonp related settings
68259 * @param {String} [datatype] "json" or "jsonp"
68260 * @param {function} [callback] function to be executed after
68261 * <a href="#/p5/loadJSON">loadJSON()</a> completes, data is passed
68262 * in as first argument
68263 * @param {function} [errorCallback] function to be executed if
68264 * there is an error, response is passed
68265 * in as first argument
68266 * @return {Object|Array} JSON data
68267 * @example
68268 *
68269 * Calling <a href="#/p5/loadJSON">loadJSON()</a> inside <a href="#/p5/preload">preload()</a> guarantees to complete the
68270 * operation before <a href="#/p5/setup">setup()</a> and <a href="#/p5/draw">draw()</a> are called.
68271 *
68272 * <div><code>
68273 * // Examples use USGS Earthquake API:
68274 * // https://earthquake.usgs.gov/fdsnws/event/1/#methods
68275 * let earthquakes;
68276 * function preload() {
68277 * // Get the most recent earthquake in the database
68278 * let url =
68279 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/' +
68280 * 'summary/all_day.geojson';
68281 * earthquakes = loadJSON(url);
68282 * }
68283 *
68284 * function setup() {
68285 * noLoop();
68286 * }
68287 *
68288 * function draw() {
68289 * background(200);
68290 * // Get the magnitude and name of the earthquake out of the loaded JSON
68291 * let earthquakeMag = earthquakes.features[0].properties.mag;
68292 * let earthquakeName = earthquakes.features[0].properties.place;
68293 * ellipse(width / 2, height / 2, earthquakeMag * 10, earthquakeMag * 10);
68294 * textAlign(CENTER);
68295 * text(earthquakeName, 0, height - 30, width, 30);
68296 * }
68297 * </code></div>
68298 *
68299 * Outside of preload(), you may supply a callback function to handle the
68300 * object:
68301 * <div><code>
68302 * function setup() {
68303 * noLoop();
68304 * let url =
68305 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/' +
68306 * 'summary/all_day.geojson';
68307 * loadJSON(url, drawEarthquake);
68308 * }
68309 *
68310 * function draw() {
68311 * background(200);
68312 * }
68313 *
68314 * function drawEarthquake(earthquakes) {
68315 * // Get the magnitude and name of the earthquake out of the loaded JSON
68316 * let earthquakeMag = earthquakes.features[0].properties.mag;
68317 * let earthquakeName = earthquakes.features[0].properties.place;
68318 * ellipse(width / 2, height / 2, earthquakeMag * 10, earthquakeMag * 10);
68319 * textAlign(CENTER);
68320 * text(earthquakeName, 0, height - 30, width, 30);
68321 * }
68322 * </code></div>
68323 *
68324 * @alt
68325 * 50x50 ellipse that changes from black to white depending on the current humidity
68326 * 50x50 ellipse that changes from black to white depending on the current humidity
68327 */
68328 /**
68329 * @method loadJSON
68330 * @param {String} path
68331 * @param {String} datatype
68332 * @param {function} [callback]
68333 * @param {function} [errorCallback]
68334 * @return {Object|Array}
68335 */
68336 /**
68337 * @method loadJSON
68338 * @param {String} path
68339 * @param {function} callback
68340 * @param {function} [errorCallback]
68341 * @return {Object|Array}
68342 */
68343 _main.default.prototype.loadJSON = function() {
68344 for (
68345 var _len = arguments.length, args = new Array(_len), _key = 0;
68346 _key < _len;
68347 _key++
68348 ) {
68349 args[_key] = arguments[_key];
68350 }
68351 _main.default._validateParameters('loadJSON', args);
68352 var path = args[0];
68353 var callback;
68354 var errorCallback;
68355 var options;
68356
68357 var ret = {}; // object needed for preload
68358 var t = 'json';
68359
68360 // check for explicit data type argument
68361 for (var i = 1; i < args.length; i++) {
68362 var arg = args[i];
68363 if (typeof arg === 'string') {
68364 if (arg === 'jsonp' || arg === 'json') {
68365 t = arg;
68366 }
68367 } else if (typeof arg === 'function') {
68368 if (!callback) {
68369 callback = arg;
68370 } else {
68371 errorCallback = arg;
68372 }
68373 } else if (
68374 _typeof(arg) === 'object' &&
68375 (arg.hasOwnProperty('jsonpCallback') ||
68376 arg.hasOwnProperty('jsonpCallbackFunction'))
68377 ) {
68378 t = 'jsonp';
68379 options = arg;
68380 }
68381 }
68382
68383 var self = this;
68384 this.httpDo(
68385 path,
68386 'GET',
68387 options,
68388 t,
68389 function(resp) {
68390 for (var k in resp) {
68391 ret[k] = resp[k];
68392 }
68393 if (typeof callback !== 'undefined') {
68394 callback(resp);
68395 }
68396
68397 self._decrementPreload();
68398 },
68399 function(err) {
68400 // Error handling
68401 _main.default._friendlyFileLoadError(5, path);
68402
68403 if (errorCallback) {
68404 errorCallback(err);
68405 } else {
68406 throw err;
68407 }
68408 }
68409 );
68410
68411 return ret;
68412 };
68413
68414 /**
68415 * Reads the contents of a file and creates a String array of its individual
68416 * lines. If the name of the file is used as the parameter, as in the above
68417 * example, the file must be located in the sketch directory/folder.
68418 *
68419 * Alternatively, the file maybe be loaded from anywhere on the local
68420 * computer using an absolute path (something that starts with / on Unix and
68421 * Linux, or a drive letter on Windows), or the filename parameter can be a
68422 * URL for a file found on a network.
68423 *
68424 * This method is asynchronous, meaning it may not finish before the next
68425 * line in your sketch is executed.
68426 *
68427 * This method is suitable for fetching files up to size of 64MB.
68428 * @method loadStrings
68429 * @param {String} filename name of the file or url to load
68430 * @param {function} [callback] function to be executed after <a href="#/p5/loadStrings">loadStrings()</a>
68431 * completes, Array is passed in as first
68432 * argument
68433 * @param {function} [errorCallback] function to be executed if
68434 * there is an error, response is passed
68435 * in as first argument
68436 * @return {String[]} Array of Strings
68437 * @example
68438 *
68439 * Calling loadStrings() inside <a href="#/p5/preload">preload()</a> guarantees to complete the
68440 * operation before <a href="#/p5/setup">setup()</a> and <a href="#/p5/draw">draw()</a> are called.
68441 *
68442 * <div><code>
68443 * let result;
68444 * function preload() {
68445 * result = loadStrings('assets/test.txt');
68446 * }
68447
68448 * function setup() {
68449 * background(200);
68450 * text(random(result), 10, 10, 80, 80);
68451 * }
68452 * </code></div>
68453 *
68454 * Outside of preload(), you may supply a callback function to handle the
68455 * object:
68456 *
68457 * <div><code>
68458 * function setup() {
68459 * loadStrings('assets/test.txt', pickString);
68460 * }
68461 *
68462 * function pickString(result) {
68463 * background(200);
68464 * text(random(result), 10, 10, 80, 80);
68465 * }
68466 * </code></div>
68467 *
68468 * @alt
68469 * randomly generated text from a file, for example "i smell like butter"
68470 * randomly generated text from a file, for example "i have three feet"
68471 */
68472 _main.default.prototype.loadStrings = function() {
68473 for (
68474 var _len2 = arguments.length, args = new Array(_len2), _key2 = 0;
68475 _key2 < _len2;
68476 _key2++
68477 ) {
68478 args[_key2] = arguments[_key2];
68479 }
68480 _main.default._validateParameters('loadStrings', args);
68481
68482 var ret = [];
68483 var callback, errorCallback;
68484
68485 for (var i = 1; i < args.length; i++) {
68486 var arg = args[i];
68487 if (typeof arg === 'function') {
68488 if (typeof callback === 'undefined') {
68489 callback = arg;
68490 } else if (typeof errorCallback === 'undefined') {
68491 errorCallback = arg;
68492 }
68493 }
68494 }
68495
68496 var self = this;
68497 _main.default.prototype.httpDo.call(
68498 this,
68499 args[0],
68500 'GET',
68501 'text',
68502 function(data) {
68503 // split lines handling mac/windows/linux endings
68504 var lines = data
68505 .replace(/\r\n/g, '\r')
68506 .replace(/\n/g, '\r')
68507 .split(/\r/);
68508 Array.prototype.push.apply(ret, lines);
68509
68510 if (typeof callback !== 'undefined') {
68511 callback(ret);
68512 }
68513
68514 self._decrementPreload();
68515 },
68516 function(err) {
68517 // Error handling
68518 _main.default._friendlyFileLoadError(3, arguments[0]);
68519
68520 if (errorCallback) {
68521 errorCallback(err);
68522 } else {
68523 throw err;
68524 }
68525 }
68526 );
68527
68528 return ret;
68529 };
68530
68531 /**
68532 * Reads the contents of a file or URL and creates a <a href="#/p5.Table">p5.Table</a> object with
68533 * its values. If a file is specified, it must be located in the sketch's
68534 * "data" folder. The filename parameter can also be a URL to a file found
68535 * online. By default, the file is assumed to be comma-separated (in CSV
68536 * format). Table only looks for a header row if the 'header' option is
68537 * included.
68538 *
68539 * This method is asynchronous, meaning it may not finish before the next
68540 * line in your sketch is executed. Calling <a href="#/p5/loadTable">loadTable()</a> inside <a href="#/p5/preload">preload()</a>
68541 * guarantees to complete the operation before <a href="#/p5/setup">setup()</a> and <a href="#/p5/draw">draw()</a> are called.
68542 * Outside of <a href="#/p5/preload">preload()</a>, you may supply a callback function to handle the
68543 * object:
68544 *
68545 * All files loaded and saved use UTF-8 encoding. This method is suitable for fetching files up to size of 64MB.
68546 * @method loadTable
68547 * @param {String} filename name of the file or URL to load
68548 * @param {String} [extension] parse the table by comma-separated values "csv", semicolon-separated
68549 * values "ssv", or tab-separated values "tsv"
68550 * @param {String} [header] "header" to indicate table has header row
68551 * @param {function} [callback] function to be executed after
68552 * <a href="#/p5/loadTable">loadTable()</a> completes. On success, the
68553 * <a href="#/p5.Table">Table</a> object is passed in as the
68554 * first argument.
68555 * @param {function} [errorCallback] function to be executed if
68556 * there is an error, response is passed
68557 * in as first argument
68558 * @return {Object} <a href="#/p5.Table">Table</a> object containing data
68559 *
68560 * @example
68561 * <div class='norender'>
68562 * <code>
68563 * // Given the following CSV file called "mammals.csv"
68564 * // located in the project's "assets" folder:
68565 * //
68566 * // id,species,name
68567 * // 0,Capra hircus,Goat
68568 * // 1,Panthera pardus,Leopard
68569 * // 2,Equus zebra,Zebra
68570 *
68571 * let table;
68572 *
68573 * function preload() {
68574 * //my table is comma separated value "csv"
68575 * //and has a header specifying the columns labels
68576 * table = loadTable('assets/mammals.csv', 'csv', 'header');
68577 * //the file can be remote
68578 * //table = loadTable("http://p5js.org/reference/assets/mammals.csv",
68579 * // "csv", "header");
68580 * }
68581 *
68582 * function setup() {
68583 * //count the columns
68584 * print(table.getRowCount() + ' total rows in table');
68585 * print(table.getColumnCount() + ' total columns in table');
68586 *
68587 * print(table.getColumn('name'));
68588 * //["Goat", "Leopard", "Zebra"]
68589 *
68590 * //cycle through the table
68591 * for (let r = 0; r < table.getRowCount(); r++)
68592 * for (let c = 0; c < table.getColumnCount(); c++) {
68593 * print(table.getString(r, c));
68594 * }
68595 * }
68596 * </code>
68597 * </div>
68598 *
68599 * @alt
68600 * randomly generated text from a file, for example "i smell like butter"
68601 * randomly generated text from a file, for example "i have three feet"
68602 */
68603 _main.default.prototype.loadTable = function(path) {
68604 // p5._validateParameters('loadTable', arguments);
68605 var callback;
68606 var errorCallback;
68607 var options = [];
68608 var header = false;
68609 var ext = path.substring(path.lastIndexOf('.') + 1, path.length);
68610
68611 var sep;
68612 if (ext === 'csv') {
68613 sep = ',';
68614 } else if (ext === 'ssv') {
68615 sep = ';';
68616 } else if (ext === 'tsv') {
68617 sep = '\t';
68618 }
68619
68620 for (var i = 1; i < arguments.length; i++) {
68621 if (typeof arguments[i] === 'function') {
68622 if (typeof callback === 'undefined') {
68623 callback = arguments[i];
68624 } else if (typeof errorCallback === 'undefined') {
68625 errorCallback = arguments[i];
68626 }
68627 } else if (typeof arguments[i] === 'string') {
68628 options.push(arguments[i]);
68629 if (arguments[i] === 'header') {
68630 header = true;
68631 }
68632 if (arguments[i] === 'csv') {
68633 sep = ',';
68634 } else if (arguments[i] === 'ssv') {
68635 sep = ';';
68636 } else if (arguments[i] === 'tsv') {
68637 sep = '\t';
68638 }
68639 }
68640 }
68641
68642 console.log('SEP IS ' + sep);
68643
68644 var t = new _main.default.Table();
68645
68646 var self = this;
68647 this.httpDo(
68648 path,
68649 'GET',
68650 'table',
68651 function(resp) {
68652 var state = {};
68653
68654 // define constants
68655 var PRE_TOKEN = 0,
68656 MID_TOKEN = 1,
68657 POST_TOKEN = 2,
68658 POST_RECORD = 4;
68659
68660 var QUOTE = '"',
68661 CR = '\r',
68662 LF = '\n';
68663
68664 var records = [];
68665 var offset = 0;
68666 var currentRecord = null;
68667 var currentChar;
68668
68669 var tokenBegin = function tokenBegin() {
68670 state.currentState = PRE_TOKEN;
68671 state.token = '';
68672 };
68673
68674 var tokenEnd = function tokenEnd() {
68675 currentRecord.push(state.token);
68676 tokenBegin();
68677 };
68678
68679 var recordBegin = function recordBegin() {
68680 state.escaped = false;
68681 currentRecord = [];
68682 tokenBegin();
68683 };
68684
68685 var recordEnd = function recordEnd() {
68686 state.currentState = POST_RECORD;
68687 records.push(currentRecord);
68688 currentRecord = null;
68689 };
68690
68691 for (;;) {
68692 currentChar = resp[offset++];
68693
68694 // EOF
68695 if (currentChar == null) {
68696 if (state.escaped) {
68697 throw new Error('Unclosed quote in file.');
68698 }
68699 if (currentRecord) {
68700 tokenEnd();
68701 recordEnd();
68702 break;
68703 }
68704 }
68705 if (currentRecord === null) {
68706 recordBegin();
68707 }
68708
68709 // Handle opening quote
68710 if (state.currentState === PRE_TOKEN) {
68711 if (currentChar === QUOTE) {
68712 state.escaped = true;
68713 state.currentState = MID_TOKEN;
68714 continue;
68715 }
68716 state.currentState = MID_TOKEN;
68717 }
68718
68719 // mid-token and escaped, look for sequences and end quote
68720 if (state.currentState === MID_TOKEN && state.escaped) {
68721 if (currentChar === QUOTE) {
68722 if (resp[offset] === QUOTE) {
68723 state.token += QUOTE;
68724 offset++;
68725 } else {
68726 state.escaped = false;
68727 state.currentState = POST_TOKEN;
68728 }
68729 } else if (currentChar === CR) {
68730 continue;
68731 } else {
68732 state.token += currentChar;
68733 }
68734 continue;
68735 }
68736
68737 // fall-through: mid-token or post-token, not escaped
68738 if (currentChar === CR) {
68739 if (resp[offset] === LF) {
68740 offset++;
68741 }
68742 tokenEnd();
68743 recordEnd();
68744 } else if (currentChar === LF) {
68745 tokenEnd();
68746 recordEnd();
68747 } else if (currentChar === sep) {
68748 tokenEnd();
68749 } else if (state.currentState === MID_TOKEN) {
68750 state.token += currentChar;
68751 }
68752 }
68753
68754 // set up column names
68755 if (header) {
68756 t.columns = records.shift();
68757 } else {
68758 for (var _i = 0; _i < records[0].length; _i++) {
68759 t.columns[_i] = 'null';
68760 }
68761 }
68762 var row;
68763 for (var _i2 = 0; _i2 < records.length; _i2++) {
68764 //Handles row of 'undefined' at end of some CSVs
68765 if (records[_i2].length === 1) {
68766 if (records[_i2][0] === 'undefined' || records[_i2][0] === '') {
68767 continue;
68768 }
68769 }
68770 row = new _main.default.TableRow();
68771 row.arr = records[_i2];
68772 row.obj = makeObject(records[_i2], t.columns);
68773 t.addRow(row);
68774 }
68775 if (typeof callback === 'function') {
68776 callback(t);
68777 }
68778
68779 self._decrementPreload();
68780 },
68781 function(err) {
68782 // Error handling
68783 _main.default._friendlyFileLoadError(2, path);
68784
68785 if (errorCallback) {
68786 errorCallback(err);
68787 } else {
68788 console.error(err);
68789 }
68790 }
68791 );
68792
68793 return t;
68794 };
68795
68796 // helper function to turn a row into a JSON object
68797 function makeObject(row, headers) {
68798 var ret = {};
68799 headers = headers || [];
68800 if (typeof headers === 'undefined') {
68801 for (var j = 0; j < row.length; j++) {
68802 headers[j.toString()] = j;
68803 }
68804 }
68805 for (var i = 0; i < headers.length; i++) {
68806 var key = headers[i];
68807 var val = row[i];
68808 ret[key] = val;
68809 }
68810 return ret;
68811 }
68812
68813 /**
68814 * Reads the contents of a file and creates an XML object with its values.
68815 * If the name of the file is used as the parameter, as in the above example,
68816 * the file must be located in the sketch directory/folder.
68817 *
68818 * Alternatively, the file maybe be loaded from anywhere on the local
68819 * computer using an absolute path (something that starts with / on Unix and
68820 * Linux, or a drive letter on Windows), or the filename parameter can be a
68821 * URL for a file found on a network.
68822 *
68823 * This method is asynchronous, meaning it may not finish before the next
68824 * line in your sketch is executed. Calling <a href="#/p5/loadXML">loadXML()</a> inside <a href="#/p5/preload">preload()</a>
68825 * guarantees to complete the operation before <a href="#/p5/setup">setup()</a> and <a href="#/p5/draw">draw()</a> are called.
68826 *
68827 * Outside of <a href="#/p5/preload">preload()</a>, you may supply a callback function to handle the
68828 * object.
68829 *
68830 * This method is suitable for fetching files up to size of 64MB.
68831 * @method loadXML
68832 * @param {String} filename name of the file or URL to load
68833 * @param {function} [callback] function to be executed after <a href="#/p5/loadXML">loadXML()</a>
68834 * completes, XML object is passed in as
68835 * first argument
68836 * @param {function} [errorCallback] function to be executed if
68837 * there is an error, response is passed
68838 * in as first argument
68839 * @return {Object} XML object containing data
68840 * @example
68841 * <div class='norender'><code>
68842 * // The following short XML file called "mammals.xml" is parsed
68843 * // in the code below.
68844 * //
68845 * // <?xml version="1.0"?>
68846 * // &lt;mammals&gt;
68847 * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
68848 * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
68849 * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
68850 * // &lt;/mammals&gt;
68851 *
68852 * let xml;
68853 *
68854 * function preload() {
68855 * xml = loadXML('assets/mammals.xml');
68856 * }
68857 *
68858 * function setup() {
68859 * let children = xml.getChildren('animal');
68860 *
68861 * for (let i = 0; i < children.length; i++) {
68862 * let id = children[i].getNum('id');
68863 * let coloring = children[i].getString('species');
68864 * let name = children[i].getContent();
68865 * print(id + ', ' + coloring + ', ' + name);
68866 * }
68867 * }
68868 *
68869 * // Sketch prints:
68870 * // 0, Capra hircus, Goat
68871 * // 1, Panthera pardus, Leopard
68872 * // 2, Equus zebra, Zebra
68873 * </code></div>
68874 *
68875 * @alt
68876 * no image displayed
68877 */
68878 _main.default.prototype.loadXML = function() {
68879 for (
68880 var _len3 = arguments.length, args = new Array(_len3), _key3 = 0;
68881 _key3 < _len3;
68882 _key3++
68883 ) {
68884 args[_key3] = arguments[_key3];
68885 }
68886 var ret = new _main.default.XML();
68887 var callback, errorCallback;
68888
68889 for (var i = 1; i < args.length; i++) {
68890 var arg = args[i];
68891 if (typeof arg === 'function') {
68892 if (typeof callback === 'undefined') {
68893 callback = arg;
68894 } else if (typeof errorCallback === 'undefined') {
68895 errorCallback = arg;
68896 }
68897 }
68898 }
68899
68900 var self = this;
68901 this.httpDo(
68902 args[0],
68903 'GET',
68904 'xml',
68905 function(xml) {
68906 for (var key in xml) {
68907 ret[key] = xml[key];
68908 }
68909 if (typeof callback !== 'undefined') {
68910 callback(ret);
68911 }
68912
68913 self._decrementPreload();
68914 },
68915 function(err) {
68916 // Error handling
68917 _main.default._friendlyFileLoadError(1, arguments[0]);
68918
68919 if (errorCallback) {
68920 errorCallback(err);
68921 } else {
68922 throw err;
68923 }
68924 }
68925 );
68926
68927 return ret;
68928 };
68929
68930 /**
68931 * This method is suitable for fetching files up to size of 64MB.
68932 * @method loadBytes
68933 * @param {string} file name of the file or URL to load
68934 * @param {function} [callback] function to be executed after <a href="#/p5/loadBytes">loadBytes()</a>
68935 * completes
68936 * @param {function} [errorCallback] function to be executed if there
68937 * is an error
68938 * @returns {Object} an object whose 'bytes' property will be the loaded buffer
68939 *
68940 * @example
68941 * <div class='norender'><code>
68942 * let data;
68943 *
68944 * function preload() {
68945 * data = loadBytes('assets/mammals.xml');
68946 * }
68947 *
68948 * function setup() {
68949 * for (let i = 0; i < 5; i++) {
68950 * console.log(data.bytes[i].toString(16));
68951 * }
68952 * }
68953 * </code></div>
68954 *
68955 * @alt
68956 * no image displayed
68957 */
68958 _main.default.prototype.loadBytes = function(file, callback, errorCallback) {
68959 var ret = {};
68960
68961 var self = this;
68962 this.httpDo(
68963 file,
68964 'GET',
68965 'arrayBuffer',
68966 function(arrayBuffer) {
68967 ret.bytes = new Uint8Array(arrayBuffer);
68968
68969 if (typeof callback === 'function') {
68970 callback(ret);
68971 }
68972
68973 self._decrementPreload();
68974 },
68975 function(err) {
68976 // Error handling
68977 _main.default._friendlyFileLoadError(6, file);
68978
68979 if (errorCallback) {
68980 errorCallback(err);
68981 } else {
68982 throw err;
68983 }
68984 }
68985 );
68986
68987 return ret;
68988 };
68989
68990 /**
68991 * Method for executing an HTTP GET request. If data type is not specified,
68992 * p5 will try to guess based on the URL, defaulting to text. This is equivalent to
68993 * calling <code>httpDo(path, 'GET')</code>. The 'binary' datatype will return
68994 * a Blob object, and the 'arrayBuffer' datatype will return an ArrayBuffer
68995 * which can be used to initialize typed arrays (such as Uint8Array).
68996 *
68997 * @method httpGet
68998 * @param {String} path name of the file or url to load
68999 * @param {String} [datatype] "json", "jsonp", "binary", "arrayBuffer",
69000 * "xml", or "text"
69001 * @param {Object|Boolean} [data] param data passed sent with request
69002 * @param {function} [callback] function to be executed after
69003 * <a href="#/p5/httpGet">httpGet()</a> completes, data is passed in
69004 * as first argument
69005 * @param {function} [errorCallback] function to be executed if
69006 * there is an error, response is passed
69007 * in as first argument
69008 * @return {Promise} A promise that resolves with the data when the operation
69009 * completes successfully or rejects with the error after
69010 * one occurs.
69011 * @example
69012 * <div class='norender'><code>
69013 * // Examples use USGS Earthquake API:
69014 * // https://earthquake.usgs.gov/fdsnws/event/1/#methods
69015 * let earthquakes;
69016 * function preload() {
69017 * // Get the most recent earthquake in the database
69018 * let url =
69019 'https://earthquake.usgs.gov/fdsnws/event/1/query?' +
69020 * 'format=geojson&limit=1&orderby=time';
69021 * httpGet(url, 'jsonp', false, function(response) {
69022 * // when the HTTP request completes, populate the variable that holds the
69023 * // earthquake data used in the visualization.
69024 * earthquakes = response;
69025 * });
69026 * }
69027 *
69028 * function draw() {
69029 * if (!earthquakes) {
69030 * // Wait until the earthquake data has loaded before drawing.
69031 * return;
69032 * }
69033 * background(200);
69034 * // Get the magnitude and name of the earthquake out of the loaded JSON
69035 * let earthquakeMag = earthquakes.features[0].properties.mag;
69036 * let earthquakeName = earthquakes.features[0].properties.place;
69037 * ellipse(width / 2, height / 2, earthquakeMag * 10, earthquakeMag * 10);
69038 * textAlign(CENTER);
69039 * text(earthquakeName, 0, height - 30, width, 30);
69040 * noLoop();
69041 * }
69042 * </code></div>
69043 */
69044 /**
69045 * @method httpGet
69046 * @param {String} path
69047 * @param {Object|Boolean} data
69048 * @param {function} [callback]
69049 * @param {function} [errorCallback]
69050 * @return {Promise}
69051 */
69052 /**
69053 * @method httpGet
69054 * @param {String} path
69055 * @param {function} callback
69056 * @param {function} [errorCallback]
69057 * @return {Promise}
69058 */
69059 _main.default.prototype.httpGet = function() {
69060 _main.default._validateParameters('httpGet', arguments);
69061
69062 var args = Array.prototype.slice.call(arguments);
69063 args.splice(1, 0, 'GET');
69064 return _main.default.prototype.httpDo.apply(this, args);
69065 };
69066
69067 /**
69068 * Method for executing an HTTP POST request. If data type is not specified,
69069 * p5 will try to guess based on the URL, defaulting to text. This is equivalent to
69070 * calling <code>httpDo(path, 'POST')</code>.
69071 *
69072 * @method httpPost
69073 * @param {String} path name of the file or url to load
69074 * @param {String} [datatype] "json", "jsonp", "xml", or "text".
69075 * If omitted, <a href="#/p5/httpPost">httpPost()</a> will guess.
69076 * @param {Object|Boolean} [data] param data passed sent with request
69077 * @param {function} [callback] function to be executed after
69078 * <a href="#/p5/httpPost">httpPost()</a> completes, data is passed in
69079 * as first argument
69080 * @param {function} [errorCallback] function to be executed if
69081 * there is an error, response is passed
69082 * in as first argument
69083 * @return {Promise} A promise that resolves with the data when the operation
69084 * completes successfully or rejects with the error after
69085 * one occurs.
69086 *
69087 * @example
69088 * <div>
69089 * <code>
69090 * // Examples use jsonplaceholder.typicode.com for a Mock Data API
69091 *
69092 * let url = 'https://jsonplaceholder.typicode.com/posts';
69093 * let postData = { userId: 1, title: 'p5 Clicked!', body: 'p5.js is way cool.' };
69094 *
69095 * function setup() {
69096 * createCanvas(800, 800);
69097 * }
69098 *
69099 * function mousePressed() {
69100 * // Pick new random color values
69101 * let r = random(255);
69102 * let g = random(255);
69103 * let b = random(255);
69104 *
69105 * httpPost(url, 'json', postData, function(result) {
69106 * strokeWeight(2);
69107 * stroke(r, g, b);
69108 * fill(r, g, b, 127);
69109 * ellipse(mouseX, mouseY, 200, 200);
69110 * text(result.body, mouseX, mouseY);
69111 * });
69112 * }
69113 * </code>
69114 * </div>
69115 *
69116 * <div><code>
69117 * let url = 'ttps://invalidURL'; // A bad URL that will cause errors
69118 * let postData = { title: 'p5 Clicked!', body: 'p5.js is way cool.' };
69119 *
69120 * function setup() {
69121 * createCanvas(800, 800);
69122 * }
69123 *
69124 * function mousePressed() {
69125 * // Pick new random color values
69126 * let r = random(255);
69127 * let g = random(255);
69128 * let b = random(255);
69129 *
69130 * httpPost(
69131 * url,
69132 * 'json',
69133 * postData,
69134 * function(result) {
69135 * // ... won't be called
69136 * },
69137 * function(error) {
69138 * strokeWeight(2);
69139 * stroke(r, g, b);
69140 * fill(r, g, b, 127);
69141 * text(error.toString(), mouseX, mouseY);
69142 * }
69143 * );
69144 * }
69145 * </code></div>
69146 */
69147 /**
69148 * @method httpPost
69149 * @param {String} path
69150 * @param {Object|Boolean} data
69151 * @param {function} [callback]
69152 * @param {function} [errorCallback]
69153 * @return {Promise}
69154 */
69155 /**
69156 * @method httpPost
69157 * @param {String} path
69158 * @param {function} callback
69159 * @param {function} [errorCallback]
69160 * @return {Promise}
69161 */
69162 _main.default.prototype.httpPost = function() {
69163 _main.default._validateParameters('httpPost', arguments);
69164
69165 var args = Array.prototype.slice.call(arguments);
69166 args.splice(1, 0, 'POST');
69167 return _main.default.prototype.httpDo.apply(this, args);
69168 };
69169
69170 /**
69171 * Method for executing an HTTP request. If data type is not specified,
69172 * p5 will try to guess based on the URL, defaulting to text.<br><br>
69173 * For more advanced use, you may also pass in the path as the first argument
69174 * and a object as the second argument, the signature follows the one specified
69175 * in the Fetch API specification.
69176 * This method is suitable for fetching files up to size of 64MB when "GET" is used.
69177 *
69178 * @method httpDo
69179 * @param {String} path name of the file or url to load
69180 * @param {String} [method] either "GET", "POST", or "PUT",
69181 * defaults to "GET"
69182 * @param {String} [datatype] "json", "jsonp", "xml", or "text"
69183 * @param {Object} [data] param data passed sent with request
69184 * @param {function} [callback] function to be executed after
69185 * <a href="#/p5/httpGet">httpGet()</a> completes, data is passed in
69186 * as first argument
69187 * @param {function} [errorCallback] function to be executed if
69188 * there is an error, response is passed
69189 * in as first argument
69190 * @return {Promise} A promise that resolves with the data when the operation
69191 * completes successfully or rejects with the error after
69192 * one occurs.
69193 *
69194 * @example
69195 * <div>
69196 * <code>
69197 * // Examples use USGS Earthquake API:
69198 * // https://earthquake.usgs.gov/fdsnws/event/1/#methods
69199 *
69200 * // displays an animation of all USGS earthquakes
69201 * let earthquakes;
69202 * let eqFeatureIndex = 0;
69203 *
69204 * function preload() {
69205 * let url = 'https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson';
69206 * httpDo(
69207 * url,
69208 * {
69209 * method: 'GET',
69210 * // Other Request options, like special headers for apis
69211 * headers: { authorization: 'Bearer secretKey' }
69212 * },
69213 * function(res) {
69214 * earthquakes = res;
69215 * }
69216 * );
69217 * }
69218 *
69219 * function draw() {
69220 * // wait until the data is loaded
69221 * if (!earthquakes || !earthquakes.features[eqFeatureIndex]) {
69222 * return;
69223 * }
69224 * clear();
69225 *
69226 * let feature = earthquakes.features[eqFeatureIndex];
69227 * let mag = feature.properties.mag;
69228 * let rad = mag / 11 * ((width + height) / 2);
69229 * fill(255, 0, 0, 100);
69230 * ellipse(width / 2 + random(-2, 2), height / 2 + random(-2, 2), rad, rad);
69231 *
69232 * if (eqFeatureIndex >= earthquakes.features.length) {
69233 * eqFeatureIndex = 0;
69234 * } else {
69235 * eqFeatureIndex += 1;
69236 * }
69237 * }
69238 * </code>
69239 * </div>
69240 */
69241 /**
69242 * @method httpDo
69243 * @param {String} path
69244 * @param {Object} options Request object options as documented in the
69245 * "fetch" API
69246 * <a href="https://developer.mozilla.org/en/docs/Web/API/Fetch_API">reference</a>
69247 * @param {function} [callback]
69248 * @param {function} [errorCallback]
69249 * @return {Promise}
69250 */
69251 _main.default.prototype.httpDo = function() {
69252 var type;
69253 var callback;
69254 var errorCallback;
69255 var request;
69256 var promise;
69257 var jsonpOptions = {};
69258 var cbCount = 0;
69259 var contentType = 'text/plain';
69260 // Trim the callbacks off the end to get an idea of how many arguments are passed
69261 for (var i = arguments.length - 1; i > 0; i--) {
69262 if (
69263 typeof (i < 0 || arguments.length <= i ? undefined : arguments[i]) ===
69264 'function'
69265 ) {
69266 cbCount++;
69267 } else {
69268 break;
69269 }
69270 }
69271 // The number of arguments minus callbacks
69272 var argsCount = arguments.length - cbCount;
69273 var path = arguments.length <= 0 ? undefined : arguments[0];
69274 if (
69275 argsCount === 2 &&
69276 typeof path === 'string' &&
69277 _typeof(arguments.length <= 1 ? undefined : arguments[1]) === 'object'
69278 ) {
69279 // Intended for more advanced use, pass in Request parameters directly
69280 request = new Request(path, arguments.length <= 1 ? undefined : arguments[1]);
69281 callback = arguments.length <= 2 ? undefined : arguments[2];
69282 errorCallback = arguments.length <= 3 ? undefined : arguments[3];
69283 } else {
69284 // Provided with arguments
69285 var method = 'GET';
69286 var data;
69287
69288 for (var j = 1; j < arguments.length; j++) {
69289 var a = j < 0 || arguments.length <= j ? undefined : arguments[j];
69290 if (typeof a === 'string') {
69291 if (a === 'GET' || a === 'POST' || a === 'PUT' || a === 'DELETE') {
69292 method = a;
69293 } else if (
69294 a === 'json' ||
69295 a === 'jsonp' ||
69296 a === 'binary' ||
69297 a === 'arrayBuffer' ||
69298 a === 'xml' ||
69299 a === 'text' ||
69300 a === 'table'
69301 ) {
69302 type = a;
69303 } else {
69304 data = a;
69305 }
69306 } else if (typeof a === 'number') {
69307 data = a.toString();
69308 } else if (_typeof(a) === 'object') {
69309 if (
69310 a.hasOwnProperty('jsonpCallback') ||
69311 a.hasOwnProperty('jsonpCallbackFunction')
69312 ) {
69313 for (var attr in a) {
69314 jsonpOptions[attr] = a[attr];
69315 }
69316 } else if (a instanceof _main.default.XML) {
69317 data = a.serialize();
69318 contentType = 'application/xml';
69319 } else {
69320 data = JSON.stringify(a);
69321 contentType = 'application/json';
69322 }
69323 } else if (typeof a === 'function') {
69324 if (!callback) {
69325 callback = a;
69326 } else {
69327 errorCallback = a;
69328 }
69329 }
69330 }
69331
69332 var headers =
69333 method === 'GET'
69334 ? new Headers()
69335 : new Headers({ 'Content-Type': contentType });
69336
69337 request = new Request(path, {
69338 method: method,
69339 mode: 'cors',
69340 body: data,
69341 headers: headers
69342 });
69343 }
69344 // do some sort of smart type checking
69345 if (!type) {
69346 if (path.includes('json')) {
69347 type = 'json';
69348 } else if (path.includes('xml')) {
69349 type = 'xml';
69350 } else {
69351 type = 'text';
69352 }
69353 }
69354
69355 if (type === 'jsonp') {
69356 promise = (0, _fetchJsonp.default)(path, jsonpOptions);
69357 } else {
69358 promise = fetch(request);
69359 }
69360 promise = promise.then(function(res) {
69361 if (!res.ok) {
69362 var err = new Error(res.body);
69363 err.status = res.status;
69364 err.ok = false;
69365 throw err;
69366 } else {
69367 var fileSize = 0;
69368 if (type !== 'jsonp') {
69369 fileSize = res.headers.get('content-length');
69370 }
69371 if (fileSize && fileSize > 64000000) {
69372 _main.default._friendlyFileLoadError(7, path);
69373 }
69374 switch (type) {
69375 case 'json':
69376 case 'jsonp':
69377 return res.json();
69378 case 'binary':
69379 return res.blob();
69380 case 'arrayBuffer':
69381 return res.arrayBuffer();
69382 case 'xml':
69383 return res.text().then(function(text) {
69384 var parser = new DOMParser();
69385 var xml = parser.parseFromString(text, 'text/xml');
69386 return new _main.default.XML(xml.documentElement);
69387 });
69388 default:
69389 return res.text();
69390 }
69391 }
69392 });
69393 promise.then(callback || function() {});
69394 promise.catch(errorCallback || console.error);
69395 return promise;
69396 };
69397
69398 /**
69399 * @module IO
69400 * @submodule Output
69401 * @for p5
69402 */
69403
69404 window.URL = window.URL || window.webkitURL;
69405
69406 // private array of p5.PrintWriter objects
69407 _main.default.prototype._pWriters = [];
69408
69409 /**
69410 * @method createWriter
69411 * @param {String} name name of the file to be created
69412 * @param {String} [extension]
69413 * @return {p5.PrintWriter}
69414 * @example
69415 * <div>
69416 * <code>
69417 * function setup() {
69418 * createCanvas(100, 100);
69419 * background(200);
69420 * text('click here to save', 10, 10, 70, 80);
69421 * }
69422 *
69423 * function mousePressed() {
69424 * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {
69425 * const writer = createWriter('squares.txt');
69426 * for (let i = 0; i < 10; i++) {
69427 * writer.print(i * i);
69428 * }
69429 * writer.close();
69430 * writer.clear();
69431 * }
69432 * }
69433 * </code>
69434 * </div>
69435 */
69436 _main.default.prototype.createWriter = function(name, extension) {
69437 var newPW;
69438 // check that it doesn't already exist
69439 for (var i in _main.default.prototype._pWriters) {
69440 if (_main.default.prototype._pWriters[i].name === name) {
69441 // if a p5.PrintWriter w/ this name already exists...
69442 // return p5.prototype._pWriters[i]; // return it w/ contents intact.
69443 // or, could return a new, empty one with a unique name:
69444 newPW = new _main.default.PrintWriter(name + this.millis(), extension);
69445 _main.default.prototype._pWriters.push(newPW);
69446 return newPW;
69447 }
69448 }
69449 newPW = new _main.default.PrintWriter(name, extension);
69450 _main.default.prototype._pWriters.push(newPW);
69451 return newPW;
69452 };
69453
69454 /**
69455 * @class p5.PrintWriter
69456 * @param {String} filename
69457 * @param {String} [extension]
69458 */
69459 _main.default.PrintWriter = function(filename, extension) {
69460 var self = this;
69461 this.name = filename;
69462 this.content = '';
69463 //Changed to write because it was being overloaded by function below.
69464 /**
69465 * Writes data to the PrintWriter stream
69466 * @method write
69467 * @param {Array} data all data to be written by the PrintWriter
69468 * @example
69469 * <div class="norender notest">
69470 * <code>
69471 * // creates a file called 'newFile.txt'
69472 * let writer = createWriter('newFile.txt');
69473 * // write 'Hello world!'' to the file
69474 * writer.write(['Hello world!']);
69475 * // close the PrintWriter and save the file
69476 * writer.close();
69477 * </code>
69478 * </div>
69479 * <div class='norender notest'>
69480 * <code>
69481 * // creates a file called 'newFile2.txt'
69482 * let writer = createWriter('newFile2.txt');
69483 * // write 'apples,bananas,123' to the file
69484 * writer.write(['apples', 'bananas', 123]);
69485 * // close the PrintWriter and save the file
69486 * writer.close();
69487 * </code>
69488 * </div>
69489 * <div class='norender notest'>
69490 * <code>
69491 * // creates a file called 'newFile3.txt'
69492 * let writer = createWriter('newFile3.txt');
69493 * // write 'My name is: Teddy' to the file
69494 * writer.write('My name is:');
69495 * writer.write(' Teddy');
69496 * // close the PrintWriter and save the file
69497 * writer.close();
69498 * </code>
69499 * </div>
69500 * <div>
69501 * <code>
69502 * function setup() {
69503 * createCanvas(100, 100);
69504 * button = createButton('SAVE FILE');
69505 * button.position(21, 40);
69506 * button.mousePressed(createFile);
69507 * }
69508 *
69509 * function createFile() {
69510 * // creates a file called 'newFile.txt'
69511 * let writer = createWriter('newFile.txt');
69512 * // write 'Hello world!'' to the file
69513 * writer.write(['Hello world!']);
69514 * // close the PrintWriter and save the file
69515 * writer.close();
69516 * }
69517 * </code>
69518 * </div>
69519 */
69520 this.write = function(data) {
69521 this.content += data;
69522 };
69523 /**
69524 * Writes data to the PrintWriter stream, and adds a new line at the end
69525 * @method print
69526 * @param {Array} data all data to be printed by the PrintWriter
69527 * @example
69528 * <div class='norender notest'>
69529 * <code>
69530 * // creates a file called 'newFile.txt'
69531 * let writer = createWriter('newFile.txt');
69532 * // creates a file containing
69533 * // My name is:
69534 * // Teddy
69535 * writer.print('My name is:');
69536 * writer.print('Teddy');
69537 * // close the PrintWriter and save the file
69538 * writer.close();
69539 * </code>
69540 * </div>
69541 * <div class='norender notest'>
69542 * <code>
69543 * let writer;
69544 *
69545 * function setup() {
69546 * createCanvas(400, 400);
69547 * // create a PrintWriter
69548 * writer = createWriter('newFile.txt');
69549 * }
69550 *
69551 * function draw() {
69552 * writer.print([mouseX, mouseY]);
69553 * }
69554 *
69555 * function mouseClicked() {
69556 * writer.close();
69557 * }
69558 * </code>
69559 * </div>
69560 */
69561 this.print = function(data) {
69562 this.content += ''.concat(data, '\n');
69563 };
69564 /**
69565 * Clears the data already written to the PrintWriter object
69566 * @method clear
69567 * @example
69568 * <div class ="norender notest"><code>
69569 * // create writer object
69570 * let writer = createWriter('newFile.txt');
69571 * writer.write(['clear me']);
69572 * // clear writer object here
69573 * writer.clear();
69574 * // close writer
69575 * writer.close();
69576 * </code></div>
69577 * <div>
69578 * <code>
69579 * function setup() {
69580 * button = createButton('CLEAR ME');
69581 * button.position(21, 40);
69582 * button.mousePressed(createFile);
69583 * }
69584 *
69585 * function createFile() {
69586 * let writer = createWriter('newFile.txt');
69587 * writer.write(['clear me']);
69588 * writer.clear();
69589 * writer.close();
69590 * }
69591 * </code>
69592 * </div>
69593 *
69594 */
69595 this.clear = function() {
69596 this.content = '';
69597 };
69598 /**
69599 * Closes the PrintWriter
69600 * @method close
69601 * @example
69602 * <div class="norender notest">
69603 * <code>
69604 * // create a file called 'newFile.txt'
69605 * let writer = createWriter('newFile.txt');
69606 * // close the PrintWriter and save the file
69607 * writer.close();
69608 * </code>
69609 * </div>
69610 * <div class='norender notest'>
69611 * <code>
69612 * // create a file called 'newFile2.txt'
69613 * let writer = createWriter('newFile2.txt');
69614 * // write some data to the file
69615 * writer.write([100, 101, 102]);
69616 * // close the PrintWriter and save the file
69617 * writer.close();
69618 * </code>
69619 * </div>
69620 */
69621 this.close = function() {
69622 // convert String to Array for the writeFile Blob
69623 var arr = [];
69624 arr.push(this.content);
69625 _main.default.prototype.writeFile(arr, filename, extension);
69626 // remove from _pWriters array and delete self
69627 for (var i in _main.default.prototype._pWriters) {
69628 if (_main.default.prototype._pWriters[i].name === this.name) {
69629 // remove from _pWriters array
69630 _main.default.prototype._pWriters.splice(i, 1);
69631 }
69632 }
69633 self.clear();
69634 self = {};
69635 };
69636 };
69637
69638 /**
69639 * @module IO
69640 * @submodule Output
69641 * @for p5
69642 */
69643
69644 // object, filename, options --> saveJSON, saveStrings,
69645 // filename, [extension] [canvas] --> saveImage
69646
69647 /**
69648 * Saves a given element(image, text, json, csv, wav, or html) to the client's
69649 * computer. The first parameter can be a pointer to element we want to save.
69650 * The element can be one of <a href="#/p5.Element">p5.Element</a>,an Array of
69651 * Strings, an Array of JSON, a JSON object, a <a href="#/p5.Table">p5.Table
69652 * </a>, a <a href="#/p5.Image">p5.Image</a>, or a p5.SoundFile (requires
69653 * p5.sound). The second parameter is a filename (including extension).The
69654 * third parameter is for options specific to this type of object. This method
69655 * will save a file that fits the given parameters.
69656 * If it is called without specifying an element, by default it will save the
69657 * whole canvas as an image file. You can optionally specify a filename as
69658 * the first parameter in such a case.
69659 * **Note that it is not recommended to
69660 * call this method within draw, as it will open a new save dialog on every
69661 * render.**
69662 *
69663 * @method save
69664 * @param {Object|String} [objectOrFilename] If filename is provided, will
69665 * save canvas as an image with
69666 * either png or jpg extension
69667 * depending on the filename.
69668 * If object is provided, will
69669 * save depending on the object
69670 * and filename (see examples
69671 * above).
69672 * @param {String} [filename] If an object is provided as the first
69673 * parameter, then the second parameter
69674 * indicates the filename,
69675 * and should include an appropriate
69676 * file extension (see examples above).
69677 * @param {Boolean|String} [options] Additional options depend on
69678 * filetype. For example, when saving JSON,
69679 * <code>true</code> indicates that the
69680 * output will be optimized for filesize,
69681 * rather than readability.
69682 *
69683 * @example
69684 * <div class="norender"><code>
69685 * // Saves the canvas as an image
69686 * cnv = createCanvas(300, 300);
69687 * save(cnv, 'myCanvas.jpg');
69688 *
69689 * // Saves the canvas as an image by default
69690 * save('myCanvas.jpg');
69691 * </code></div>
69692 *
69693 * <div class="norender"><code>
69694 * // Saves p5.Image as an image
69695 * img = createImage(10, 10);
69696 * save(img, 'myImage.png');
69697 * </code></div>
69698 *
69699 * <div class="norender"><code>
69700 * // Saves p5.Renderer object as an image
69701 * obj = createGraphics(100, 100);
69702 * save(obj, 'myObject.png');
69703 * </code></div>
69704 *
69705 * <div class="norender"><code>
69706 * let myTable = new p5.Table();
69707 * // Saves table as html file
69708 * save(myTable, 'myTable.html');
69709 *
69710 * // Comma Separated Values
69711 * save(myTable, 'myTable.csv');
69712 *
69713 * // Tab Separated Values
69714 * save(myTable, 'myTable.tsv');
69715 * </code></div>
69716 *
69717 * <div class="norender"><code>
69718 * let myJSON = { a: 1, b: true };
69719 *
69720 * // Saves pretty JSON
69721 * save(myJSON, 'my.json');
69722 *
69723 * // Optimizes JSON filesize
69724 * save(myJSON, 'my.json', true);
69725 * </code></div>
69726 *
69727 * <div class="norender"><code>
69728 * // Saves array of strings to text file with line breaks after each item
69729 * let arrayOfStrings = ['a', 'b'];
69730 * save(arrayOfStrings, 'my.txt');
69731 * </code></div>
69732 *
69733 * @alt
69734 * An example for saving a canvas as an image.
69735 * An example for saving a p5.Image element as an image.
69736 * An example for saving a p5.Renderer element.
69737 * An example showing how to save a table in formats of HTML, CSV and TSV.
69738 * An example for saving JSON to a txt file with some extra arguments.
69739 * An example for saving an array of strings to text file with line breaks.
69740 */
69741
69742 _main.default.prototype.save = function(object, _filename, _options) {
69743 // parse the arguments and figure out which things we are saving
69744 var args = arguments;
69745 // =================================================
69746 // OPTION 1: saveCanvas...
69747
69748 // if no arguments are provided, save canvas
69749 var cnv = this._curElement ? this._curElement.elt : this.elt;
69750 if (args.length === 0) {
69751 _main.default.prototype.saveCanvas(cnv);
69752 return;
69753 } else if (
69754 args[0] instanceof _main.default.Renderer ||
69755 args[0] instanceof _main.default.Graphics
69756 ) {
69757 // otherwise, parse the arguments
69758
69759 // if first param is a p5Graphics, then saveCanvas
69760 _main.default.prototype.saveCanvas(args[0].elt, args[1], args[2]);
69761 return;
69762 } else if (args.length === 1 && typeof args[0] === 'string') {
69763 // if 1st param is String and only one arg, assume it is canvas filename
69764 _main.default.prototype.saveCanvas(cnv, args[0]);
69765 } else {
69766 // =================================================
69767 // OPTION 2: extension clarifies saveStrings vs. saveJSON
69768 var extension = _checkFileExtension(args[1], args[2])[1];
69769 switch (extension) {
69770 case 'json':
69771 _main.default.prototype.saveJSON(args[0], args[1], args[2]);
69772 return;
69773 case 'txt':
69774 _main.default.prototype.saveStrings(args[0], args[1], args[2]);
69775 return;
69776 // =================================================
69777 // OPTION 3: decide based on object...
69778 default:
69779 if (args[0] instanceof Array) {
69780 _main.default.prototype.saveStrings(args[0], args[1], args[2]);
69781 } else if (args[0] instanceof _main.default.Table) {
69782 _main.default.prototype.saveTable(args[0], args[1], args[2]);
69783 } else if (args[0] instanceof _main.default.Image) {
69784 _main.default.prototype.saveCanvas(args[0].canvas, args[1]);
69785 } else if (args[0] instanceof _main.default.SoundFile) {
69786 _main.default.prototype.saveSound(args[0], args[1], args[2], args[3]);
69787 }
69788 }
69789 }
69790 };
69791
69792 /**
69793 * Writes the contents of an Array or a JSON object to a .json file.
69794 * The file saving process and location of the saved file will
69795 * vary between web browsers.
69796 *
69797 * @method saveJSON
69798 * @param {Array|Object} json
69799 * @param {String} filename
69800 * @param {Boolean} [optimize] If true, removes line breaks
69801 * and spaces from the output
69802 * file to optimize filesize
69803 * (but not readability).
69804 * @example
69805 * <div><code>
69806 * let json = {}; // new JSON Object
69807 *
69808 * json.id = 0;
69809 * json.species = 'Panthera leo';
69810 * json.name = 'Lion';
69811 *
69812 * function setup() {
69813 * createCanvas(100, 100);
69814 * background(200);
69815 * text('click here to save', 10, 10, 70, 80);
69816 * }
69817 *
69818 * function mousePressed() {
69819 * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {
69820 * saveJSON(json, 'lion.json');
69821 * }
69822 * }
69823 *
69824 * // saves the following to a file called "lion.json":
69825 * // {
69826 * // "id": 0,
69827 * // "species": "Panthera leo",
69828 * // "name": "Lion"
69829 * // }
69830 * </code></div>
69831 *
69832 * @alt
69833 * no image displayed
69834 */
69835 _main.default.prototype.saveJSON = function(json, filename, opt) {
69836 _main.default._validateParameters('saveJSON', arguments);
69837 var stringify;
69838 if (opt) {
69839 stringify = JSON.stringify(json);
69840 } else {
69841 stringify = JSON.stringify(json, undefined, 2);
69842 }
69843 this.saveStrings(stringify.split('\n'), filename, 'json');
69844 };
69845
69846 _main.default.prototype.saveJSONObject = _main.default.prototype.saveJSON;
69847 _main.default.prototype.saveJSONArray = _main.default.prototype.saveJSON;
69848
69849 /**
69850 * Writes an array of Strings to a text file, one line per String.
69851 * The file saving process and location of the saved file will
69852 * vary between web browsers.
69853 *
69854 * @method saveStrings
69855 * @param {String[]} list string array to be written
69856 * @param {String} filename filename for output
69857 * @param {String} [extension] the filename's extension
69858 * @param {Boolean} [isCRLF] if true, change line-break to CRLF
69859 * @example
69860 * <div><code>
69861 * let words = 'apple bear cat dog';
69862 *
69863 * // .split() outputs an Array
69864 * let list = split(words, ' ');
69865 *
69866 * function setup() {
69867 * createCanvas(100, 100);
69868 * background(200);
69869 * text('click here to save', 10, 10, 70, 80);
69870 * }
69871 *
69872 * function mousePressed() {
69873 * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {
69874 * saveStrings(list, 'nouns.txt');
69875 * }
69876 * }
69877 *
69878 * // Saves the following to a file called 'nouns.txt':
69879 * //
69880 * // apple
69881 * // bear
69882 * // cat
69883 * // dog
69884 * </code></div>
69885 *
69886 * @alt
69887 * no image displayed
69888 */
69889 _main.default.prototype.saveStrings = function(
69890 list,
69891 filename,
69892 extension,
69893 isCRLF
69894 ) {
69895 _main.default._validateParameters('saveStrings', arguments);
69896 var ext = extension || 'txt';
69897 var pWriter = this.createWriter(filename, ext);
69898 for (var i = 0; i < list.length; i++) {
69899 isCRLF ? pWriter.write(list[i] + '\r\n') : pWriter.write(list[i] + '\n');
69900 }
69901 pWriter.close();
69902 pWriter.clear();
69903 };
69904
69905 // =======
69906 // HELPERS
69907 // =======
69908
69909 function escapeHelper(content) {
69910 return content
69911 .replace(/&/g, '&amp;')
69912 .replace(/</g, '&lt;')
69913 .replace(/>/g, '&gt;')
69914 .replace(/"/g, '&quot;')
69915 .replace(/'/g, '&#039;');
69916 }
69917
69918 /**
69919 * Writes the contents of a <a href="#/p5.Table">Table</a> object to a file. Defaults to a
69920 * text file with comma-separated-values ('csv') but can also
69921 * use tab separation ('tsv'), or generate an HTML table ('html').
69922 * The file saving process and location of the saved file will
69923 * vary between web browsers.
69924 *
69925 * @method saveTable
69926 * @param {p5.Table} Table the <a href="#/p5.Table">Table</a> object to save to a file
69927 * @param {String} filename the filename to which the Table should be saved
69928 * @param {String} [options] can be one of "tsv", "csv", or "html"
69929 * @example
69930 * <div><code>
69931 * let table;
69932 *
69933 * function setup() {
69934 * table = new p5.Table();
69935 *
69936 * table.addColumn('id');
69937 * table.addColumn('species');
69938 * table.addColumn('name');
69939 *
69940 * let newRow = table.addRow();
69941 * newRow.setNum('id', table.getRowCount() - 1);
69942 * newRow.setString('species', 'Panthera leo');
69943 * newRow.setString('name', 'Lion');
69944 *
69945 * // To save, un-comment next line then click 'run'
69946 * // saveTable(table, 'new.csv');
69947 * }
69948 *
69949 * // Saves the following to a file called 'new.csv':
69950 * // id,species,name
69951 * // 0,Panthera leo,Lion
69952 * </code></div>
69953 *
69954 * @alt
69955 * no image displayed
69956 */
69957 _main.default.prototype.saveTable = function(table, filename, options) {
69958 _main.default._validateParameters('saveTable', arguments);
69959 var ext;
69960 if (options === undefined) {
69961 ext = filename.substring(filename.lastIndexOf('.') + 1, filename.length);
69962 } else {
69963 ext = options;
69964 }
69965 var pWriter = this.createWriter(filename, ext);
69966
69967 var header = table.columns;
69968
69969 var sep = ','; // default to CSV
69970 if (ext === 'tsv') {
69971 sep = '\t';
69972 }
69973 if (ext !== 'html') {
69974 // make header if it has values
69975 if (header[0] !== '0') {
69976 for (var h = 0; h < header.length; h++) {
69977 if (h < header.length - 1) {
69978 pWriter.write(header[h] + sep);
69979 } else {
69980 pWriter.write(header[h]);
69981 }
69982 }
69983 pWriter.write('\n');
69984 }
69985
69986 // make rows
69987 for (var i = 0; i < table.rows.length; i++) {
69988 var j = void 0;
69989 for (j = 0; j < table.rows[i].arr.length; j++) {
69990 if (j < table.rows[i].arr.length - 1) {
69991 pWriter.write(table.rows[i].arr[j] + sep);
69992 } else if (i < table.rows.length - 1) {
69993 pWriter.write(table.rows[i].arr[j]);
69994 } else {
69995 pWriter.write(table.rows[i].arr[j]);
69996 }
69997 }
69998 pWriter.write('\n');
69999 }
70000 } else {
70001 // otherwise, make HTML
70002 pWriter.print('<html>');
70003 pWriter.print('<head>');
70004 var str = ' <meta http-equiv="content-type" content';
70005 str += '="text/html;charset=utf-8" />';
70006 pWriter.print(str);
70007 pWriter.print('</head>');
70008
70009 pWriter.print('<body>');
70010 pWriter.print(' <table>');
70011
70012 // make header if it has values
70013 if (header[0] !== '0') {
70014 pWriter.print(' <tr>');
70015 for (var k = 0; k < header.length; k++) {
70016 var e = escapeHelper(header[k]);
70017 pWriter.print(' <td>'.concat(e));
70018 pWriter.print(' </td>');
70019 }
70020 pWriter.print(' </tr>');
70021 }
70022
70023 // make rows
70024 for (var row = 0; row < table.rows.length; row++) {
70025 pWriter.print(' <tr>');
70026 for (var col = 0; col < table.columns.length; col++) {
70027 var entry = table.rows[row].getString(col);
70028 var htmlEntry = escapeHelper(entry);
70029 pWriter.print(' <td>'.concat(htmlEntry));
70030 pWriter.print(' </td>');
70031 }
70032 pWriter.print(' </tr>');
70033 }
70034 pWriter.print(' </table>');
70035 pWriter.print('</body>');
70036 pWriter.print('</html>');
70037 }
70038 // close and clear the pWriter
70039 pWriter.close();
70040 pWriter.clear();
70041 }; // end saveTable()
70042
70043 /**
70044 * Generate a blob of file data as a url to prepare for download.
70045 * Accepts an array of data, a filename, and an extension (optional).
70046 * This is a private function because it does not do any formatting,
70047 * but it is used by <a href="#/p5/saveStrings">saveStrings</a>, <a href="#/p5/saveJSON">saveJSON</a>, <a href="#/p5/saveTable">saveTable</a> etc.
70048 *
70049 * @param {Array} dataToDownload
70050 * @param {String} filename
70051 * @param {String} [extension]
70052 * @private
70053 */
70054 _main.default.prototype.writeFile = function(
70055 dataToDownload,
70056 filename,
70057 extension
70058 ) {
70059 var type = 'application/octet-stream';
70060 if (_main.default.prototype._isSafari()) {
70061 type = 'text/plain';
70062 }
70063 var blob = new Blob(dataToDownload, {
70064 type: type
70065 });
70066
70067 _main.default.prototype.downloadFile(blob, filename, extension);
70068 };
70069
70070 /**
70071 * Forces download. Accepts a url to filedata/blob, a filename,
70072 * and an extension (optional).
70073 * This is a private function because it does not do any formatting,
70074 * but it is used by <a href="#/p5/saveStrings">saveStrings</a>, <a href="#/p5/saveJSON">saveJSON</a>, <a href="#/p5/saveTable">saveTable</a> etc.
70075 *
70076 * @method downloadFile
70077 * @private
70078 * @param {String|Blob} data either an href generated by createObjectURL,
70079 * or a Blob object containing the data
70080 * @param {String} [filename]
70081 * @param {String} [extension]
70082 */
70083 _main.default.prototype.downloadFile = function(data, fName, extension) {
70084 var fx = _checkFileExtension(fName, extension);
70085 var filename = fx[0];
70086
70087 if (data instanceof Blob) {
70088 _fileSaver.default.saveAs(data, filename);
70089 return;
70090 }
70091
70092 var a = document.createElement('a');
70093 a.href = data;
70094 a.download = filename;
70095
70096 // Firefox requires the link to be added to the DOM before click()
70097 a.onclick = function(e) {
70098 destroyClickedElement(e);
70099 e.stopPropagation();
70100 };
70101
70102 a.style.display = 'none';
70103 document.body.appendChild(a);
70104
70105 // Safari will open this file in the same page as a confusing Blob.
70106 if (_main.default.prototype._isSafari()) {
70107 var aText = 'Hello, Safari user! To download this file...\n';
70108 aText += '1. Go to File --> Save As.\n';
70109 aText += '2. Choose "Page Source" as the Format.\n';
70110 aText += '3. Name it with this extension: ."'.concat(fx[1], '"');
70111 alert(aText);
70112 }
70113 a.click();
70114 };
70115
70116 /**
70117 * Returns a file extension, or another string
70118 * if the provided parameter has no extension.
70119 *
70120 * @param {String} filename
70121 * @param {String} [extension]
70122 * @return {String[]} [fileName, fileExtension]
70123 *
70124 * @private
70125 */
70126 function _checkFileExtension(filename, extension) {
70127 if (!extension || extension === true || extension === 'true') {
70128 extension = '';
70129 }
70130 if (!filename) {
70131 filename = 'untitled';
70132 }
70133 var ext = '';
70134 // make sure the file will have a name, see if filename needs extension
70135 if (filename && filename.includes('.')) {
70136 ext = filename.split('.').pop();
70137 }
70138 // append extension if it doesn't exist
70139 if (extension) {
70140 if (ext !== extension) {
70141 ext = extension;
70142 filename = ''.concat(filename, '.').concat(ext);
70143 }
70144 }
70145 return [filename, ext];
70146 }
70147 _main.default.prototype._checkFileExtension = _checkFileExtension;
70148
70149 /**
70150 * Returns true if the browser is Safari, false if not.
70151 * Safari makes trouble for downloading files.
70152 *
70153 * @return {Boolean} [description]
70154 * @private
70155 */
70156 _main.default.prototype._isSafari = function() {
70157 var x = Object.prototype.toString.call(window.HTMLElement);
70158 return x.indexOf('Constructor') > 0;
70159 };
70160
70161 /**
70162 * Helper function, a callback for download that deletes
70163 * an invisible anchor element from the DOM once the file
70164 * has been automatically downloaded.
70165 *
70166 * @private
70167 */
70168 function destroyClickedElement(event) {
70169 document.body.removeChild(event.target);
70170 }
70171 var _default = _main.default;
70172 exports.default = _default;
70173 },
70174 {
70175 '../core/friendly_errors/fes_core': 46,
70176 '../core/friendly_errors/file_errors': 47,
70177 '../core/friendly_errors/validate_params': 49,
70178 '../core/main': 54,
70179 'es6-promise/auto': 23,
70180 'fetch-jsonp': 25,
70181 'file-saver': 26,
70182 'whatwg-fetch': 37
70183 }
70184 ],
70185 81: [
70186 function(_dereq_, module, exports) {
70187 'use strict';
70188 Object.defineProperty(exports, '__esModule', { value: true });
70189 exports.default = void 0;
70190
70191 var _main = _interopRequireDefault(_dereq_('../core/main'));
70192 function _interopRequireDefault(obj) {
70193 return obj && obj.__esModule ? obj : { default: obj };
70194 } /**
70195 * <a href="#/p5.Table">Table</a> objects store data with multiple rows and columns, much
70196 * like in a traditional spreadsheet. Tables can be generated from
70197 * scratch, dynamically, or using data from an existing file.
70198 *
70199 * @class p5.Table
70200 * @constructor
70201 * @param {p5.TableRow[]} [rows] An array of p5.TableRow objects
70202 */ /**
70203 * @module IO
70204 * @submodule Table
70205 * @requires core
70206 */ /**
70207 * Table Options
70208 * Generic class for handling tabular data, typically from a
70209 * CSV, TSV, or other sort of spreadsheet file.
70210 * CSV files are
70211 * <a href="http://en.wikipedia.org/wiki/Comma-separated_values">
70212 * comma separated values</a>, often with the data in quotes. TSV
70213 * files use tabs as separators, and usually don't bother with the
70214 * quotes.
70215 * File names should end with .csv if they're comma separated.
70216 * A rough "spec" for CSV can be found
70217 * <a href="http://tools.ietf.org/html/rfc4180">here</a>.
70218 * To load files, use the <a href="#/p5/loadTable">loadTable</a> method.
70219 * To save tables to your computer, use the <a href="#/p5/save">save</a> method
70220 * or the <a href="#/p5/saveTable">saveTable</a> method.
70221 *
70222 * Possible options include:
70223 * <ul>
70224 * <li>csv - parse the table as comma-separated values
70225 * <li>tsv - parse the table as tab-separated values
70226 * <li>header - this table has a header (title) row
70227 * </ul>
70228 */
70229 _main.default.Table = function(rows) {
70230 /**
70231 * An array containing the names of the columns in the table, if the "header" the table is
70232 * loaded with the "header" parameter.
70233 * @property columns {String[]}
70234 * @example
70235 * <div class="norender">
70236 * <code>
70237 * // Given the CSV file "mammals.csv"
70238 * // in the project's "assets" folder:
70239 * //
70240 * // id,species,name
70241 * // 0,Capra hircus,Goat
70242 * // 1,Panthera pardus,Leopard
70243 * // 2,Equus zebra,Zebra
70244 *
70245 * let table;
70246 *
70247 * function preload() {
70248 * //my table is comma separated value "csv"
70249 * //and has a header specifying the columns labels
70250 * table = loadTable('assets/mammals.csv', 'csv', 'header');
70251 * }
70252 *
70253 * function setup() {
70254 * //print the column names
70255 * for (let c = 0; c < table.getColumnCount(); c++) {
70256 * print('column ' + c + ' is named ' + table.columns[c]);
70257 * }
70258 * }
70259 * </code>
70260 * </div>
70261 */
70262 this.columns = [];
70263
70264 /**
70265 * An array containing the <a href="#/p5.Table">p5.TableRow</a> objects that make up the
70266 * rows of the table. The same result as calling <a href="#/p5/getRows">getRows()</a>
70267 * @property rows {p5.TableRow[]}
70268 */
70269 this.rows = [];
70270 };
70271
70272 /**
70273 * Use <a href="#/p5/addRow">addRow()</a> to add a new row of data to a <a href="#/p5.Table">p5.Table</a> object. By default,
70274 * an empty row is created. Typically, you would store a reference to
70275 * the new row in a TableRow object (see newRow in the example above),
70276 * and then set individual values using <a href="#/p5/set">set()</a>.
70277 *
70278 * If a <a href="#/p5.TableRow">p5.TableRow</a> object is included as a parameter, then that row is
70279 * duplicated and added to the table.
70280 *
70281 * @method addRow
70282 * @param {p5.TableRow} [row] row to be added to the table
70283 * @return {p5.TableRow} the row that was added
70284 *
70285 * @example
70286 * <div class="norender">
70287 * <code>
70288 * // Given the CSV file "mammals.csv"
70289 * // in the project's "assets" folder:
70290 * //
70291 * // id,species,name
70292 * // 0,Capra hircus,Goat
70293 * // 1,Panthera pardus,Leopard
70294 * // 2,Equus zebra,Zebra
70295 *
70296 * let table;
70297 *
70298 * function preload() {
70299 * //my table is comma separated value "csv"
70300 * //and has a header specifying the columns labels
70301 * table = loadTable('assets/mammals.csv', 'csv', 'header');
70302 * }
70303 *
70304 * function setup() {
70305 * //add a row
70306 * let newRow = table.addRow();
70307 * newRow.setString('id', table.getRowCount() - 1);
70308 * newRow.setString('species', 'Canis Lupus');
70309 * newRow.setString('name', 'Wolf');
70310 *
70311 * //print the results
70312 * for (let r = 0; r < table.getRowCount(); r++)
70313 * for (let c = 0; c < table.getColumnCount(); c++)
70314 * print(table.getString(r, c));
70315 * }
70316 * </code>
70317 * </div>
70318 *
70319 * @alt
70320 * no image displayed
70321 */
70322 _main.default.Table.prototype.addRow = function(row) {
70323 // make sure it is a valid TableRow
70324 var r = row || new _main.default.TableRow();
70325
70326 if (typeof r.arr === 'undefined' || typeof r.obj === 'undefined') {
70327 //r = new p5.prototype.TableRow(r);
70328 throw new Error('invalid TableRow: '.concat(r));
70329 }
70330 r.table = this;
70331 this.rows.push(r);
70332 return r;
70333 };
70334
70335 /**
70336 * Removes a row from the table object.
70337 *
70338 * @method removeRow
70339 * @param {Integer} id ID number of the row to remove
70340 *
70341 * @example
70342 * <div class="norender">
70343 * <code>
70344 * // Given the CSV file "mammals.csv"
70345 * // in the project's "assets" folder:
70346 * //
70347 * // id,species,name
70348 * // 0,Capra hircus,Goat
70349 * // 1,Panthera pardus,Leopard
70350 * // 2,Equus zebra,Zebra
70351 *
70352 * let table;
70353 *
70354 * function preload() {
70355 * //my table is comma separated value "csv"
70356 * //and has a header specifying the columns labels
70357 * table = loadTable('assets/mammals.csv', 'csv', 'header');
70358 * }
70359 *
70360 * function setup() {
70361 * //remove the first row
70362 * table.removeRow(0);
70363 *
70364 * //print the results
70365 * for (let r = 0; r < table.getRowCount(); r++)
70366 * for (let c = 0; c < table.getColumnCount(); c++)
70367 * print(table.getString(r, c));
70368 * }
70369 * </code>
70370 * </div>
70371 *
70372 * @alt
70373 * no image displayed
70374 */
70375 _main.default.Table.prototype.removeRow = function(id) {
70376 this.rows[id].table = null; // remove reference to table
70377 var chunk = this.rows.splice(id + 1, this.rows.length);
70378 this.rows.pop();
70379 this.rows = this.rows.concat(chunk);
70380 };
70381
70382 /**
70383 * Returns a reference to the specified <a href="#/p5.TableRow">p5.TableRow</a>. The reference
70384 * can then be used to get and set values of the selected row.
70385 *
70386 * @method getRow
70387 * @param {Integer} rowID ID number of the row to get
70388 * @return {p5.TableRow} <a href="#/p5.TableRow">p5.TableRow</a> object
70389 *
70390 * @example
70391 * <div class="norender">
70392 * <code>
70393 * // Given the CSV file "mammals.csv"
70394 * // in the project's "assets" folder:
70395 * //
70396 * // id,species,name
70397 * // 0,Capra hircus,Goat
70398 * // 1,Panthera pardus,Leopard
70399 * // 2,Equus zebra,Zebra
70400 *
70401 * let table;
70402 *
70403 * function preload() {
70404 * //my table is comma separated value "csv"
70405 * //and has a header specifying the columns labels
70406 * table = loadTable('assets/mammals.csv', 'csv', 'header');
70407 * }
70408 *
70409 * function setup() {
70410 * let row = table.getRow(1);
70411 * //print it column by column
70412 * //note: a row is an object, not an array
70413 * for (let c = 0; c < table.getColumnCount(); c++) {
70414 * print(row.getString(c));
70415 * }
70416 * }
70417 * </code>
70418 * </div>
70419 *
70420 *@alt
70421 * no image displayed
70422 */
70423 _main.default.Table.prototype.getRow = function(r) {
70424 return this.rows[r];
70425 };
70426
70427 /**
70428 * Gets all rows from the table. Returns an array of <a href="#/p5.TableRow">p5.TableRow</a>s.
70429 *
70430 * @method getRows
70431 * @return {p5.TableRow[]} Array of <a href="#/p5.TableRow">p5.TableRow</a>s
70432 *
70433 * @example
70434 * <div class="norender">
70435 * <code>
70436 * // Given the CSV file "mammals.csv"
70437 * // in the project's "assets" folder:
70438 * //
70439 * // id,species,name
70440 * // 0,Capra hircus,Goat
70441 * // 1,Panthera pardus,Leopard
70442 * // 2,Equus zebra,Zebra
70443 *
70444 * let table;
70445 *
70446 * function preload() {
70447 * //my table is comma separated value "csv"
70448 * //and has a header specifying the columns labels
70449 * table = loadTable('assets/mammals.csv', 'csv', 'header');
70450 * }
70451 *
70452 * function setup() {
70453 * let rows = table.getRows();
70454 *
70455 * //warning: rows is an array of objects
70456 * for (let r = 0; r < rows.length; r++) {
70457 * rows[r].set('name', 'Unicorn');
70458 * }
70459 *
70460 * //print the results
70461 * for (let r = 0; r < table.getRowCount(); r++)
70462 * for (let c = 0; c < table.getColumnCount(); c++)
70463 * print(table.getString(r, c));
70464 * }
70465 * </code>
70466 * </div>
70467 *
70468 * @alt
70469 * no image displayed
70470 */
70471 _main.default.Table.prototype.getRows = function() {
70472 return this.rows;
70473 };
70474
70475 /**
70476 * Finds the first row in the Table that contains the value
70477 * provided, and returns a reference to that row. Even if
70478 * multiple rows are possible matches, only the first matching
70479 * row is returned. The column to search may be specified by
70480 * either its ID or title.
70481 *
70482 * @method findRow
70483 * @param {String} value The value to match
70484 * @param {Integer|String} column ID number or title of the
70485 * column to search
70486 * @return {p5.TableRow}
70487 *
70488 * @example
70489 * <div class="norender">
70490 * <code>
70491 * // Given the CSV file "mammals.csv"
70492 * // in the project's "assets" folder:
70493 * //
70494 * // id,species,name
70495 * // 0,Capra hircus,Goat
70496 * // 1,Panthera pardus,Leopard
70497 * // 2,Equus zebra,Zebra
70498 *
70499 * let table;
70500 *
70501 * function preload() {
70502 * //my table is comma separated value "csv"
70503 * //and has a header specifying the columns labels
70504 * table = loadTable('assets/mammals.csv', 'csv', 'header');
70505 * }
70506 *
70507 * function setup() {
70508 * //find the animal named zebra
70509 * let row = table.findRow('Zebra', 'name');
70510 * //find the corresponding species
70511 * print(row.getString('species'));
70512 * }
70513 * </code>
70514 * </div>
70515 *
70516 * @alt
70517 * no image displayed
70518 */
70519 _main.default.Table.prototype.findRow = function(value, column) {
70520 // try the Object
70521 if (typeof column === 'string') {
70522 for (var i = 0; i < this.rows.length; i++) {
70523 if (this.rows[i].obj[column] === value) {
70524 return this.rows[i];
70525 }
70526 }
70527 } else {
70528 // try the Array
70529 for (var j = 0; j < this.rows.length; j++) {
70530 if (this.rows[j].arr[column] === value) {
70531 return this.rows[j];
70532 }
70533 }
70534 }
70535 // otherwise...
70536 return null;
70537 };
70538
70539 /**
70540 * Finds the rows in the Table that contain the value
70541 * provided, and returns references to those rows. Returns an
70542 * Array, so for must be used to iterate through all the rows,
70543 * as shown in the example above. The column to search may be
70544 * specified by either its ID or title.
70545 *
70546 * @method findRows
70547 * @param {String} value The value to match
70548 * @param {Integer|String} column ID number or title of the
70549 * column to search
70550 * @return {p5.TableRow[]} An Array of TableRow objects
70551 *
70552 * @example
70553 * <div class="norender">
70554 * <code>
70555 * // Given the CSV file "mammals.csv"
70556 * // in the project's "assets" folder:
70557 * //
70558 * // id,species,name
70559 * // 0,Capra hircus,Goat
70560 * // 1,Panthera pardus,Leopard
70561 * // 2,Equus zebra,Zebra
70562 *
70563 * let table;
70564 *
70565 * function preload() {
70566 * //my table is comma separated value "csv"
70567 * //and has a header specifying the columns labels
70568 * table = loadTable('assets/mammals.csv', 'csv', 'header');
70569 * }
70570 *
70571 * function setup() {
70572 * //add another goat
70573 * let newRow = table.addRow();
70574 * newRow.setString('id', table.getRowCount() - 1);
70575 * newRow.setString('species', 'Scape Goat');
70576 * newRow.setString('name', 'Goat');
70577 *
70578 * //find the rows containing animals named Goat
70579 * let rows = table.findRows('Goat', 'name');
70580 * print(rows.length + ' Goats found');
70581 * }
70582 * </code>
70583 * </div>
70584 *
70585 *@alt
70586 * no image displayed
70587 */
70588 _main.default.Table.prototype.findRows = function(value, column) {
70589 var ret = [];
70590 if (typeof column === 'string') {
70591 for (var i = 0; i < this.rows.length; i++) {
70592 if (this.rows[i].obj[column] === value) {
70593 ret.push(this.rows[i]);
70594 }
70595 }
70596 } else {
70597 // try the Array
70598 for (var j = 0; j < this.rows.length; j++) {
70599 if (this.rows[j].arr[column] === value) {
70600 ret.push(this.rows[j]);
70601 }
70602 }
70603 }
70604 return ret;
70605 };
70606
70607 /**
70608 * Finds the first row in the Table that matches the regular
70609 * expression provided, and returns a reference to that row.
70610 * Even if multiple rows are possible matches, only the first
70611 * matching row is returned. The column to search may be
70612 * specified by either its ID or title.
70613 *
70614 * @method matchRow
70615 * @param {String|RegExp} regexp The regular expression to match
70616 * @param {String|Integer} column The column ID (number) or
70617 * title (string)
70618 * @return {p5.TableRow} TableRow object
70619 *
70620 * @example
70621 * <div class="norender">
70622 * <code>
70623 * // Given the CSV file "mammals.csv"
70624 * // in the project's "assets" folder:
70625 * //
70626 * // id,species,name
70627 * // 0,Capra hircus,Goat
70628 * // 1,Panthera pardus,Leopard
70629 * // 2,Equus zebra,Zebra
70630 *
70631 * let table;
70632 *
70633 * function preload() {
70634 * //my table is comma separated value "csv"
70635 * //and has a header specifying the columns labels
70636 * table = loadTable('assets/mammals.csv', 'csv', 'header');
70637 * }
70638 *
70639 * function setup() {
70640 * //Search using specified regex on a given column, return TableRow object
70641 * let mammal = table.matchRow(new RegExp('ant'), 1);
70642 * print(mammal.getString(1));
70643 * //Output "Panthera pardus"
70644 * }
70645 * </code>
70646 * </div>
70647 */
70648 _main.default.Table.prototype.matchRow = function(regexp, column) {
70649 if (typeof column === 'number') {
70650 for (var j = 0; j < this.rows.length; j++) {
70651 if (this.rows[j].arr[column].match(regexp)) {
70652 return this.rows[j];
70653 }
70654 }
70655 } else {
70656 for (var i = 0; i < this.rows.length; i++) {
70657 if (this.rows[i].obj[column].match(regexp)) {
70658 return this.rows[i];
70659 }
70660 }
70661 }
70662 return null;
70663 };
70664
70665 /**
70666 * Finds the rows in the Table that match the regular expression provided,
70667 * and returns references to those rows. Returns an array, so for must be
70668 * used to iterate through all the rows, as shown in the example. The
70669 * column to search may be specified by either its ID or title.
70670 *
70671 * @method matchRows
70672 * @param {String} regexp The regular expression to match
70673 * @param {String|Integer} [column] The column ID (number) or
70674 * title (string)
70675 * @return {p5.TableRow[]} An Array of TableRow objects
70676 * @example
70677 * <div class="norender">
70678 * <code>
70679 * let table;
70680 *
70681 * function setup() {
70682 * table = new p5.Table();
70683 *
70684 * table.addColumn('name');
70685 * table.addColumn('type');
70686 *
70687 * let newRow = table.addRow();
70688 * newRow.setString('name', 'Lion');
70689 * newRow.setString('type', 'Mammal');
70690 *
70691 * newRow = table.addRow();
70692 * newRow.setString('name', 'Snake');
70693 * newRow.setString('type', 'Reptile');
70694 *
70695 * newRow = table.addRow();
70696 * newRow.setString('name', 'Mosquito');
70697 * newRow.setString('type', 'Insect');
70698 *
70699 * newRow = table.addRow();
70700 * newRow.setString('name', 'Lizard');
70701 * newRow.setString('type', 'Reptile');
70702 *
70703 * let rows = table.matchRows('R.*', 'type');
70704 * for (let i = 0; i < rows.length; i++) {
70705 * print(rows[i].getString('name') + ': ' + rows[i].getString('type'));
70706 * }
70707 * }
70708 * // Sketch prints:
70709 * // Snake: Reptile
70710 * // Lizard: Reptile
70711 * </code>
70712 * </div>
70713 */
70714 _main.default.Table.prototype.matchRows = function(regexp, column) {
70715 var ret = [];
70716 if (typeof column === 'number') {
70717 for (var j = 0; j < this.rows.length; j++) {
70718 if (this.rows[j].arr[column].match(regexp)) {
70719 ret.push(this.rows[j]);
70720 }
70721 }
70722 } else {
70723 for (var i = 0; i < this.rows.length; i++) {
70724 if (this.rows[i].obj[column].match(regexp)) {
70725 ret.push(this.rows[i]);
70726 }
70727 }
70728 }
70729 return ret;
70730 };
70731
70732 /**
70733 * Retrieves all values in the specified column, and returns them
70734 * as an array. The column may be specified by either its ID or title.
70735 *
70736 * @method getColumn
70737 * @param {String|Number} column String or Number of the column to return
70738 * @return {Array} Array of column values
70739 *
70740 * @example
70741 * <div class="norender">
70742 * <code>
70743 * // Given the CSV file "mammals.csv"
70744 * // in the project's "assets" folder:
70745 * //
70746 * // id,species,name
70747 * // 0,Capra hircus,Goat
70748 * // 1,Panthera pardus,Leopard
70749 * // 2,Equus zebra,Zebra
70750 *
70751 * let table;
70752 *
70753 * function preload() {
70754 * //my table is comma separated value "csv"
70755 * //and has a header specifying the columns labels
70756 * table = loadTable('assets/mammals.csv', 'csv', 'header');
70757 * }
70758 *
70759 * function setup() {
70760 * //getColumn returns an array that can be printed directly
70761 * print(table.getColumn('species'));
70762 * //outputs ["Capra hircus", "Panthera pardus", "Equus zebra"]
70763 * }
70764 * </code>
70765 * </div>
70766 *
70767 *@alt
70768 * no image displayed
70769 */
70770 _main.default.Table.prototype.getColumn = function(value) {
70771 var ret = [];
70772 if (typeof value === 'string') {
70773 for (var i = 0; i < this.rows.length; i++) {
70774 ret.push(this.rows[i].obj[value]);
70775 }
70776 } else {
70777 for (var j = 0; j < this.rows.length; j++) {
70778 ret.push(this.rows[j].arr[value]);
70779 }
70780 }
70781 return ret;
70782 };
70783
70784 /**
70785 * Removes all rows from a Table. While all rows are removed,
70786 * columns and column titles are maintained.
70787 *
70788 * @method clearRows
70789 *
70790 * @example
70791 * <div class="norender">
70792 * <code>
70793 * // Given the CSV file "mammals.csv"
70794 * // in the project's "assets" folder:
70795 * //
70796 * // id,species,name
70797 * // 0,Capra hircus,Goat
70798 * // 1,Panthera pardus,Leopard
70799 * // 2,Equus zebra,Zebra
70800 *
70801 * let table;
70802 *
70803 * function preload() {
70804 * //my table is comma separated value "csv"
70805 * //and has a header specifying the columns labels
70806 * table = loadTable('assets/mammals.csv', 'csv', 'header');
70807 * }
70808 *
70809 * function setup() {
70810 * table.clearRows();
70811 * print(table.getRowCount() + ' total rows in table');
70812 * print(table.getColumnCount() + ' total columns in table');
70813 * }
70814 * </code>
70815 * </div>
70816 *
70817 *@alt
70818 * no image displayed
70819 */
70820 _main.default.Table.prototype.clearRows = function() {
70821 delete this.rows;
70822 this.rows = [];
70823 };
70824
70825 /**
70826 * Use <a href="#/p5/addColumn">addColumn()</a> to add a new column to a <a href="#/p5.Table">Table</a> object.
70827 * Typically, you will want to specify a title, so the column
70828 * may be easily referenced later by name. (If no title is
70829 * specified, the new column's title will be null.)
70830 *
70831 * @method addColumn
70832 * @param {String} [title] title of the given column
70833 *
70834 * @example
70835 * <div class="norender">
70836 * <code>
70837 * // Given the CSV file "mammals.csv"
70838 * // in the project's "assets" folder:
70839 * //
70840 * // id,species,name
70841 * // 0,Capra hircus,Goat
70842 * // 1,Panthera pardus,Leopard
70843 * // 2,Equus zebra,Zebra
70844 *
70845 * let table;
70846 *
70847 * function preload() {
70848 * //my table is comma separated value "csv"
70849 * //and has a header specifying the columns labels
70850 * table = loadTable('assets/mammals.csv', 'csv', 'header');
70851 * }
70852 *
70853 * function setup() {
70854 * table.addColumn('carnivore');
70855 * table.set(0, 'carnivore', 'no');
70856 * table.set(1, 'carnivore', 'yes');
70857 * table.set(2, 'carnivore', 'no');
70858 *
70859 * //print the results
70860 * for (let r = 0; r < table.getRowCount(); r++)
70861 * for (let c = 0; c < table.getColumnCount(); c++)
70862 * print(table.getString(r, c));
70863 * }
70864 * </code>
70865 * </div>
70866 *
70867 *@alt
70868 * no image displayed
70869 */
70870 _main.default.Table.prototype.addColumn = function(title) {
70871 var t = title || null;
70872 this.columns.push(t);
70873 };
70874
70875 /**
70876 * Returns the total number of columns in a Table.
70877 *
70878 * @method getColumnCount
70879 * @return {Integer} Number of columns in this table
70880 * @example
70881 * <div>
70882 * <code>
70883 * // given the cvs file "blobs.csv" in /assets directory
70884 * // ID, Name, Flavor, Shape, Color
70885 * // Blob1, Blobby, Sweet, Blob, Pink
70886 * // Blob2, Saddy, Savory, Blob, Blue
70887 *
70888 * let table;
70889 *
70890 * function preload() {
70891 * table = loadTable('assets/blobs.csv');
70892 * }
70893 *
70894 * function setup() {
70895 * createCanvas(200, 100);
70896 * textAlign(CENTER);
70897 * background(255);
70898 * }
70899 *
70900 * function draw() {
70901 * let numOfColumn = table.getColumnCount();
70902 * text('There are ' + numOfColumn + ' columns in the table.', 100, 50);
70903 * }
70904 * </code>
70905 * </div>
70906 */
70907 _main.default.Table.prototype.getColumnCount = function() {
70908 return this.columns.length;
70909 };
70910
70911 /**
70912 * Returns the total number of rows in a Table.
70913 *
70914 * @method getRowCount
70915 * @return {Integer} Number of rows in this table
70916 * @example
70917 * <div>
70918 * <code>
70919 * // given the cvs file "blobs.csv" in /assets directory
70920 * //
70921 * // ID, Name, Flavor, Shape, Color
70922 * // Blob1, Blobby, Sweet, Blob, Pink
70923 * // Blob2, Saddy, Savory, Blob, Blue
70924 *
70925 * let table;
70926 *
70927 * function preload() {
70928 * table = loadTable('assets/blobs.csv');
70929 * }
70930 *
70931 * function setup() {
70932 * createCanvas(200, 100);
70933 * textAlign(CENTER);
70934 * background(255);
70935 * }
70936 *
70937 * function draw() {
70938 * text('There are ' + table.getRowCount() + ' rows in the table.', 100, 50);
70939 * }
70940 * </code>
70941 * </div>
70942 */
70943 _main.default.Table.prototype.getRowCount = function() {
70944 return this.rows.length;
70945 };
70946
70947 /**
70948 * Removes any of the specified characters (or "tokens").
70949 *
70950 * If no column is specified, then the values in all columns and
70951 * rows are processed. A specific column may be referenced by
70952 * either its ID or title.
70953 *
70954 * @method removeTokens
70955 * @param {String} chars String listing characters to be removed
70956 * @param {String|Integer} [column] Column ID (number)
70957 * or name (string)
70958 *
70959 * @example
70960 * <div class="norender"><code>
70961 * function setup() {
70962 * let table = new p5.Table();
70963 *
70964 * table.addColumn('name');
70965 * table.addColumn('type');
70966 *
70967 * let newRow = table.addRow();
70968 * newRow.setString('name', ' $Lion ,');
70969 * newRow.setString('type', ',,,Mammal');
70970 *
70971 * newRow = table.addRow();
70972 * newRow.setString('name', '$Snake ');
70973 * newRow.setString('type', ',,,Reptile');
70974 *
70975 * table.removeTokens(',$ ');
70976 * print(table.getArray());
70977 * }
70978 *
70979 * // prints:
70980 * // 0 "Lion" "Mamal"
70981 * // 1 "Snake" "Reptile"
70982 * </code></div>
70983 */
70984 _main.default.Table.prototype.removeTokens = function(chars, column) {
70985 var escape = function escape(s) {
70986 return s.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
70987 };
70988 var charArray = [];
70989 for (var i = 0; i < chars.length; i++) {
70990 charArray.push(escape(chars.charAt(i)));
70991 }
70992 var regex = new RegExp(charArray.join('|'), 'g');
70993
70994 if (typeof column === 'undefined') {
70995 for (var c = 0; c < this.columns.length; c++) {
70996 for (var d = 0; d < this.rows.length; d++) {
70997 var s = this.rows[d].arr[c];
70998 s = s.replace(regex, '');
70999 this.rows[d].arr[c] = s;
71000 this.rows[d].obj[this.columns[c]] = s;
71001 }
71002 }
71003 } else if (typeof column === 'string') {
71004 for (var j = 0; j < this.rows.length; j++) {
71005 var val = this.rows[j].obj[column];
71006 val = val.replace(regex, '');
71007 this.rows[j].obj[column] = val;
71008 var pos = this.columns.indexOf(column);
71009 this.rows[j].arr[pos] = val;
71010 }
71011 } else {
71012 for (var k = 0; k < this.rows.length; k++) {
71013 var str = this.rows[k].arr[column];
71014 str = str.replace(regex, '');
71015 this.rows[k].arr[column] = str;
71016 this.rows[k].obj[this.columns[column]] = str;
71017 }
71018 }
71019 };
71020
71021 /**
71022 * Trims leading and trailing whitespace, such as spaces and tabs,
71023 * from String table values. If no column is specified, then the
71024 * values in all columns and rows are trimmed. A specific column
71025 * may be referenced by either its ID or title.
71026 *
71027 * @method trim
71028 * @param {String|Integer} [column] Column ID (number)
71029 * or name (string)
71030 * @example
71031 * <div class="norender"><code>
71032 * function setup() {
71033 * let table = new p5.Table();
71034 *
71035 * table.addColumn('name');
71036 * table.addColumn('type');
71037 *
71038 * let newRow = table.addRow();
71039 * newRow.setString('name', ' Lion ,');
71040 * newRow.setString('type', ' Mammal ');
71041 *
71042 * newRow = table.addRow();
71043 * newRow.setString('name', ' Snake ');
71044 * newRow.setString('type', ' Reptile ');
71045 *
71046 * table.trim();
71047 * print(table.getArray());
71048 * }
71049 *
71050 * // prints:
71051 * // 0 "Lion" "Mamal"
71052 * // 1 "Snake" "Reptile"
71053 * </code></div>
71054 */
71055 _main.default.Table.prototype.trim = function(column) {
71056 var regex = new RegExp(' ', 'g');
71057
71058 if (typeof column === 'undefined') {
71059 for (var c = 0; c < this.columns.length; c++) {
71060 for (var d = 0; d < this.rows.length; d++) {
71061 var s = this.rows[d].arr[c];
71062 s = s.replace(regex, '');
71063 this.rows[d].arr[c] = s;
71064 this.rows[d].obj[this.columns[c]] = s;
71065 }
71066 }
71067 } else if (typeof column === 'string') {
71068 for (var j = 0; j < this.rows.length; j++) {
71069 var val = this.rows[j].obj[column];
71070 val = val.replace(regex, '');
71071 this.rows[j].obj[column] = val;
71072 var pos = this.columns.indexOf(column);
71073 this.rows[j].arr[pos] = val;
71074 }
71075 } else {
71076 for (var k = 0; k < this.rows.length; k++) {
71077 var str = this.rows[k].arr[column];
71078 str = str.replace(regex, '');
71079 this.rows[k].arr[column] = str;
71080 this.rows[k].obj[this.columns[column]] = str;
71081 }
71082 }
71083 };
71084
71085 /**
71086 * Use <a href="#/p5/removeColumn">removeColumn()</a> to remove an existing column from a Table
71087 * object. The column to be removed may be identified by either
71088 * its title (a String) or its index value (an int).
71089 * removeColumn(0) would remove the first column, removeColumn(1)
71090 * would remove the second column, and so on.
71091 *
71092 * @method removeColumn
71093 * @param {String|Integer} column columnName (string) or ID (number)
71094 *
71095 * @example
71096 * <div class="norender">
71097 * <code>
71098 * // Given the CSV file "mammals.csv"
71099 * // in the project's "assets" folder:
71100 * //
71101 * // id,species,name
71102 * // 0,Capra hircus,Goat
71103 * // 1,Panthera pardus,Leopard
71104 * // 2,Equus zebra,Zebra
71105 *
71106 * let table;
71107 *
71108 * function preload() {
71109 * //my table is comma separated value "csv"
71110 * //and has a header specifying the columns labels
71111 * table = loadTable('assets/mammals.csv', 'csv', 'header');
71112 * }
71113 *
71114 * function setup() {
71115 * table.removeColumn('id');
71116 * print(table.getColumnCount());
71117 * }
71118 * </code>
71119 * </div>
71120 *
71121 *@alt
71122 * no image displayed
71123 */
71124 _main.default.Table.prototype.removeColumn = function(c) {
71125 var cString;
71126 var cNumber;
71127 if (typeof c === 'string') {
71128 // find the position of c in the columns
71129 cString = c;
71130 cNumber = this.columns.indexOf(c);
71131 } else {
71132 cNumber = c;
71133 cString = this.columns[c];
71134 }
71135
71136 var chunk = this.columns.splice(cNumber + 1, this.columns.length);
71137 this.columns.pop();
71138 this.columns = this.columns.concat(chunk);
71139
71140 for (var i = 0; i < this.rows.length; i++) {
71141 var tempR = this.rows[i].arr;
71142 var chip = tempR.splice(cNumber + 1, tempR.length);
71143 tempR.pop();
71144 this.rows[i].arr = tempR.concat(chip);
71145 delete this.rows[i].obj[cString];
71146 }
71147 };
71148
71149 /**
71150 * Stores a value in the Table's specified row and column.
71151 * The row is specified by its ID, while the column may be specified
71152 * by either its ID or title.
71153 *
71154 * @method set
71155 * @param {Integer} row row ID
71156 * @param {String|Integer} column column ID (Number)
71157 * or title (String)
71158 * @param {String|Number} value value to assign
71159 *
71160 * @example
71161 * <div class="norender">
71162 * <code>
71163 * // Given the CSV file "mammals.csv"
71164 * // in the project's "assets" folder:
71165 * //
71166 * // id,species,name
71167 * // 0,Capra hircus,Goat
71168 * // 1,Panthera pardus,Leopard
71169 * // 2,Equus zebra,Zebra
71170 *
71171 * let table;
71172 *
71173 * function preload() {
71174 * //my table is comma separated value "csv"
71175 * //and has a header specifying the columns labels
71176 * table = loadTable('assets/mammals.csv', 'csv', 'header');
71177 * }
71178 *
71179 * function setup() {
71180 * table.set(0, 'species', 'Canis Lupus');
71181 * table.set(0, 'name', 'Wolf');
71182 *
71183 * //print the results
71184 * for (let r = 0; r < table.getRowCount(); r++)
71185 * for (let c = 0; c < table.getColumnCount(); c++)
71186 * print(table.getString(r, c));
71187 * }
71188 * </code>
71189 * </div>
71190 *
71191 *@alt
71192 * no image displayed
71193 */
71194 _main.default.Table.prototype.set = function(row, column, value) {
71195 this.rows[row].set(column, value);
71196 };
71197
71198 /**
71199 * Stores a Float value in the Table's specified row and column.
71200 * The row is specified by its ID, while the column may be specified
71201 * by either its ID or title.
71202 *
71203 * @method setNum
71204 * @param {Integer} row row ID
71205 * @param {String|Integer} column column ID (Number)
71206 * or title (String)
71207 * @param {Number} value value to assign
71208 *
71209 * @example
71210 * <div class="norender">
71211 * <code>
71212 * // Given the CSV file "mammals.csv"
71213 * // in the project's "assets" folder:
71214 * //
71215 * // id,species,name
71216 * // 0,Capra hircus,Goat
71217 * // 1,Panthera pardus,Leopard
71218 * // 2,Equus zebra,Zebra
71219 *
71220 * let table;
71221 *
71222 * function preload() {
71223 * //my table is comma separated value "csv"
71224 * //and has a header specifying the columns labels
71225 * table = loadTable('assets/mammals.csv', 'csv', 'header');
71226 * }
71227 *
71228 * function setup() {
71229 * table.setNum(1, 'id', 1);
71230 *
71231 * print(table.getColumn(0));
71232 * //["0", 1, "2"]
71233 * }
71234 * </code>
71235 * </div>
71236 *
71237 *@alt
71238 * no image displayed
71239 */
71240 _main.default.Table.prototype.setNum = function(row, column, value) {
71241 this.rows[row].setNum(column, value);
71242 };
71243
71244 /**
71245 * Stores a String value in the Table's specified row and column.
71246 * The row is specified by its ID, while the column may be specified
71247 * by either its ID or title.
71248 *
71249 * @method setString
71250 * @param {Integer} row row ID
71251 * @param {String|Integer} column column ID (Number)
71252 * or title (String)
71253 * @param {String} value value to assign
71254 * @example
71255 * <div class="norender"><code>
71256 * // Given the CSV file "mammals.csv" in the project's "assets" folder:
71257 * //
71258 * // id,species,name
71259 * // 0,Capra hircus,Goat
71260 * // 1,Panthera pardus,Leopard
71261 * // 2,Equus zebra,Zebra
71262 *
71263 * let table;
71264 *
71265 * function preload() {
71266 * //my table is comma separated value "csv"
71267 * //and has a header specifying the columns labels
71268 * table = loadTable('assets/mammals.csv', 'csv', 'header');
71269 * }
71270 *
71271 * function setup() {
71272 * //add a row
71273 * let newRow = table.addRow();
71274 * newRow.setString('id', table.getRowCount() - 1);
71275 * newRow.setString('species', 'Canis Lupus');
71276 * newRow.setString('name', 'Wolf');
71277 *
71278 * print(table.getArray());
71279 * }
71280 * </code></div>
71281 *
71282 * @alt
71283 * no image displayed
71284 */
71285 _main.default.Table.prototype.setString = function(row, column, value) {
71286 this.rows[row].setString(column, value);
71287 };
71288
71289 /**
71290 * Retrieves a value from the Table's specified row and column.
71291 * The row is specified by its ID, while the column may be specified by
71292 * either its ID or title.
71293 *
71294 * @method get
71295 * @param {Integer} row row ID
71296 * @param {String|Integer} column columnName (string) or
71297 * ID (number)
71298 * @return {String|Number}
71299 *
71300 * @example
71301 * <div class="norender">
71302 * <code>
71303 * // Given the CSV file "mammals.csv"
71304 * // in the project's "assets" folder:
71305 * //
71306 * // id,species,name
71307 * // 0,Capra hircus,Goat
71308 * // 1,Panthera pardus,Leopard
71309 * // 2,Equus zebra,Zebra
71310 *
71311 * let table;
71312 *
71313 * function preload() {
71314 * //my table is comma separated value "csv"
71315 * //and has a header specifying the columns labels
71316 * table = loadTable('assets/mammals.csv', 'csv', 'header');
71317 * }
71318 *
71319 * function setup() {
71320 * print(table.get(0, 1));
71321 * //Capra hircus
71322 * print(table.get(0, 'species'));
71323 * //Capra hircus
71324 * }
71325 * </code>
71326 * </div>
71327 *
71328 *@alt
71329 * no image displayed
71330 */
71331 _main.default.Table.prototype.get = function(row, column) {
71332 return this.rows[row].get(column);
71333 };
71334
71335 /**
71336 * Retrieves a Float value from the Table's specified row and column.
71337 * The row is specified by its ID, while the column may be specified by
71338 * either its ID or title.
71339 *
71340 * @method getNum
71341 * @param {Integer} row row ID
71342 * @param {String|Integer} column columnName (string) or
71343 * ID (number)
71344 * @return {Number}
71345 *
71346 * @example
71347 * <div class="norender">
71348 * <code>
71349 * // Given the CSV file "mammals.csv"
71350 * // in the project's "assets" folder:
71351 * //
71352 * // id,species,name
71353 * // 0,Capra hircus,Goat
71354 * // 1,Panthera pardus,Leopard
71355 * // 2,Equus zebra,Zebra
71356 *
71357 * let table;
71358 *
71359 * function preload() {
71360 * //my table is comma separated value "csv"
71361 * //and has a header specifying the columns labels
71362 * table = loadTable('assets/mammals.csv', 'csv', 'header');
71363 * }
71364 *
71365 * function setup() {
71366 * print(table.getNum(1, 0) + 100);
71367 * //id 1 + 100 = 101
71368 * }
71369 * </code>
71370 * </div>
71371 *
71372 *@alt
71373 * no image displayed
71374 */
71375 _main.default.Table.prototype.getNum = function(row, column) {
71376 return this.rows[row].getNum(column);
71377 };
71378
71379 /**
71380 * Retrieves a String value from the Table's specified row and column.
71381 * The row is specified by its ID, while the column may be specified by
71382 * either its ID or title.
71383 *
71384 * @method getString
71385 * @param {Integer} row row ID
71386 * @param {String|Integer} column columnName (string) or
71387 * ID (number)
71388 * @return {String}
71389 *
71390 * @example
71391 * <div class="norender">
71392 * <code>
71393 * // Given the CSV file "mammals.csv"
71394 * // in the project's "assets" folder:
71395 * //
71396 * // id,species,name
71397 * // 0,Capra hircus,Goat
71398 * // 1,Panthera pardus,Leopard
71399 * // 2,Equus zebra,Zebra
71400 *
71401 * let table;
71402 *
71403 * function preload() {
71404 * // table is comma separated value "CSV"
71405 * // and has specifiying header for column labels
71406 * table = loadTable('assets/mammals.csv', 'csv', 'header');
71407 * }
71408 *
71409 * function setup() {
71410 * print(table.getString(0, 0)); // 0
71411 * print(table.getString(0, 1)); // Capra hircus
71412 * print(table.getString(0, 2)); // Goat
71413 * print(table.getString(1, 0)); // 1
71414 * print(table.getString(1, 1)); // Panthera pardus
71415 * print(table.getString(1, 2)); // Leopard
71416 * print(table.getString(2, 0)); // 2
71417 * print(table.getString(2, 1)); // Equus zebra
71418 * print(table.getString(2, 2)); // Zebra
71419 * }
71420 * </code>
71421 * </div>
71422 *
71423 *@alt
71424 * no image displayed
71425 */
71426
71427 _main.default.Table.prototype.getString = function(row, column) {
71428 return this.rows[row].getString(column);
71429 };
71430
71431 /**
71432 * Retrieves all table data and returns as an object. If a column name is
71433 * passed in, each row object will be stored with that attribute as its
71434 * title.
71435 *
71436 * @method getObject
71437 * @param {String} [headerColumn] Name of the column which should be used to
71438 * title each row object (optional)
71439 * @return {Object}
71440 *
71441 * @example
71442 * <div class="norender">
71443 * <code>
71444 * // Given the CSV file "mammals.csv"
71445 * // in the project's "assets" folder:
71446 * //
71447 * // id,species,name
71448 * // 0,Capra hircus,Goat
71449 * // 1,Panthera pardus,Leopard
71450 * // 2,Equus zebra,Zebra
71451 *
71452 * let table;
71453 *
71454 * function preload() {
71455 * //my table is comma separated value "csv"
71456 * //and has a header specifying the columns labels
71457 * table = loadTable('assets/mammals.csv', 'csv', 'header');
71458 * }
71459 *
71460 * function setup() {
71461 * let tableObject = table.getObject();
71462 *
71463 * print(tableObject);
71464 * //outputs an object
71465 * }
71466 * </code>
71467 * </div>
71468 *
71469 *@alt
71470 * no image displayed
71471 */
71472 _main.default.Table.prototype.getObject = function(headerColumn) {
71473 var tableObject = {};
71474 var obj, cPos, index;
71475
71476 for (var i = 0; i < this.rows.length; i++) {
71477 obj = this.rows[i].obj;
71478
71479 if (typeof headerColumn === 'string') {
71480 cPos = this.columns.indexOf(headerColumn); // index of columnID
71481 if (cPos >= 0) {
71482 index = obj[headerColumn];
71483 tableObject[index] = obj;
71484 } else {
71485 throw new Error(
71486 'This table has no column named "'.concat(headerColumn, '"')
71487 );
71488 }
71489 } else {
71490 tableObject[i] = this.rows[i].obj;
71491 }
71492 }
71493 return tableObject;
71494 };
71495
71496 /**
71497 * Retrieves all table data and returns it as a multidimensional array.
71498 *
71499 * @method getArray
71500 * @return {Array}
71501 *
71502 * @example
71503 * <div class="norender">
71504 * <code>
71505 * // Given the CSV file "mammals.csv"
71506 * // in the project's "assets" folder
71507 * //
71508 * // id,species,name
71509 * // 0,Capra hircus,Goat
71510 * // 1,Panthera pardus,Leoperd
71511 * // 2,Equus zebra,Zebra
71512 *
71513 * let table;
71514 *
71515 * function preload() {
71516 * // table is comma separated value "CSV"
71517 * // and has specifiying header for column labels
71518 * table = loadTable('assets/mammals.csv', 'csv', 'header');
71519 * }
71520 *
71521 * function setup() {
71522 * let tableArray = table.getArray();
71523 * for (let i = 0; i < tableArray.length; i++) {
71524 * print(tableArray[i]);
71525 * }
71526 * }
71527 * </code>
71528 * </div>
71529 *
71530 *@alt
71531 * no image displayed
71532 */
71533 _main.default.Table.prototype.getArray = function() {
71534 var tableArray = [];
71535 for (var i = 0; i < this.rows.length; i++) {
71536 tableArray.push(this.rows[i].arr);
71537 }
71538 return tableArray;
71539 };
71540 var _default = _main.default;
71541 exports.default = _default;
71542 },
71543 { '../core/main': 54 }
71544 ],
71545 82: [
71546 function(_dereq_, module, exports) {
71547 'use strict';
71548 Object.defineProperty(exports, '__esModule', { value: true });
71549 exports.default = void 0;
71550
71551 var _main = _interopRequireDefault(_dereq_('../core/main'));
71552 function _interopRequireDefault(obj) {
71553 return obj && obj.__esModule ? obj : { default: obj };
71554 }
71555 /**
71556 * @module IO
71557 * @submodule Table
71558 * @requires core
71559 */ /**
71560 * A TableRow object represents a single row of data values,
71561 * stored in columns, from a table.
71562 *
71563 * A Table Row contains both an ordered array, and an unordered
71564 * JSON object.
71565 *
71566 * @class p5.TableRow
71567 * @constructor
71568 * @param {String} [str] optional: populate the row with a
71569 * string of values, separated by the
71570 * separator
71571 * @param {String} [separator] comma separated values (csv) by default
71572 */ _main.default.TableRow = function(str, separator) {
71573 var arr = [];
71574 var obj = {};
71575 if (str) {
71576 separator = separator || ',';
71577 arr = str.split(separator);
71578 }
71579 for (var i = 0; i < arr.length; i++) {
71580 var key = i;
71581 var val = arr[i];
71582 obj[key] = val;
71583 }
71584 this.arr = arr;
71585 this.obj = obj;
71586 this.table = null;
71587 };
71588
71589 /**
71590 * Stores a value in the TableRow's specified column.
71591 * The column may be specified by either its ID or title.
71592 *
71593 * @method set
71594 * @param {String|Integer} column Column ID (Number)
71595 * or Title (String)
71596 * @param {String|Number} value The value to be stored
71597 *
71598 * @example
71599 * <div class="norender"><code>
71600 * // Given the CSV file "mammals.csv" in the project's "assets" folder:
71601 * //
71602 * // id,species,name
71603 * // 0,Capra hircus,Goat
71604 * // 1,Panthera pardus,Leopard
71605 * // 2,Equus zebra,Zebra
71606 *
71607 * let table;
71608 *
71609 * function preload() {
71610 * //my table is comma separated value "csv"
71611 * //and has a header specifying the columns labels
71612 * table = loadTable('assets/mammals.csv', 'csv', 'header');
71613 * }
71614 *
71615 * function setup() {
71616 * let rows = table.getRows();
71617 * for (let r = 0; r < rows.length; r++) {
71618 * rows[r].set('name', 'Unicorn');
71619 * }
71620 *
71621 * //print the results
71622 * print(table.getArray());
71623 * }
71624 * </code></div>
71625 *
71626 * @alt
71627 * no image displayed
71628 */
71629 _main.default.TableRow.prototype.set = function(column, value) {
71630 // if typeof column is string, use .obj
71631 if (typeof column === 'string') {
71632 var cPos = this.table.columns.indexOf(column); // index of columnID
71633 if (cPos >= 0) {
71634 this.obj[column] = value;
71635 this.arr[cPos] = value;
71636 } else {
71637 throw new Error('This table has no column named "'.concat(column, '"'));
71638 }
71639 } else {
71640 // if typeof column is number, use .arr
71641 if (column < this.table.columns.length) {
71642 this.arr[column] = value;
71643 var cTitle = this.table.columns[column];
71644 this.obj[cTitle] = value;
71645 } else {
71646 throw new Error(
71647 'Column #'.concat(column, ' is out of the range of this table')
71648 );
71649 }
71650 }
71651 };
71652
71653 /**
71654 * Stores a Float value in the TableRow's specified column.
71655 * The column may be specified by either its ID or title.
71656 *
71657 * @method setNum
71658 * @param {String|Integer} column Column ID (Number)
71659 * or Title (String)
71660 * @param {Number|String} value The value to be stored
71661 * as a Float
71662 * @example
71663 * <div class="norender"><code>
71664 * // Given the CSV file "mammals.csv" in the project's "assets" folder:
71665 * //
71666 * // id,species,name
71667 * // 0,Capra hircus,Goat
71668 * // 1,Panthera pardus,Leopard
71669 * // 2,Equus zebra,Zebra
71670 *
71671 * let table;
71672 *
71673 * function preload() {
71674 * //my table is comma separated value "csv"
71675 * //and has a header specifying the columns labels
71676 * table = loadTable('assets/mammals.csv', 'csv', 'header');
71677 * }
71678 *
71679 * function setup() {
71680 * let rows = table.getRows();
71681 * for (let r = 0; r < rows.length; r++) {
71682 * rows[r].setNum('id', r + 10);
71683 * }
71684 *
71685 * print(table.getArray());
71686 * }
71687 * </code></div>
71688 *
71689 * @alt
71690 * no image displayed
71691 */
71692 _main.default.TableRow.prototype.setNum = function(column, value) {
71693 var floatVal = parseFloat(value);
71694 this.set(column, floatVal);
71695 };
71696
71697 /**
71698 * Stores a String value in the TableRow's specified column.
71699 * The column may be specified by either its ID or title.
71700 *
71701 * @method setString
71702 * @param {String|Integer} column Column ID (Number)
71703 * or Title (String)
71704 * @param {String|Number|Boolean|Object} value The value to be stored
71705 * as a String
71706 * @example
71707 * <div class="norender"><code>
71708 * // Given the CSV file "mammals.csv" in the project's "assets" folder:
71709 * //
71710 * // id,species,name
71711 * // 0,Capra hircus,Goat
71712 * // 1,Panthera pardus,Leopard
71713 * // 2,Equus zebra,Zebra
71714 *
71715 * let table;
71716 *
71717 * function preload() {
71718 * //my table is comma separated value "csv"
71719 * //and has a header specifying the columns labels
71720 * table = loadTable('assets/mammals.csv', 'csv', 'header');
71721 * }
71722 *
71723 * function setup() {
71724 * let rows = table.getRows();
71725 * for (let r = 0; r < rows.length; r++) {
71726 * let name = rows[r].getString('name');
71727 * rows[r].setString('name', 'A ' + name + ' named George');
71728 * }
71729 *
71730 * print(table.getArray());
71731 * }
71732 * </code></div>
71733 *
71734 * @alt
71735 * no image displayed
71736 */
71737 _main.default.TableRow.prototype.setString = function(column, value) {
71738 var stringVal = value.toString();
71739 this.set(column, stringVal);
71740 };
71741
71742 /**
71743 * Retrieves a value from the TableRow's specified column.
71744 * The column may be specified by either its ID or title.
71745 *
71746 * @method get
71747 * @param {String|Integer} column columnName (string) or
71748 * ID (number)
71749 * @return {String|Number}
71750 *
71751 * @example
71752 * <div class="norender"><code>
71753 * // Given the CSV file "mammals.csv" in the project's "assets" folder:
71754 * //
71755 * // id,species,name
71756 * // 0,Capra hircus,Goat
71757 * // 1,Panthera pardus,Leopard
71758 * // 2,Equus zebra,Zebra
71759 *
71760 * let table;
71761 *
71762 * function preload() {
71763 * //my table is comma separated value "csv"
71764 * //and has a header specifying the columns labels
71765 * table = loadTable('assets/mammals.csv', 'csv', 'header');
71766 * }
71767 *
71768 * function setup() {
71769 * let names = [];
71770 * let rows = table.getRows();
71771 * for (let r = 0; r < rows.length; r++) {
71772 * names.push(rows[r].get('name'));
71773 * }
71774 *
71775 * print(names);
71776 * }
71777 * </code></div>
71778 *
71779 * @alt
71780 * no image displayed
71781 */
71782 _main.default.TableRow.prototype.get = function(column) {
71783 if (typeof column === 'string') {
71784 return this.obj[column];
71785 } else {
71786 return this.arr[column];
71787 }
71788 };
71789
71790 /**
71791 * Retrieves a Float value from the TableRow's specified
71792 * column. The column may be specified by either its ID or
71793 * title.
71794 *
71795 * @method getNum
71796 * @param {String|Integer} column columnName (string) or
71797 * ID (number)
71798 * @return {Number} Float Floating point number
71799 * @example
71800 * <div class="norender"><code>
71801 * // Given the CSV file "mammals.csv" in the project's "assets" folder:
71802 * //
71803 * // id,species,name
71804 * // 0,Capra hircus,Goat
71805 * // 1,Panthera pardus,Leopard
71806 * // 2,Equus zebra,Zebra
71807 *
71808 * let table;
71809 *
71810 * function preload() {
71811 * //my table is comma separated value "csv"
71812 * //and has a header specifying the columns labels
71813 * table = loadTable('assets/mammals.csv', 'csv', 'header');
71814 * }
71815 *
71816 * function setup() {
71817 * let rows = table.getRows();
71818 * let minId = Infinity;
71819 * let maxId = -Infinity;
71820 * for (let r = 0; r < rows.length; r++) {
71821 * let id = rows[r].getNum('id');
71822 * minId = min(minId, id);
71823 * maxId = min(maxId, id);
71824 * }
71825 * print('minimum id = ' + minId + ', maximum id = ' + maxId);
71826 * }
71827 * </code></div>
71828 *
71829 * @alt
71830 * no image displayed
71831 */
71832 _main.default.TableRow.prototype.getNum = function(column) {
71833 var ret;
71834 if (typeof column === 'string') {
71835 ret = parseFloat(this.obj[column]);
71836 } else {
71837 ret = parseFloat(this.arr[column]);
71838 }
71839
71840 if (ret.toString() === 'NaN') {
71841 throw 'Error: '.concat(this.obj[column], ' is NaN (Not a Number)');
71842 }
71843 return ret;
71844 };
71845
71846 /**
71847 * Retrieves an String value from the TableRow's specified
71848 * column. The column may be specified by either its ID or
71849 * title.
71850 *
71851 * @method getString
71852 * @param {String|Integer} column columnName (string) or
71853 * ID (number)
71854 * @return {String} String
71855 * @example
71856 * <div class="norender"><code>
71857 * // Given the CSV file "mammals.csv" in the project's "assets" folder:
71858 * //
71859 * // id,species,name
71860 * // 0,Capra hircus,Goat
71861 * // 1,Panthera pardus,Leopard
71862 * // 2,Equus zebra,Zebra
71863 *
71864 * let table;
71865 *
71866 * function preload() {
71867 * //my table is comma separated value "csv"
71868 * //and has a header specifying the columns labels
71869 * table = loadTable('assets/mammals.csv', 'csv', 'header');
71870 * }
71871 *
71872 * function setup() {
71873 * let rows = table.getRows();
71874 * let longest = '';
71875 * for (let r = 0; r < rows.length; r++) {
71876 * let species = rows[r].getString('species');
71877 * if (longest.length < species.length) {
71878 * longest = species;
71879 * }
71880 * }
71881 *
71882 * print('longest: ' + longest);
71883 * }
71884 * </code></div>
71885 *
71886 * @alt
71887 * no image displayed
71888 */
71889 _main.default.TableRow.prototype.getString = function(column) {
71890 if (typeof column === 'string') {
71891 return this.obj[column].toString();
71892 } else {
71893 return this.arr[column].toString();
71894 }
71895 };
71896 var _default = _main.default;
71897 exports.default = _default;
71898 },
71899 { '../core/main': 54 }
71900 ],
71901 83: [
71902 function(_dereq_, module, exports) {
71903 'use strict';
71904 Object.defineProperty(exports, '__esModule', { value: true });
71905 exports.default = void 0;
71906
71907 var _main = _interopRequireDefault(_dereq_('../core/main'));
71908 function _interopRequireDefault(obj) {
71909 return obj && obj.__esModule ? obj : { default: obj };
71910 }
71911 /**
71912 * @module IO
71913 * @submodule Input
71914 * @requires core
71915 */ /**
71916 * XML is a representation of an XML object, able to parse XML code. Use
71917 * <a href="#/p5/loadXML">loadXML()</a> to load external XML files and create XML objects.
71918 *
71919 * @class p5.XML
71920 * @constructor
71921 * @example
71922 * <div class='norender'><code>
71923 * // The following short XML file called "mammals.xml" is parsed
71924 * // in the code below.
71925 * //
71926 * // <?xml version="1.0"?>
71927 * // &lt;mammals&gt;
71928 * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
71929 * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
71930 * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
71931 * // &lt;/mammals&gt;
71932 *
71933 * let xml;
71934 *
71935 * function preload() {
71936 * xml = loadXML('assets/mammals.xml');
71937 * }
71938 *
71939 * function setup() {
71940 * let children = xml.getChildren('animal');
71941 *
71942 * for (let i = 0; i < children.length; i++) {
71943 * let id = children[i].getNum('id');
71944 * let coloring = children[i].getString('species');
71945 * let name = children[i].getContent();
71946 * print(id + ', ' + coloring + ', ' + name);
71947 * }
71948 * }
71949 *
71950 * // Sketch prints:
71951 * // 0, Capra hircus, Goat
71952 * // 1, Panthera pardus, Leopard
71953 * // 2, Equus zebra, Zebra
71954 * </code></div>
71955 *
71956 * @alt
71957 * no image displayed
71958 */ _main.default.XML = function(DOM) {
71959 if (!DOM) {
71960 var xmlDoc = document.implementation.createDocument(null, 'doc');
71961 this.DOM = xmlDoc.createElement('root');
71962 } else {
71963 this.DOM = DOM;
71964 }
71965 };
71966
71967 /**
71968 * Gets a copy of the element's parent. Returns the parent as another
71969 * <a href="#/p5.XML">p5.XML</a> object.
71970 *
71971 * @method getParent
71972 * @return {p5.XML} element parent
71973 * @example
71974 * <div class='norender'><code>
71975 * // The following short XML file called "mammals.xml" is parsed
71976 * // in the code below.
71977 * //
71978 * // <?xml version="1.0"?>
71979 * // &lt;mammals&gt;
71980 * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
71981 * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
71982 * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
71983 * // &lt;/mammals&gt;
71984 *
71985 * let xml;
71986 *
71987 * function preload() {
71988 * xml = loadXML('assets/mammals.xml');
71989 * }
71990 *
71991 * function setup() {
71992 * let children = xml.getChildren('animal');
71993 * let parent = children[1].getParent();
71994 * print(parent.getName());
71995 * }
71996 *
71997 * // Sketch prints:
71998 * // mammals
71999 * </code></div>
72000 */
72001 _main.default.XML.prototype.getParent = function() {
72002 return new _main.default.XML(this.DOM.parentElement);
72003 };
72004
72005 /**
72006 * Gets the element's full name, which is returned as a String.
72007 *
72008 * @method getName
72009 * @return {String} the name of the node
72010 * @example&lt;animal
72011 * <div class='norender'><code>
72012 * // The following short XML file called "mammals.xml" is parsed
72013 * // in the code below.
72014 * //
72015 * // <?xml version="1.0"?>
72016 * // &lt;mammals&gt;
72017 * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
72018 * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
72019 * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
72020 * // &lt;/mammals&gt;
72021 *
72022 * let xml;
72023 *
72024 * function preload() {
72025 * xml = loadXML('assets/mammals.xml');
72026 * }
72027 *
72028 * function setup() {
72029 * print(xml.getName());
72030 * }
72031 *
72032 * // Sketch prints:
72033 * // mammals
72034 * </code></div>
72035 */
72036 _main.default.XML.prototype.getName = function() {
72037 return this.DOM.tagName;
72038 };
72039
72040 /**
72041 * Sets the element's name, which is specified as a String.
72042 *
72043 * @method setName
72044 * @param {String} the new name of the node
72045 * @example&lt;animal
72046 * <div class='norender'><code>
72047 * // The following short XML file called "mammals.xml" is parsed
72048 * // in the code below.
72049 * //
72050 * // <?xml version="1.0"?>
72051 * // &lt;mammals&gt;
72052 * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
72053 * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
72054 * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
72055 * // &lt;/mammals&gt;
72056 *
72057 * let xml;
72058 *
72059 * function preload() {
72060 * xml = loadXML('assets/mammals.xml');
72061 * }
72062 *
72063 * function setup() {
72064 * print(xml.getName());
72065 * xml.setName('fish');
72066 * print(xml.getName());
72067 * }
72068 *
72069 * // Sketch prints:
72070 * // mammals
72071 * // fish
72072 * </code></div>
72073 */
72074 _main.default.XML.prototype.setName = function(name) {
72075 var content = this.DOM.innerHTML;
72076 var attributes = this.DOM.attributes;
72077 var xmlDoc = document.implementation.createDocument(null, 'default');
72078 var newDOM = xmlDoc.createElement(name);
72079 newDOM.innerHTML = content;
72080 for (var i = 0; i < attributes.length; i++) {
72081 newDOM.setAttribute(attributes[i].nodeName, attributes.nodeValue);
72082 }
72083 this.DOM = newDOM;
72084 };
72085
72086 /**
72087 * Checks whether or not the element has any children, and returns the result
72088 * as a boolean.
72089 *
72090 * @method hasChildren
72091 * @return {boolean}
72092 * @example&lt;animal
72093 * <div class='norender'><code>
72094 * // The following short XML file called "mammals.xml" is parsed
72095 * // in the code below.
72096 * //
72097 * // <?xml version="1.0"?>
72098 * // &lt;mammals&gt;
72099 * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
72100 * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
72101 * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
72102 * // &lt;/mammals&gt;
72103 *
72104 * let xml;
72105 *
72106 * function preload() {
72107 * xml = loadXML('assets/mammals.xml');
72108 * }
72109 *
72110 * function setup() {
72111 * print(xml.hasChildren());
72112 * }
72113 *
72114 * // Sketch prints:
72115 * // true
72116 * </code></div>
72117 */
72118 _main.default.XML.prototype.hasChildren = function() {
72119 return this.DOM.children.length > 0;
72120 };
72121
72122 /**
72123 * Get the names of all of the element's children, and returns the names as an
72124 * array of Strings. This is the same as looping through and calling <a href="#/p5.XML/getName">getName()</a>
72125 * on each child element individually.
72126 *
72127 * @method listChildren
72128 * @return {String[]} names of the children of the element
72129 * @example&lt;animal
72130 * <div class='norender'><code>
72131 * // The following short XML file called "mammals.xml" is parsed
72132 * // in the code below.
72133 * //
72134 * // <?xml version="1.0"?>
72135 * // &lt;mammals&gt;
72136 * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
72137 * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
72138 * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
72139 * // &lt;/mammals&gt;
72140 *
72141 * let xml;
72142 *
72143 * function preload() {
72144 * xml = loadXML('assets/mammals.xml');
72145 * }
72146 *
72147 * function setup() {
72148 * print(xml.listChildren());
72149 * }
72150 *
72151 * // Sketch prints:
72152 * // ["animal", "animal", "animal"]
72153 * </code></div>
72154 */
72155 _main.default.XML.prototype.listChildren = function() {
72156 var arr = [];
72157 for (var i = 0; i < this.DOM.childNodes.length; i++) {
72158 arr.push(this.DOM.childNodes[i].nodeName);
72159 }
72160 return arr;
72161 };
72162
72163 /**
72164 * Returns all of the element's children as an array of <a href="#/p5.XML">p5.XML</a> objects. When
72165 * the name parameter is specified, then it will return all children that match
72166 * that name.
72167 *
72168 * @method getChildren
72169 * @param {String} [name] element name
72170 * @return {p5.XML[]} children of the element
72171 * @example&lt;animal
72172 * <div class='norender'><code>
72173 * // The following short XML file called "mammals.xml" is parsed
72174 * // in the code below.
72175 * //
72176 * // <?xml version="1.0"?>
72177 * // &lt;mammals&gt;
72178 * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
72179 * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
72180 * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
72181 * // &lt;/mammals&gt;
72182 *
72183 * let xml;
72184 *
72185 * function preload() {
72186 * xml = loadXML('assets/mammals.xml');
72187 * }
72188 *
72189 * function setup() {
72190 * let animals = xml.getChildren('animal');
72191 *
72192 * for (let i = 0; i < animals.length; i++) {
72193 * print(animals[i].getContent());
72194 * }
72195 * }
72196 *
72197 * // Sketch prints:
72198 * // "Goat"
72199 * // "Leopard"
72200 * // "Zebra"
72201 * </code></div>
72202 */
72203 _main.default.XML.prototype.getChildren = function(param) {
72204 if (param) {
72205 return elementsToP5XML(this.DOM.getElementsByTagName(param));
72206 } else {
72207 return elementsToP5XML(this.DOM.children);
72208 }
72209 };
72210
72211 function elementsToP5XML(elements) {
72212 var arr = [];
72213 for (var i = 0; i < elements.length; i++) {
72214 arr.push(new _main.default.XML(elements[i]));
72215 }
72216 return arr;
72217 }
72218
72219 /**
72220 * Returns the first of the element's children that matches the name parameter
72221 * or the child of the given index.It returns undefined if no matching
72222 * child is found.
72223 *
72224 * @method getChild
72225 * @param {String|Integer} name element name or index
72226 * @return {p5.XML}
72227 * @example&lt;animal
72228 * <div class='norender'><code>
72229 * // The following short XML file called "mammals.xml" is parsed
72230 * // in the code below.
72231 * //
72232 * // <?xml version="1.0"?>
72233 * // &lt;mammals&gt;
72234 * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
72235 * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
72236 * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
72237 * // &lt;/mammals&gt;
72238 *
72239 * let xml;
72240 *
72241 * function preload() {
72242 * xml = loadXML('assets/mammals.xml');
72243 * }
72244 *
72245 * function setup() {
72246 * let firstChild = xml.getChild('animal');
72247 * print(firstChild.getContent());
72248 * }
72249 *
72250 * // Sketch prints:
72251 * // "Goat"
72252 * </code></div>
72253 * <div class='norender'><code>
72254 * let xml;
72255 *
72256 * function preload() {
72257 * xml = loadXML('assets/mammals.xml');
72258 * }
72259 *
72260 * function setup() {
72261 * let secondChild = xml.getChild(1);
72262 * print(secondChild.getContent());
72263 * }
72264 *
72265 * // Sketch prints:
72266 * // "Leopard"
72267 * </code></div>
72268 */
72269 _main.default.XML.prototype.getChild = function(param) {
72270 if (typeof param === 'string') {
72271 var _iteratorNormalCompletion = true;
72272 var _didIteratorError = false;
72273 var _iteratorError = undefined;
72274 try {
72275 for (
72276 var _iterator = this.DOM.children[Symbol.iterator](), _step;
72277 !(_iteratorNormalCompletion = (_step = _iterator.next()).done);
72278 _iteratorNormalCompletion = true
72279 ) {
72280 var child = _step.value;
72281 if (child.tagName === param) return new _main.default.XML(child);
72282 }
72283 } catch (err) {
72284 _didIteratorError = true;
72285 _iteratorError = err;
72286 } finally {
72287 try {
72288 if (!_iteratorNormalCompletion && _iterator.return != null) {
72289 _iterator.return();
72290 }
72291 } finally {
72292 if (_didIteratorError) {
72293 throw _iteratorError;
72294 }
72295 }
72296 }
72297 } else {
72298 return new _main.default.XML(this.DOM.children[param]);
72299 }
72300 };
72301
72302 /**
72303 * Appends a new child to the element. The child can be specified with
72304 * either a String, which will be used as the new tag's name, or as a
72305 * reference to an existing <a href="#/p5.XML">p5.XML</a> object.
72306 * A reference to the newly created child is returned as an <a href="#/p5.XML">p5.XML</a> object.
72307 *
72308 * @method addChild
72309 * @param {p5.XML} node a <a href="#/p5.XML">p5.XML</a> Object which will be the child to be added
72310 * @example
72311 * <div class='norender'><code>
72312 * // The following short XML file called "mammals.xml" is parsed
72313 * // in the code below.
72314 * //
72315 * // <?xml version="1.0"?>
72316 * // &lt;mammals&gt;
72317 * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
72318 * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
72319 * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
72320 * // &lt;/mammals&gt;
72321 *
72322 * let xml;
72323 *
72324 * function preload() {
72325 * xml = loadXML('assets/mammals.xml');
72326 * }
72327 *
72328 * function setup() {
72329 * let child = new p5.XML();
72330 * child.setName('animal');
72331 * child.setAttribute('id', '3');
72332 * child.setAttribute('species', 'Ornithorhynchus anatinus');
72333 * child.setContent('Platypus');
72334 * xml.addChild(child);
72335 *
72336 * let animals = xml.getChildren('animal');
72337 * print(animals[animals.length - 1].getContent());
72338 * }
72339 *
72340 * // Sketch prints:
72341 * // "Goat"
72342 * // "Leopard"
72343 * // "Zebra"
72344 * </code></div>
72345 */
72346 _main.default.XML.prototype.addChild = function(node) {
72347 if (node instanceof _main.default.XML) {
72348 this.DOM.appendChild(node.DOM);
72349 } else {
72350 // PEND
72351 }
72352 };
72353
72354 /**
72355 * Removes the element specified by name or index.
72356 *
72357 * @method removeChild
72358 * @param {String|Integer} name element name or index
72359 * @example
72360 * <div class='norender'><code>
72361 * // The following short XML file called "mammals.xml" is parsed
72362 * // in the code below.
72363 * //
72364 * // <?xml version="1.0"?>
72365 * // &lt;mammals&gt;
72366 * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
72367 * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
72368 * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
72369 * // &lt;/mammals&gt;
72370 *
72371 * let xml;
72372 *
72373 * function preload() {
72374 * xml = loadXML('assets/mammals.xml');
72375 * }
72376 *
72377 * function setup() {
72378 * xml.removeChild('animal');
72379 * let children = xml.getChildren();
72380 * for (let i = 0; i < children.length; i++) {
72381 * print(children[i].getContent());
72382 * }
72383 * }
72384 *
72385 * // Sketch prints:
72386 * // "Leopard"
72387 * // "Zebra"
72388 * </code></div>
72389 * <div class='norender'><code>
72390 * let xml;
72391 *
72392 * function preload() {
72393 * xml = loadXML('assets/mammals.xml');
72394 * }
72395 *
72396 * function setup() {
72397 * xml.removeChild(1);
72398 * let children = xml.getChildren();
72399 * for (let i = 0; i < children.length; i++) {
72400 * print(children[i].getContent());
72401 * }
72402 * }
72403 *
72404 * // Sketch prints:
72405 * // "Goat"
72406 * // "Zebra"
72407 * </code></div>
72408 */
72409 _main.default.XML.prototype.removeChild = function(param) {
72410 var ind = -1;
72411 if (typeof param === 'string') {
72412 for (var i = 0; i < this.DOM.children.length; i++) {
72413 if (this.DOM.children[i].tagName === param) {
72414 ind = i;
72415 break;
72416 }
72417 }
72418 } else {
72419 ind = param;
72420 }
72421 if (ind !== -1) {
72422 this.DOM.removeChild(this.DOM.children[ind]);
72423 }
72424 };
72425
72426 /**
72427 * Counts the specified element's number of attributes, returned as an Number.
72428 *
72429 * @method getAttributeCount
72430 * @return {Integer}
72431 * @example
72432 * <div class='norender'><code>
72433 * // The following short XML file called "mammals.xml" is parsed
72434 * // in the code below.
72435 * //
72436 * // <?xml version="1.0"?>
72437 * // &lt;mammals&gt;
72438 * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
72439 * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
72440 * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
72441 * // &lt;/mammals&gt;
72442 *
72443 * let xml;
72444 *
72445 * function preload() {
72446 * xml = loadXML('assets/mammals.xml');
72447 * }
72448 *
72449 * function setup() {
72450 * let firstChild = xml.getChild('animal');
72451 * print(firstChild.getAttributeCount());
72452 * }
72453 *
72454 * // Sketch prints:
72455 * // 2
72456 * </code></div>
72457 */
72458 _main.default.XML.prototype.getAttributeCount = function() {
72459 return this.DOM.attributes.length;
72460 };
72461
72462 /**
72463 * Gets all of the specified element's attributes, and returns them as an
72464 * array of Strings.
72465 *
72466 * @method listAttributes
72467 * @return {String[]} an array of strings containing the names of attributes
72468 * @example
72469 * <div class='norender'><code>
72470 * // The following short XML file called "mammals.xml" is parsed
72471 * // in the code below.
72472 * //
72473 * // <?xml version="1.0"?>
72474 * // &lt;mammals&gt;
72475 * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
72476 * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
72477 * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
72478 * // &lt;/mammals&gt;
72479 *
72480 * let xml;
72481 *
72482 * function preload() {
72483 * xml = loadXML('assets/mammals.xml');
72484 * }
72485 *
72486 * function setup() {
72487 * let firstChild = xml.getChild('animal');
72488 * print(firstChild.listAttributes());
72489 * }
72490 *
72491 * // Sketch prints:
72492 * // ["id", "species"]
72493 * </code></div>
72494 */
72495 _main.default.XML.prototype.listAttributes = function() {
72496 var arr = [];
72497 var _iteratorNormalCompletion2 = true;
72498 var _didIteratorError2 = false;
72499 var _iteratorError2 = undefined;
72500 try {
72501 for (
72502 var _iterator2 = this.DOM.attributes[Symbol.iterator](), _step2;
72503 !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done);
72504 _iteratorNormalCompletion2 = true
72505 ) {
72506 var attribute = _step2.value;
72507 arr.push(attribute.nodeName);
72508 }
72509 } catch (err) {
72510 _didIteratorError2 = true;
72511 _iteratorError2 = err;
72512 } finally {
72513 try {
72514 if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
72515 _iterator2.return();
72516 }
72517 } finally {
72518 if (_didIteratorError2) {
72519 throw _iteratorError2;
72520 }
72521 }
72522 }
72523
72524 return arr;
72525 };
72526
72527 /**
72528 * Checks whether or not an element has the specified attribute.
72529 *
72530 * @method hasAttribute
72531 * @param {String} the attribute to be checked
72532 * @return {boolean} true if attribute found else false
72533 * @example
72534 * <div class='norender'><code>
72535 * // The following short XML file called "mammals.xml" is parsed
72536 * // in the code below.
72537 * //
72538 * // <?xml version="1.0"?>
72539 * // &lt;mammals&gt;
72540 * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
72541 * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
72542 * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
72543 * // &lt;/mammals&gt;
72544 *
72545 * let xml;
72546 *
72547 * function preload() {
72548 * xml = loadXML('assets/mammals.xml');
72549 * }
72550 *
72551 * function setup() {
72552 * let firstChild = xml.getChild('animal');
72553 * print(firstChild.hasAttribute('species'));
72554 * print(firstChild.hasAttribute('color'));
72555 * }
72556 *
72557 * // Sketch prints:
72558 * // true
72559 * // false
72560 * </code></div>
72561 */
72562 _main.default.XML.prototype.hasAttribute = function(name) {
72563 var obj = {};
72564 var _iteratorNormalCompletion3 = true;
72565 var _didIteratorError3 = false;
72566 var _iteratorError3 = undefined;
72567 try {
72568 for (
72569 var _iterator3 = this.DOM.attributes[Symbol.iterator](), _step3;
72570 !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done);
72571 _iteratorNormalCompletion3 = true
72572 ) {
72573 var attribute = _step3.value;
72574 obj[attribute.nodeName] = attribute.nodeValue;
72575 }
72576 } catch (err) {
72577 _didIteratorError3 = true;
72578 _iteratorError3 = err;
72579 } finally {
72580 try {
72581 if (!_iteratorNormalCompletion3 && _iterator3.return != null) {
72582 _iterator3.return();
72583 }
72584 } finally {
72585 if (_didIteratorError3) {
72586 throw _iteratorError3;
72587 }
72588 }
72589 }
72590
72591 return obj[name] ? true : false;
72592 };
72593
72594 /**
72595 * Returns an attribute value of the element as an Number. If the defaultValue
72596 * parameter is specified and the attribute doesn't exist, then defaultValue
72597 * is returned. If no defaultValue is specified and the attribute doesn't
72598 * exist, the value 0 is returned.
72599 *
72600 * @method getNum
72601 * @param {String} name the non-null full name of the attribute
72602 * @param {Number} [defaultValue] the default value of the attribute
72603 * @return {Number}
72604 * @example
72605 * <div class='norender'><code>
72606 * // The following short XML file called "mammals.xml" is parsed
72607 * // in the code below.
72608 * //
72609 * // <?xml version="1.0"?>
72610 * // &lt;mammals&gt;
72611 * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
72612 * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
72613 * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
72614 * // &lt;/mammals&gt;
72615 *
72616 * let xml;
72617 *
72618 * function preload() {
72619 * xml = loadXML('assets/mammals.xml');
72620 * }
72621 *
72622 * function setup() {
72623 * let firstChild = xml.getChild('animal');
72624 * print(firstChild.getNum('id'));
72625 * }
72626 *
72627 * // Sketch prints:
72628 * // 0
72629 * </code></div>
72630 */
72631 _main.default.XML.prototype.getNum = function(name, defaultValue) {
72632 var obj = {};
72633 var _iteratorNormalCompletion4 = true;
72634 var _didIteratorError4 = false;
72635 var _iteratorError4 = undefined;
72636 try {
72637 for (
72638 var _iterator4 = this.DOM.attributes[Symbol.iterator](), _step4;
72639 !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done);
72640 _iteratorNormalCompletion4 = true
72641 ) {
72642 var attribute = _step4.value;
72643 obj[attribute.nodeName] = attribute.nodeValue;
72644 }
72645 } catch (err) {
72646 _didIteratorError4 = true;
72647 _iteratorError4 = err;
72648 } finally {
72649 try {
72650 if (!_iteratorNormalCompletion4 && _iterator4.return != null) {
72651 _iterator4.return();
72652 }
72653 } finally {
72654 if (_didIteratorError4) {
72655 throw _iteratorError4;
72656 }
72657 }
72658 }
72659
72660 return Number(obj[name]) || defaultValue || 0;
72661 };
72662
72663 /**
72664 * Returns an attribute value of the element as an String. If the defaultValue
72665 * parameter is specified and the attribute doesn't exist, then defaultValue
72666 * is returned. If no defaultValue is specified and the attribute doesn't
72667 * exist, null is returned.
72668 *
72669 * @method getString
72670 * @param {String} name the non-null full name of the attribute
72671 * @param {Number} [defaultValue] the default value of the attribute
72672 * @return {String}
72673 * @example
72674 * <div class='norender'><code>
72675 * // The following short XML file called "mammals.xml" is parsed
72676 * // in the code below.
72677 * //
72678 * // <?xml version="1.0"?>
72679 * // &lt;mammals&gt;
72680 * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
72681 * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
72682 * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
72683 * // &lt;/mammals&gt;
72684 *
72685 * let xml;
72686 *
72687 * function preload() {
72688 * xml = loadXML('assets/mammals.xml');
72689 * }
72690 *
72691 * function setup() {
72692 * let firstChild = xml.getChild('animal');
72693 * print(firstChild.getString('species'));
72694 * }
72695 *
72696 * // Sketch prints:
72697 * // "Capra hircus"
72698 * </code></div>
72699 */
72700 _main.default.XML.prototype.getString = function(name, defaultValue) {
72701 var obj = {};
72702 var _iteratorNormalCompletion5 = true;
72703 var _didIteratorError5 = false;
72704 var _iteratorError5 = undefined;
72705 try {
72706 for (
72707 var _iterator5 = this.DOM.attributes[Symbol.iterator](), _step5;
72708 !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done);
72709 _iteratorNormalCompletion5 = true
72710 ) {
72711 var attribute = _step5.value;
72712 obj[attribute.nodeName] = attribute.nodeValue;
72713 }
72714 } catch (err) {
72715 _didIteratorError5 = true;
72716 _iteratorError5 = err;
72717 } finally {
72718 try {
72719 if (!_iteratorNormalCompletion5 && _iterator5.return != null) {
72720 _iterator5.return();
72721 }
72722 } finally {
72723 if (_didIteratorError5) {
72724 throw _iteratorError5;
72725 }
72726 }
72727 }
72728
72729 return obj[name] ? String(obj[name]) : defaultValue || null;
72730 };
72731
72732 /**
72733 * Sets the content of an element's attribute. The first parameter specifies
72734 * the attribute name, while the second specifies the new content.
72735 *
72736 * @method setAttribute
72737 * @param {String} name the full name of the attribute
72738 * @param {Number|String|Boolean} value the value of the attribute
72739 * @example
72740 * <div class='norender'><code>
72741 * // The following short XML file called "mammals.xml" is parsed
72742 * // in the code below.
72743 * //
72744 * // <?xml version="1.0"?>
72745 * // &lt;mammals&gt;
72746 * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
72747 * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
72748 * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
72749 * // &lt;/mammals&gt;
72750 *
72751 * let xml;
72752 *
72753 * function preload() {
72754 * xml = loadXML('assets/mammals.xml');
72755 * }
72756 *
72757 * function setup() {
72758 * let firstChild = xml.getChild('animal');
72759 * print(firstChild.getString('species'));
72760 * firstChild.setAttribute('species', 'Jamides zebra');
72761 * print(firstChild.getString('species'));
72762 * }
72763 *
72764 * // Sketch prints:
72765 * // "Capra hircus"
72766 * // "Jamides zebra"
72767 * </code></div>
72768 */
72769 _main.default.XML.prototype.setAttribute = function(name, value) {
72770 this.DOM.setAttribute(name, value);
72771 };
72772
72773 /**
72774 * Returns the content of an element. If there is no such content,
72775 * defaultValue is returned if specified, otherwise null is returned.
72776 *
72777 * @method getContent
72778 * @param {String} [defaultValue] value returned if no content is found
72779 * @return {String}
72780 * @example
72781 * <div class='norender'><code>
72782 * // The following short XML file called "mammals.xml" is parsed
72783 * // in the code below.
72784 * //
72785 * // <?xml version="1.0"?>
72786 * // &lt;mammals&gt;
72787 * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
72788 * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
72789 * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
72790 * // &lt;/mammals&gt;
72791 *
72792 * let xml;
72793 *
72794 * function preload() {
72795 * xml = loadXML('assets/mammals.xml');
72796 * }
72797 *
72798 * function setup() {
72799 * let firstChild = xml.getChild('animal');
72800 * print(firstChild.getContent());
72801 * }
72802 *
72803 * // Sketch prints:
72804 * // "Goat"
72805 * </code></div>
72806 */
72807 _main.default.XML.prototype.getContent = function(defaultValue) {
72808 var str;
72809 str = this.DOM.textContent;
72810 str = str.replace(/\s\s+/g, ',');
72811 return str || defaultValue || null;
72812 };
72813
72814 /**
72815 * Sets the element's content.
72816 *
72817 * @method setContent
72818 * @param {String} text the new content
72819 * @example
72820 * <div class='norender'><code>
72821 * // The following short XML file called "mammals.xml" is parsed
72822 * // in the code below.
72823 * //
72824 * // <?xml version="1.0"?>
72825 * // &lt;mammals&gt;
72826 * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
72827 * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
72828 * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
72829 * // &lt;/mammals&gt;
72830 *
72831 * let xml;
72832 *
72833 * function preload() {
72834 * xml = loadXML('assets/mammals.xml');
72835 * }
72836 *
72837 * function setup() {
72838 * let firstChild = xml.getChild('animal');
72839 * print(firstChild.getContent());
72840 * firstChild.setContent('Mountain Goat');
72841 * print(firstChild.getContent());
72842 * }
72843 *
72844 * // Sketch prints:
72845 * // "Goat"
72846 * // "Mountain Goat"
72847 * </code></div>
72848 */
72849 _main.default.XML.prototype.setContent = function(content) {
72850 if (!this.DOM.children.length) {
72851 this.DOM.textContent = content;
72852 }
72853 };
72854
72855 /**
72856 * Serializes the element into a string. This function is useful for preparing
72857 * the content to be sent over a http request or saved to file.
72858 *
72859 * @method serialize
72860 * @return {String} Serialized string of the element
72861 * @example
72862 * <div class='norender'><code>
72863 * let xml;
72864 *
72865 * function preload() {
72866 * xml = loadXML('assets/mammals.xml');
72867 * }
72868 *
72869 * function setup() {
72870 * print(xml.serialize());
72871 * }
72872 *
72873 * // Sketch prints:
72874 * // <mammals>
72875 * // <animal id="0" species="Capra hircus">Goat</animal>
72876 * // <animal id="1" species="Panthera pardus">Leopard</animal>
72877 * // <animal id="2" species="Equus zebra">Zebra</animal>
72878 * // </mammals>
72879 * </code></div>
72880 */
72881 _main.default.XML.prototype.serialize = function() {
72882 var xmlSerializer = new XMLSerializer();
72883 return xmlSerializer.serializeToString(this.DOM);
72884 };
72885 var _default = _main.default;
72886 exports.default = _default;
72887 },
72888 { '../core/main': 54 }
72889 ],
72890 84: [
72891 function(_dereq_, module, exports) {
72892 'use strict';
72893 Object.defineProperty(exports, '__esModule', { value: true });
72894 exports.default = void 0;
72895
72896 var _main = _interopRequireDefault(_dereq_('../core/main'));
72897 function _interopRequireDefault(obj) {
72898 return obj && obj.__esModule ? obj : { default: obj };
72899 }
72900 /**
72901 * @module Math
72902 * @submodule Calculation
72903 * @for p5
72904 * @requires core
72905 */ /**
72906 * Calculates the absolute value (magnitude) of a number. Maps to Math.abs().
72907 * The absolute value of a number is always positive.
72908 *
72909 * @method abs
72910 * @param {Number} n number to compute
72911 * @return {Number} absolute value of given number
72912 * @example
72913 * <div class = "norender"><code>
72914 * function setup() {
72915 * let x = -3;
72916 * let y = abs(x);
72917 *
72918 * print(x); // -3
72919 * print(y); // 3
72920 * }
72921 * </code></div>
72922 *
72923 * @alt
72924 * no image displayed
72925 */ _main.default.prototype.abs = Math.abs; /**
72926 * Calculates the closest int value that is greater than or equal to the
72927 * value of the parameter. Maps to Math.ceil(). For example, ceil(9.03)
72928 * returns the value 10.
72929 *
72930 * @method ceil
72931 * @param {Number} n number to round up
72932 * @return {Integer} rounded up number
72933 * @example
72934 * <div><code>
72935 * function draw() {
72936 * background(200);
72937 * // map, mouseX between 0 and 5.
72938 * let ax = map(mouseX, 0, 100, 0, 5);
72939 * let ay = 66;
72940 *
72941 * //Get the ceiling of the mapped number.
72942 * let bx = ceil(map(mouseX, 0, 100, 0, 5));
72943 * let by = 33;
72944 *
72945 * // Multiply the mapped numbers by 20 to more easily
72946 * // see the changes.
72947 * stroke(0);
72948 * fill(0);
72949 * line(0, ay, ax * 20, ay);
72950 * line(0, by, bx * 20, by);
72951 *
72952 * // Reformat the float returned by map and draw it.
72953 * noStroke();
72954 * text(nfc(ax, 2), ax, ay - 5);
72955 * text(nfc(bx, 1), bx, by - 5);
72956 * }
72957 * </code></div>
72958 *
72959 * @alt
72960 * 2 horizontal lines & number sets. increase with mouse x. bottom to 2 decimals
72961 */
72962 _main.default.prototype.ceil = Math.ceil;
72963
72964 /**
72965 * Constrains a value between a minimum and maximum value.
72966 *
72967 * @method constrain
72968 * @param {Number} n number to constrain
72969 * @param {Number} low minimum limit
72970 * @param {Number} high maximum limit
72971 * @return {Number} constrained number
72972 * @example
72973 * <div><code>
72974 * function draw() {
72975 * background(200);
72976 *
72977 * let leftWall = 25;
72978 * let rightWall = 75;
72979 *
72980 * // xm is just the mouseX, while
72981 * // xc is the mouseX, but constrained
72982 * // between the leftWall and rightWall!
72983 * let xm = mouseX;
72984 * let xc = constrain(mouseX, leftWall, rightWall);
72985 *
72986 * // Draw the walls.
72987 * stroke(150);
72988 * line(leftWall, 0, leftWall, height);
72989 * line(rightWall, 0, rightWall, height);
72990 *
72991 * // Draw xm and xc as circles.
72992 * noStroke();
72993 * fill(150);
72994 * ellipse(xm, 33, 9, 9); // Not Constrained
72995 * fill(0);
72996 * ellipse(xc, 66, 9, 9); // Constrained
72997 * }
72998 * </code></div>
72999 *
73000 * @alt
73001 * 2 vertical lines. 2 ellipses move with mouse X 1 does not move passed lines
73002 */
73003 _main.default.prototype.constrain = function(n, low, high) {
73004 _main.default._validateParameters('constrain', arguments);
73005 return Math.max(Math.min(n, high), low);
73006 };
73007
73008 /**
73009 * Calculates the distance between two points, in either two or three dimensions.
73010 *
73011 * @method dist
73012 * @param {Number} x1 x-coordinate of the first point
73013 * @param {Number} y1 y-coordinate of the first point
73014 * @param {Number} x2 x-coordinate of the second point
73015 * @param {Number} y2 y-coordinate of the second point
73016 * @return {Number} distance between the two points
73017 *
73018 * @example
73019 * <div><code>
73020 * // Move your mouse inside the canvas to see the
73021 * // change in distance between two points!
73022 * function draw() {
73023 * background(200);
73024 * fill(0);
73025 *
73026 * let x1 = 10;
73027 * let y1 = 90;
73028 * let x2 = mouseX;
73029 * let y2 = mouseY;
73030 *
73031 * line(x1, y1, x2, y2);
73032 * ellipse(x1, y1, 7, 7);
73033 * ellipse(x2, y2, 7, 7);
73034 *
73035 * // d is the length of the line
73036 * // the distance from point 1 to point 2.
73037 * let d = int(dist(x1, y1, x2, y2));
73038 *
73039 * // Let's write d along the line we are drawing!
73040 * push();
73041 * translate((x1 + x2) / 2, (y1 + y2) / 2);
73042 * rotate(atan2(y2 - y1, x2 - x1));
73043 * text(nfc(d, 1), 0, -5);
73044 * pop();
73045 * // Fancy!
73046 * }
73047 * </code></div>
73048 *
73049 * @alt
73050 * 2 ellipses joined by line. 1 ellipse moves with mouse X&Y. Distance displayed.
73051 */
73052 /**
73053 * @method dist
73054 * @param {Number} x1
73055 * @param {Number} y1
73056 * @param {Number} z1 z-coordinate of the first point
73057 * @param {Number} x2
73058 * @param {Number} y2
73059 * @param {Number} z2 z-coordinate of the second point
73060 * @return {Number} distance between the two points
73061 */
73062 _main.default.prototype.dist = function() {
73063 for (
73064 var _len = arguments.length, args = new Array(_len), _key = 0;
73065 _key < _len;
73066 _key++
73067 ) {
73068 args[_key] = arguments[_key];
73069 }
73070 _main.default._validateParameters('dist', args);
73071 if (args.length === 4) {
73072 //2D
73073 return hypot(args[2] - args[0], args[3] - args[1]);
73074 } else if (args.length === 6) {
73075 //3D
73076 return hypot(args[3] - args[0], args[4] - args[1], args[5] - args[2]);
73077 }
73078 };
73079
73080 /**
73081 * Returns Euler's number e (2.71828...) raised to the power of the n
73082 * parameter. Maps to Math.exp().
73083 *
73084 * @method exp
73085 * @param {Number} n exponent to raise
73086 * @return {Number} e^n
73087 * @example
73088 * <div><code>
73089 * function draw() {
73090 * background(200);
73091 *
73092 * // Compute the exp() function with a value between 0 and 2
73093 * let xValue = map(mouseX, 0, width, 0, 2);
73094 * let yValue = exp(xValue);
73095 *
73096 * let y = map(yValue, 0, 8, height, 0);
73097 *
73098 * let legend = 'exp (' + nfc(xValue, 3) + ')\n= ' + nf(yValue, 1, 4);
73099 * stroke(150);
73100 * line(mouseX, y, mouseX, height);
73101 * fill(0);
73102 * text(legend, 5, 15);
73103 * noStroke();
73104 * ellipse(mouseX, y, 7, 7);
73105 *
73106 * // Draw the exp(x) curve,
73107 * // over the domain of x from 0 to 2
73108 * noFill();
73109 * stroke(0);
73110 * beginShape();
73111 * for (let x = 0; x < width; x++) {
73112 * xValue = map(x, 0, width, 0, 2);
73113 * yValue = exp(xValue);
73114 * y = map(yValue, 0, 8, height, 0);
73115 * vertex(x, y);
73116 * }
73117 *
73118 * endShape();
73119 * line(0, 0, 0, height);
73120 * line(0, height - 1, width, height - 1);
73121 * }
73122 * </code></div>
73123 *
73124 * @alt
73125 * ellipse moves along a curve with mouse x. e^n displayed.
73126 */
73127 _main.default.prototype.exp = Math.exp;
73128
73129 /**
73130 * Calculates the closest int value that is less than or equal to the
73131 * value of the parameter. Maps to Math.floor().
73132 *
73133 * @method floor
73134 * @param {Number} n number to round down
73135 * @return {Integer} rounded down number
73136 * @example
73137 * <div><code>
73138 * function draw() {
73139 * background(200);
73140 * //map, mouseX between 0 and 5.
73141 * let ax = map(mouseX, 0, 100, 0, 5);
73142 * let ay = 66;
73143 *
73144 * //Get the floor of the mapped number.
73145 * let bx = floor(map(mouseX, 0, 100, 0, 5));
73146 * let by = 33;
73147 *
73148 * // Multiply the mapped numbers by 20 to more easily
73149 * // see the changes.
73150 * stroke(0);
73151 * fill(0);
73152 * line(0, ay, ax * 20, ay);
73153 * line(0, by, bx * 20, by);
73154 *
73155 * // Reformat the float returned by map and draw it.
73156 * noStroke();
73157 * text(nfc(ax, 2), ax, ay - 5);
73158 * text(nfc(bx, 1), bx, by - 5);
73159 * }
73160 * </code></div>
73161 *
73162 * @alt
73163 * 2 horizontal lines & number sets. increase with mouse x. bottom to 2 decimals
73164 */
73165 _main.default.prototype.floor = Math.floor;
73166
73167 /**
73168 * Calculates a number between two numbers at a specific increment. The amt
73169 * parameter is the amount to interpolate between the two values where 0.0
73170 * equal to the first point, 0.1 is very near the first point, 0.5 is
73171 * half-way in between, and 1.0 is equal to the second point. If the
73172 * value of amt is more than 1.0 or less than 0.0, the number will be
73173 * calculated accordingly in the ratio of the two given numbers. The lerp
73174 * function is convenient for creating motion along a straight
73175 * path and for drawing dotted lines.
73176 *
73177 * @method lerp
73178 * @param {Number} start first value
73179 * @param {Number} stop second value
73180 * @param {Number} amt number
73181 * @return {Number} lerped value
73182 * @example
73183 * <div><code>
73184 * function setup() {
73185 * background(200);
73186 * let a = 20;
73187 * let b = 80;
73188 * let c = lerp(a, b, 0.2);
73189 * let d = lerp(a, b, 0.5);
73190 * let e = lerp(a, b, 0.8);
73191 *
73192 * let y = 50;
73193 *
73194 * strokeWeight(5);
73195 * stroke(0); // Draw the original points in black
73196 * point(a, y);
73197 * point(b, y);
73198 *
73199 * stroke(100); // Draw the lerp points in gray
73200 * point(c, y);
73201 * point(d, y);
73202 * point(e, y);
73203 * }
73204 * </code></div>
73205 *
73206 * @alt
73207 * 5 points horizontally staggered mid-canvas. mid 3 are grey, outer black
73208 */
73209 _main.default.prototype.lerp = function(start, stop, amt) {
73210 _main.default._validateParameters('lerp', arguments);
73211 return amt * (stop - start) + start;
73212 };
73213
73214 /**
73215 * Calculates the natural logarithm (the base-e logarithm) of a number. This
73216 * function expects the n parameter to be a value greater than 0.0. Maps to
73217 * Math.log().
73218 *
73219 * @method log
73220 * @param {Number} n number greater than 0
73221 * @return {Number} natural logarithm of n
73222 * @example
73223 * <div><code>
73224 * function draw() {
73225 * background(200);
73226 * let maxX = 2.8;
73227 * let maxY = 1.5;
73228 *
73229 * // Compute the natural log of a value between 0 and maxX
73230 * let xValue = map(mouseX, 0, width, 0, maxX);
73231 * let yValue, y;
73232 * if (xValue > 0) {
73233 // Cannot take the log of a negative number.
73234 * yValue = log(xValue);
73235 * y = map(yValue, -maxY, maxY, height, 0);
73236 *
73237 * // Display the calculation occurring.
73238 * let legend = 'log(' + nf(xValue, 1, 2) + ')\n= ' + nf(yValue, 1, 3);
73239 * stroke(150);
73240 * line(mouseX, y, mouseX, height);
73241 * fill(0);
73242 * text(legend, 5, 15);
73243 * noStroke();
73244 * ellipse(mouseX, y, 7, 7);
73245 * }
73246 *
73247 * // Draw the log(x) curve,
73248 * // over the domain of x from 0 to maxX
73249 * noFill();
73250 * stroke(0);
73251 * beginShape();
73252 * for (let x = 0; x < width; x++) {
73253 * xValue = map(x, 0, width, 0, maxX);
73254 * yValue = log(xValue);
73255 * y = map(yValue, -maxY, maxY, height, 0);
73256 * vertex(x, y);
73257 * }
73258 * endShape();
73259 * line(0, 0, 0, height);
73260 * line(0, height / 2, width, height / 2);
73261 * }
73262 * </code></div>
73263 *
73264 * @alt
73265 * ellipse moves along a curve with mouse x. natural logarithm of n displayed.
73266 */
73267 _main.default.prototype.log = Math.log;
73268
73269 /**
73270 * Calculates the magnitude (or length) of a vector. A vector is a direction
73271 * in space commonly used in computer graphics and linear algebra. Because it
73272 * has no "start" position, the magnitude of a vector can be thought of as
73273 * the distance from the coordinate 0,0 to its x,y value. Therefore, <a href="#/p5/mag">mag()</a> is
73274 * a shortcut for writing dist(0, 0, x, y).
73275 *
73276 * @method mag
73277 * @param {Number} a first value
73278 * @param {Number} b second value
73279 * @return {Number} magnitude of vector from (0,0) to (a,b)
73280 * @example
73281 * <div><code>
73282 * function setup() {
73283 * let x1 = 20;
73284 * let x2 = 80;
73285 * let y1 = 30;
73286 * let y2 = 70;
73287 *
73288 * line(0, 0, x1, y1);
73289 * print(mag(x1, y1)); // Prints "36.05551275463989"
73290 * line(0, 0, x2, y1);
73291 * print(mag(x2, y1)); // Prints "85.44003745317531"
73292 * line(0, 0, x1, y2);
73293 * print(mag(x1, y2)); // Prints "72.80109889280519"
73294 * line(0, 0, x2, y2);
73295 * print(mag(x2, y2)); // Prints "106.3014581273465"
73296 * }
73297 * </code></div>
73298 *
73299 * @alt
73300 * 4 lines of different length radiate from top left of canvas.
73301 */
73302 _main.default.prototype.mag = function(x, y) {
73303 _main.default._validateParameters('mag', arguments);
73304 return hypot(x, y);
73305 };
73306
73307 /**
73308 * Re-maps a number from one range to another.
73309 *
73310 * In the first example above, the number 25 is converted from a value in the
73311 * range of 0 to 100 into a value that ranges from the left edge of the
73312 * window (0) to the right edge (width).
73313 *
73314 * @method map
73315 * @param {Number} value the incoming value to be converted
73316 * @param {Number} start1 lower bound of the value's current range
73317 * @param {Number} stop1 upper bound of the value's current range
73318 * @param {Number} start2 lower bound of the value's target range
73319 * @param {Number} stop2 upper bound of the value's target range
73320 * @param {Boolean} [withinBounds] constrain the value to the newly mapped range
73321 * @return {Number} remapped number
73322 * @example
73323 * <div><code>
73324 * let value = 25;
73325 * let m = map(value, 0, 100, 0, width);
73326 * ellipse(m, 50, 10, 10);
73327 </code></div>
73328 *
73329 * <div><code>
73330 * function setup() {
73331 * noStroke();
73332 * }
73333 *
73334 * function draw() {
73335 * background(204);
73336 * let x1 = map(mouseX, 0, width, 25, 75);
73337 * ellipse(x1, 25, 25, 25);
73338 * //This ellipse is constrained to the 0-100 range
73339 * //after setting withinBounds to true
73340 * let x2 = map(mouseX, 0, width, 0, 100, true);
73341 * ellipse(x2, 75, 25, 25);
73342 * }
73343 </code></div>
73344 *
73345 * @alt
73346 * 10 by 10 white ellipse with in mid left canvas
73347 * 2 25 by 25 white ellipses move with mouse x. Bottom has more range from X
73348 */
73349 _main.default.prototype.map = function(
73350 n,
73351 start1,
73352 stop1,
73353 start2,
73354 stop2,
73355 withinBounds
73356 ) {
73357 _main.default._validateParameters('map', arguments);
73358 var newval = (n - start1) / (stop1 - start1) * (stop2 - start2) + start2;
73359 if (!withinBounds) {
73360 return newval;
73361 }
73362 if (start2 < stop2) {
73363 return this.constrain(newval, start2, stop2);
73364 } else {
73365 return this.constrain(newval, stop2, start2);
73366 }
73367 };
73368
73369 /**
73370 * Determines the largest value in a sequence of numbers, and then returns
73371 * that value. <a href="#/p5/max">max()</a> accepts any number of Number parameters, or an Array
73372 * of any length.
73373 *
73374 * @method max
73375 * @param {Number} n0 Number to compare
73376 * @param {Number} n1 Number to compare
73377 * @return {Number} maximum Number
73378 * @example
73379 * <div><code>
73380 * function setup() {
73381 * // Change the elements in the array and run the sketch
73382 * // to show how max() works!
73383 * let numArray = [2, 1, 5, 4, 8, 9];
73384 * fill(0);
73385 * noStroke();
73386 * text('Array Elements', 0, 10);
73387 * // Draw all numbers in the array
73388 * let spacing = 15;
73389 * let elemsY = 25;
73390 * for (let i = 0; i < numArray.length; i++) {
73391 * text(numArray[i], i * spacing, elemsY);
73392 * }
73393 * let maxX = 33;
73394 * let maxY = 80;
73395 * // Draw the Maximum value in the array.
73396 * textSize(32);
73397 * text(max(numArray), maxX, maxY);
73398 * }
73399 * </code></div>
73400 *
73401 * @alt
73402 * Small text at top reads: Array Elements 2 1 5 4 8 9. Large text at center: 9
73403 */
73404 /**
73405 * @method max
73406 * @param {Number[]} nums Numbers to compare
73407 * @return {Number}
73408 */
73409 _main.default.prototype.max = function() {
73410 for (
73411 var _len2 = arguments.length, args = new Array(_len2), _key2 = 0;
73412 _key2 < _len2;
73413 _key2++
73414 ) {
73415 args[_key2] = arguments[_key2];
73416 }
73417 _main.default._validateParameters('max', args);
73418 if (args[0] instanceof Array) {
73419 return Math.max.apply(null, args[0]);
73420 } else {
73421 return Math.max.apply(null, args);
73422 }
73423 };
73424
73425 /**
73426 * Determines the smallest value in a sequence of numbers, and then returns
73427 * that value. <a href="#/p5/min">min()</a> accepts any number of Number parameters, or an Array
73428 * of any length.
73429 *
73430 * @method min
73431 * @param {Number} n0 Number to compare
73432 * @param {Number} n1 Number to compare
73433 * @return {Number} minimum Number
73434 * @example
73435 * <div><code>
73436 * function setup() {
73437 * // Change the elements in the array and run the sketch
73438 * // to show how min() works!
73439 * let numArray = [2, 1, 5, 4, 8, 9];
73440 * fill(0);
73441 * noStroke();
73442 * text('Array Elements', 0, 10);
73443 * // Draw all numbers in the array
73444 * let spacing = 15;
73445 * let elemsY = 25;
73446 * for (let i = 0; i < numArray.length; i++) {
73447 * text(numArray[i], i * spacing, elemsY);
73448 * }
73449 * let maxX = 33;
73450 * let maxY = 80;
73451 * // Draw the Minimum value in the array.
73452 * textSize(32);
73453 * text(min(numArray), maxX, maxY);
73454 * }
73455 * </code></div>
73456 *
73457 * @alt
73458 * Small text at top reads: Array Elements 2 1 5 4 8 9. Large text at center: 1
73459 */
73460 /**
73461 * @method min
73462 * @param {Number[]} nums Numbers to compare
73463 * @return {Number}
73464 */
73465 _main.default.prototype.min = function() {
73466 for (
73467 var _len3 = arguments.length, args = new Array(_len3), _key3 = 0;
73468 _key3 < _len3;
73469 _key3++
73470 ) {
73471 args[_key3] = arguments[_key3];
73472 }
73473 _main.default._validateParameters('min', args);
73474 if (args[0] instanceof Array) {
73475 return Math.min.apply(null, args[0]);
73476 } else {
73477 return Math.min.apply(null, args);
73478 }
73479 };
73480
73481 /**
73482 * Normalizes a number from another range into a value between 0 and 1.
73483 * Identical to map(value, low, high, 0, 1).
73484 * Numbers outside of the range are not clamped to 0 and 1, because
73485 * out-of-range values are often intentional and useful. (See the example above.)
73486 *
73487 * @method norm
73488 * @param {Number} value incoming value to be normalized
73489 * @param {Number} start lower bound of the value's current range
73490 * @param {Number} stop upper bound of the value's current range
73491 * @return {Number} normalized number
73492 * @example
73493 * <div><code>
73494 * function draw() {
73495 * background(200);
73496 * let currentNum = mouseX;
73497 * let lowerBound = 0;
73498 * let upperBound = width; //100;
73499 * let normalized = norm(currentNum, lowerBound, upperBound);
73500 * let lineY = 70;
73501 * stroke(3);
73502 * line(0, lineY, width, lineY);
73503 * //Draw an ellipse mapped to the non-normalized value.
73504 * noStroke();
73505 * fill(50);
73506 * let s = 7; // ellipse size
73507 * ellipse(currentNum, lineY, s, s);
73508 *
73509 * // Draw the guide
73510 * let guideY = lineY + 15;
73511 * text('0', 0, guideY);
73512 * textAlign(RIGHT);
73513 * text('100', width, guideY);
73514 *
73515 * // Draw the normalized value
73516 * textAlign(LEFT);
73517 * fill(0);
73518 * textSize(32);
73519 * let normalY = 40;
73520 * let normalX = 20;
73521 * text(normalized, normalX, normalY);
73522 * }
73523 * </code></div>
73524 *
73525 * @alt
73526 * ellipse moves with mouse. 0 shown left & 100 right and updating values center
73527 */
73528 _main.default.prototype.norm = function(n, start, stop) {
73529 _main.default._validateParameters('norm', arguments);
73530 return this.map(n, start, stop, 0, 1);
73531 };
73532
73533 /**
73534 * Facilitates exponential expressions. The <a href="#/p5/pow">pow()</a> function is an efficient
73535 * way of multiplying numbers by themselves (or their reciprocals) in large
73536 * quantities. For example, pow(3, 5) is equivalent to the expression
73537 * 3 &times; 3 &times; 3 &times; 3 &times; 3 and pow(3, -5) is equivalent to 1 /
73538 * 3 &times; 3 &times; 3 &times; 3 &times; 3. Maps to
73539 * Math.pow().
73540 *
73541 * @method pow
73542 * @param {Number} n base of the exponential expression
73543 * @param {Number} e power by which to raise the base
73544 * @return {Number} n^e
73545 * @example
73546 * <div><code>
73547 * function setup() {
73548 * //Exponentially increase the size of an ellipse.
73549 * let eSize = 3; // Original Size
73550 * let eLoc = 10; // Original Location
73551 *
73552 * ellipse(eLoc, eLoc, eSize, eSize);
73553 *
73554 * ellipse(eLoc * 2, eLoc * 2, pow(eSize, 2), pow(eSize, 2));
73555 *
73556 * ellipse(eLoc * 4, eLoc * 4, pow(eSize, 3), pow(eSize, 3));
73557 *
73558 * ellipse(eLoc * 8, eLoc * 8, pow(eSize, 4), pow(eSize, 4));
73559 * }
73560 * </code></div>
73561 *
73562 * @alt
73563 * small to large ellipses radiating from top left of canvas
73564 */
73565 _main.default.prototype.pow = Math.pow;
73566
73567 /**
73568 * Calculates the integer closest to the n parameter. For example,
73569 * round(133.8) returns the value 134. Maps to Math.round().
73570 *
73571 * @method round
73572 * @param {Number} n number to round
73573 * @param {Number} [decimals] number of decimal places to round to, default is 0
73574 * @return {Integer} rounded number
73575 * @example
73576 * <div><code>
73577 * let x = round(3.7);
73578 * text(x, width / 2, height / 2);
73579 * </code></div>
73580 * <div><code>
73581 * let x = round(12.782383, 2);
73582 * text(x, width / 2, height / 2);
73583 * </code></div>
73584 * <div><code>
73585 * function draw() {
73586 * background(200);
73587 * //map, mouseX between 0 and 5.
73588 * let ax = map(mouseX, 0, 100, 0, 5);
73589 * let ay = 66;
73590 *
73591 * // Round the mapped number.
73592 * let bx = round(map(mouseX, 0, 100, 0, 5));
73593 * let by = 33;
73594 *
73595 * // Multiply the mapped numbers by 20 to more easily
73596 * // see the changes.
73597 * stroke(0);
73598 * fill(0);
73599 * line(0, ay, ax * 20, ay);
73600 * line(0, by, bx * 20, by);
73601 *
73602 * // Reformat the float returned by map and draw it.
73603 * noStroke();
73604 * text(nfc(ax, 2), ax, ay - 5);
73605 * text(nfc(bx, 1), bx, by - 5);
73606 * }
73607 * </code></div>
73608 *
73609 * @alt
73610 * "3" written in middle of canvas
73611 * "12.78" written in middle of canvas
73612 * horizontal center line squared values displayed on top and regular on bottom.
73613 */
73614 _main.default.prototype.round = function(n, decimals) {
73615 if (!decimals) {
73616 return Math.round(n);
73617 }
73618 return Number(Math.round(n + 'e' + decimals) + 'e-' + decimals);
73619 };
73620
73621 /**
73622 * Squares a number (multiplies a number by itself). The result is always a
73623 * positive number, as multiplying two negative numbers always yields a
73624 * positive result. For example, -1 * -1 = 1.
73625 *
73626 * @method sq
73627 * @param {Number} n number to square
73628 * @return {Number} squared number
73629 * @example
73630 * <div><code>
73631 * function draw() {
73632 * background(200);
73633 * let eSize = 7;
73634 * let x1 = map(mouseX, 0, width, 0, 10);
73635 * let y1 = 80;
73636 * let x2 = sq(x1);
73637 * let y2 = 20;
73638 *
73639 * // Draw the non-squared.
73640 * line(0, y1, width, y1);
73641 * ellipse(x1, y1, eSize, eSize);
73642 *
73643 * // Draw the squared.
73644 * line(0, y2, width, y2);
73645 * ellipse(x2, y2, eSize, eSize);
73646 *
73647 * // Draw dividing line.
73648 * stroke(100);
73649 * line(0, height / 2, width, height / 2);
73650 *
73651 * // Draw text.
73652 * let spacing = 15;
73653 * noStroke();
73654 * fill(0);
73655 * text('x = ' + x1, 0, y1 + spacing);
73656 * text('sq(x) = ' + x2, 0, y2 + spacing);
73657 * }
73658 * </code></div>
73659 *
73660 * @alt
73661 * horizontal center line squared values displayed on top and regular on bottom.
73662 */
73663 _main.default.prototype.sq = function(n) {
73664 return n * n;
73665 };
73666
73667 /**
73668 * Calculates the square root of a number. The square root of a number is
73669 * always positive, even though there may be a valid negative root. The
73670 * square root s of number a is such that s*s = a. It is the opposite of
73671 * squaring. Maps to Math.sqrt().
73672 *
73673 * @method sqrt
73674 * @param {Number} n non-negative number to square root
73675 * @return {Number} square root of number
73676 * @example
73677 * <div><code>
73678 * function draw() {
73679 * background(200);
73680 * let eSize = 7;
73681 * let x1 = mouseX;
73682 * let y1 = 80;
73683 * let x2 = sqrt(x1);
73684 * let y2 = 20;
73685 *
73686 * // Draw the non-squared.
73687 * line(0, y1, width, y1);
73688 * ellipse(x1, y1, eSize, eSize);
73689 *
73690 * // Draw the squared.
73691 * line(0, y2, width, y2);
73692 * ellipse(x2, y2, eSize, eSize);
73693 *
73694 * // Draw dividing line.
73695 * stroke(100);
73696 * line(0, height / 2, width, height / 2);
73697 *
73698 * // Draw text.
73699 * noStroke();
73700 * fill(0);
73701 * let spacing = 15;
73702 * text('x = ' + x1, 0, y1 + spacing);
73703 * text('sqrt(x) = ' + x2, 0, y2 + spacing);
73704 * }
73705 * </code></div>
73706 *
73707 * @alt
73708 * horizontal center line squareroot values displayed on top and regular on bottom.
73709 */
73710 _main.default.prototype.sqrt = Math.sqrt;
73711
73712 // Calculate the length of the hypotenuse of a right triangle
73713 // This won't under- or overflow in intermediate steps
73714 // https://en.wikipedia.org/wiki/Hypot
73715 function hypot(x, y, z) {
73716 // Use the native implementation if it's available
73717 if (typeof Math.hypot === 'function') {
73718 return Math.hypot.apply(null, arguments);
73719 }
73720
73721 // Otherwise use the V8 implementation
73722 // https://github.com/v8/v8/blob/8cd3cf297287e581a49e487067f5cbd991b27123/src/js/math.js#L217
73723 var length = arguments.length;
73724 var args = [];
73725 var max = 0;
73726 for (var i = 0; i < length; i++) {
73727 var n = arguments[i];
73728 n = +n;
73729 if (n === Infinity || n === -Infinity) {
73730 return Infinity;
73731 }
73732 n = Math.abs(n);
73733 if (n > max) {
73734 max = n;
73735 }
73736 args[i] = n;
73737 }
73738
73739 if (max === 0) {
73740 max = 1;
73741 }
73742 var sum = 0;
73743 var compensation = 0;
73744 for (var j = 0; j < length; j++) {
73745 var m = args[j] / max;
73746 var summand = m * m - compensation;
73747 var preliminary = sum + summand;
73748 compensation = preliminary - sum - summand;
73749 sum = preliminary;
73750 }
73751 return Math.sqrt(sum) * max;
73752 }
73753
73754 /**
73755 * Calculates the fractional part of a number.
73756 *
73757 * @method fract
73758 * @param {Number} num Number whose fractional part needs to be found out
73759 * @returns {Number} fractional part of x, i.e, {x}
73760 * @example
73761 * <div>
73762 * <code>
73763 * function setup() {
73764 * createCanvas(windowWidth, windowHeight);
73765 * fill(0);
73766 * text(7345.73472742, 0, 50);
73767 * text(fract(7345.73472742), 0, 100);
73768 * text(1.4215e-15, 150, 50);
73769 * text(fract(1.4215e-15), 150, 100);
73770 * }
73771 * </code>
73772 * </div>
73773 * @alt
73774 * 2 rows of numbers, the first row having 8 numbers and the second having the fractional parts of those numbers.
73775 */
73776 _main.default.prototype.fract = function(toConvert) {
73777 _main.default._validateParameters('fract', arguments);
73778 var sign = 0;
73779 var num = Number(toConvert);
73780 if (isNaN(num) || Math.abs(num) === Infinity) {
73781 return num;
73782 } else if (num < 0) {
73783 num = -num;
73784 sign = 1;
73785 }
73786 if (String(num).includes('.') && !String(num).includes('e')) {
73787 var toFract = String(num);
73788 toFract = Number('0' + toFract.slice(toFract.indexOf('.')));
73789 return Math.abs(sign - toFract);
73790 } else if (num < 1) {
73791 return Math.abs(sign - num);
73792 } else {
73793 return 0;
73794 }
73795 };
73796 var _default = _main.default;
73797 exports.default = _default;
73798 },
73799 { '../core/main': 54 }
73800 ],
73801 85: [
73802 function(_dereq_, module, exports) {
73803 'use strict';
73804 Object.defineProperty(exports, '__esModule', { value: true });
73805 exports.default = void 0;
73806
73807 var _main = _interopRequireDefault(_dereq_('../core/main'));
73808 function _interopRequireDefault(obj) {
73809 return obj && obj.__esModule ? obj : { default: obj };
73810 }
73811 /**
73812 * @module Math
73813 * @submodule Vector
73814 * @for p5
73815 * @requires core
73816 */ /**
73817 * Creates a new <a href="#/p5.Vector">p5.Vector</a> (the datatype for storing vectors). This provides a
73818 * two or three dimensional vector, specifically a Euclidean (also known as
73819 * geometric) vector. A vector is an entity that has both magnitude and
73820 * direction.
73821 *
73822 * @method createVector
73823 * @param {Number} [x] x component of the vector
73824 * @param {Number} [y] y component of the vector
73825 * @param {Number} [z] z component of the vector
73826 * @return {p5.Vector}
73827 * @example
73828 * <div><code>
73829 * let v1;
73830 * function setup() {
73831 * createCanvas(100, 100);
73832 * stroke(255, 0, 255);
73833 * v1 = createVector(width / 2, height / 2);
73834 * }
73835 *
73836 * function draw() {
73837 * background(255);
73838 * line(v1.x, v1.y, mouseX, mouseY);
73839 * }
73840 * </code></div>
73841 *
73842 * @alt
73843 * draws a line from center of canvas to mouse pointer position.
73844 */ _main.default.prototype.createVector = function(x, y, z) {
73845 if (this instanceof _main.default) {
73846 return new _main.default.Vector(this, arguments);
73847 } else {
73848 return new _main.default.Vector(x, y, z);
73849 }
73850 };
73851 var _default = _main.default;
73852 exports.default = _default;
73853 },
73854 { '../core/main': 54 }
73855 ],
73856 86: [
73857 function(_dereq_, module, exports) {
73858 'use strict';
73859 Object.defineProperty(exports, '__esModule', { value: true });
73860 exports.default = void 0;
73861
73862 var _main = _interopRequireDefault(_dereq_('../core/main'));
73863 function _interopRequireDefault(obj) {
73864 return obj && obj.__esModule ? obj : { default: obj };
73865 } //////////////////////////////////////////////////////////////
73866 // http://mrl.nyu.edu/~perlin/noise/
73867 // Adapting from PApplet.java
73868 // which was adapted from toxi
73869 // which was adapted from the german demo group farbrausch
73870 // as used in their demo "art": http://www.farb-rausch.de/fr010src.zip
73871 // someday we might consider using "improved noise"
73872 // http://mrl.nyu.edu/~perlin/paper445.pdf
73873 // See: https://github.com/shiffman/The-Nature-of-Code-Examples-p5.js/
73874 // blob/main/introduction/Noise1D/noise.js
73875 /**
73876 * @module Math
73877 * @submodule Noise
73878 * @for p5
73879 * @requires core
73880 */ var PERLIN_YWRAPB = 4;
73881 var PERLIN_YWRAP = 1 << PERLIN_YWRAPB;
73882 var PERLIN_ZWRAPB = 8;
73883 var PERLIN_ZWRAP = 1 << PERLIN_ZWRAPB;
73884 var PERLIN_SIZE = 4095;
73885 var perlin_octaves = 4; // default to medium smooth
73886 var perlin_amp_falloff = 0.5; // 50% reduction/octave
73887 var scaled_cosine = function scaled_cosine(i) {
73888 return 0.5 * (1.0 - Math.cos(i * Math.PI));
73889 };
73890 var perlin; // will be initialized lazily by noise() or noiseSeed()
73891 /**
73892 * Returns the Perlin noise value at specified coordinates. Perlin noise is
73893 * a random sequence generator producing a more naturally ordered, harmonic
73894 * succession of numbers compared to the standard <b>random()</b> function.
73895 * It was invented by Ken Perlin in the 1980s and been used since in
73896 * graphical applications to produce procedural textures, natural motion,
73897 * shapes, terrains etc.<br /><br /> The main difference to the
73898 * <b>random()</b> function is that Perlin noise is defined in an infinite
73899 * n-dimensional space where each pair of coordinates corresponds to a
73900 * fixed semi-random value (fixed only for the lifespan of the program; see
73901 * the <a href="#/p5/noiseSeed">noiseSeed()</a> function). p5.js can compute 1D, 2D and 3D noise,
73902 * depending on the number of coordinates given. The resulting value will
73903 * always be between 0.0 and 1.0. The noise value can be animated by moving
73904 * through the noise space as demonstrated in the example above. The 2nd
73905 * and 3rd dimension can also be interpreted as time.<br /><br />The actual
73906 * noise is structured similar to an audio signal, in respect to the
73907 * function's use of frequencies. Similar to the concept of harmonics in
73908 * physics, perlin noise is computed over several octaves which are added
73909 * together for the final result. <br /><br />Another way to adjust the
73910 * character of the resulting sequence is the scale of the input
73911 * coordinates. As the function works within an infinite space the value of
73912 * the coordinates doesn't matter as such, only the distance between
73913 * successive coordinates does (eg. when using <b>noise()</b> within a
73914 * loop). As a general rule the smaller the difference between coordinates,
73915 * the smoother the resulting noise sequence will be. Steps of 0.005-0.03
73916 * work best for most applications, but this will differ depending on use.
73917 *
73918 * @method noise
73919 * @param {Number} x x-coordinate in noise space
73920 * @param {Number} [y] y-coordinate in noise space
73921 * @param {Number} [z] z-coordinate in noise space
73922 * @return {Number} Perlin noise value (between 0 and 1) at specified
73923 * coordinates
73924 * @example
73925 * <div>
73926 * <code>
73927 * let xoff = 0.0;
73928 *
73929 * function draw() {
73930 * background(204);
73931 * xoff = xoff + 0.01;
73932 * let n = noise(xoff) * width;
73933 * line(n, 0, n, height);
73934 * }
73935 * </code>
73936 * </div>
73937 * <div>
73938 * <code>let noiseScale=0.02;
73939 *
73940 * function draw() {
73941 * background(0);
73942 * for (let x=0; x < width; x++) {
73943 * let noiseVal = noise((mouseX+x)*noiseScale, mouseY*noiseScale);
73944 * stroke(noiseVal*255);
73945 * line(x, mouseY+noiseVal*80, x, height);
73946 * }
73947 * }
73948 * </code>
73949 * </div>
73950 *
73951 * @alt
73952 * vertical line moves left to right with updating noise values.
73953 * horizontal wave pattern effected by mouse x-position & updating noise values.
73954 */ _main.default.prototype.noise = function(x) {
73955 var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
73956 var z = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
73957 if (perlin == null) {
73958 perlin = new Array(PERLIN_SIZE + 1);
73959 for (var i = 0; i < PERLIN_SIZE + 1; i++) {
73960 perlin[i] = Math.random();
73961 }
73962 }
73963
73964 if (x < 0) {
73965 x = -x;
73966 }
73967 if (y < 0) {
73968 y = -y;
73969 }
73970 if (z < 0) {
73971 z = -z;
73972 }
73973
73974 var xi = Math.floor(x),
73975 yi = Math.floor(y),
73976 zi = Math.floor(z);
73977 var xf = x - xi;
73978 var yf = y - yi;
73979 var zf = z - zi;
73980 var rxf, ryf;
73981
73982 var r = 0;
73983 var ampl = 0.5;
73984
73985 var n1, n2, n3;
73986
73987 for (var o = 0; o < perlin_octaves; o++) {
73988 var of = xi + (yi << PERLIN_YWRAPB) + (zi << PERLIN_ZWRAPB);
73989
73990 rxf = scaled_cosine(xf);
73991 ryf = scaled_cosine(yf);
73992
73993 n1 = perlin[of & PERLIN_SIZE];
73994 n1 += rxf * (perlin[(of + 1) & PERLIN_SIZE] - n1);
73995 n2 = perlin[(of + PERLIN_YWRAP) & PERLIN_SIZE];
73996 n2 += rxf * (perlin[(of + PERLIN_YWRAP + 1) & PERLIN_SIZE] - n2);
73997 n1 += ryf * (n2 - n1);
73998
73999 of += PERLIN_ZWRAP;
74000 n2 = perlin[of & PERLIN_SIZE];
74001 n2 += rxf * (perlin[(of + 1) & PERLIN_SIZE] - n2);
74002 n3 = perlin[(of + PERLIN_YWRAP) & PERLIN_SIZE];
74003 n3 += rxf * (perlin[(of + PERLIN_YWRAP + 1) & PERLIN_SIZE] - n3);
74004 n2 += ryf * (n3 - n2);
74005
74006 n1 += scaled_cosine(zf) * (n2 - n1);
74007
74008 r += n1 * ampl;
74009 ampl *= perlin_amp_falloff;
74010 xi <<= 1;
74011 xf *= 2;
74012 yi <<= 1;
74013 yf *= 2;
74014 zi <<= 1;
74015 zf *= 2;
74016
74017 if (xf >= 1.0) {
74018 xi++;
74019 xf--;
74020 }
74021 if (yf >= 1.0) {
74022 yi++;
74023 yf--;
74024 }
74025 if (zf >= 1.0) {
74026 zi++;
74027 zf--;
74028 }
74029 }
74030 return r;
74031 };
74032
74033 /**
74034 *
74035 * Adjusts the character and level of detail produced by the Perlin noise
74036 * function. Similar to harmonics in physics, noise is computed over
74037 * several octaves. Lower octaves contribute more to the output signal and
74038 * as such define the overall intensity of the noise, whereas higher octaves
74039 * create finer grained details in the noise sequence.
74040 *
74041 * By default, noise is computed over 4 octaves with each octave contributing
74042 * exactly half than its predecessor, starting at 50% strength for the 1st
74043 * octave. This falloff amount can be changed by adding an additional function
74044 * parameter. Eg. a falloff factor of 0.75 means each octave will now have
74045 * 75% impact (25% less) of the previous lower octave. Any value between
74046 * 0.0 and 1.0 is valid, however note that values greater than 0.5 might
74047 * result in greater than 1.0 values returned by <b>noise()</b>.
74048 *
74049 * By changing these parameters, the signal created by the <b>noise()</b>
74050 * function can be adapted to fit very specific needs and characteristics.
74051 *
74052 * @method noiseDetail
74053 * @param {Number} lod number of octaves to be used by the noise
74054 * @param {Number} falloff falloff factor for each octave
74055 * @example
74056 * <div>
74057 * <code>
74058 * let noiseVal;
74059 * let noiseScale = 0.02;
74060 *
74061 * function setup() {
74062 * createCanvas(100, 100);
74063 * }
74064 *
74065 * function draw() {
74066 * background(0);
74067 * for (let y = 0; y < height; y++) {
74068 * for (let x = 0; x < width / 2; x++) {
74069 * noiseDetail(2, 0.2);
74070 * noiseVal = noise((mouseX + x) * noiseScale, (mouseY + y) * noiseScale);
74071 * stroke(noiseVal * 255);
74072 * point(x, y);
74073 * noiseDetail(8, 0.65);
74074 * noiseVal = noise(
74075 * (mouseX + x + width / 2) * noiseScale,
74076 * (mouseY + y) * noiseScale
74077 * );
74078 * stroke(noiseVal * 255);
74079 * point(x + width / 2, y);
74080 * }
74081 * }
74082 * }
74083 * </code>
74084 * </div>
74085 *
74086 * @alt
74087 * 2 vertical grey smokey patterns affected my mouse x-position and noise.
74088 */
74089 _main.default.prototype.noiseDetail = function(lod, falloff) {
74090 if (lod > 0) {
74091 perlin_octaves = lod;
74092 }
74093 if (falloff > 0) {
74094 perlin_amp_falloff = falloff;
74095 }
74096 };
74097
74098 /**
74099 * Sets the seed value for <b>noise()</b>. By default, <b>noise()</b>
74100 * produces different results each time the program is run. Set the
74101 * <b>value</b> parameter to a constant to return the same pseudo-random
74102 * numbers each time the software is run.
74103 *
74104 * @method noiseSeed
74105 * @param {Number} seed the seed value
74106 * @example
74107 * <div>
74108 * <code>let xoff = 0.0;
74109 *
74110 * function setup() {
74111 * noiseSeed(99);
74112 * stroke(0, 10);
74113 * }
74114 *
74115 * function draw() {
74116 * xoff = xoff + .01;
74117 * let n = noise(xoff) * width;
74118 * line(n, 0, n, height);
74119 * }
74120 * </code>
74121 * </div>
74122 *
74123 * @alt
74124 * vertical grey lines drawing in pattern affected by noise.
74125 */
74126 _main.default.prototype.noiseSeed = function(seed) {
74127 // Linear Congruential Generator
74128 // Variant of a Lehman Generator
74129 var lcg = (function() {
74130 // Set to values from http://en.wikipedia.org/wiki/Numerical_Recipes
74131 // m is basically chosen to be large (as it is the max period)
74132 // and for its relationships to a and c
74133 var m = 4294967296;
74134 // a - 1 should be divisible by m's prime factors
74135 var a = 1664525;
74136 // c and m should be co-prime
74137 var c = 1013904223;
74138 var seed, z;
74139 return {
74140 setSeed: function setSeed(val) {
74141 // pick a random seed if val is undefined or null
74142 // the >>> 0 casts the seed to an unsigned 32-bit integer
74143 z = seed = (val == null ? Math.random() * m : val) >>> 0;
74144 },
74145 getSeed: function getSeed() {
74146 return seed;
74147 },
74148 rand: function rand() {
74149 // define the recurrence relationship
74150 z = (a * z + c) % m;
74151 // return a float in [0, 1)
74152 // if z = m then z / m = 0 therefore (z % m) / m < 1 always
74153 return z / m;
74154 }
74155 };
74156 })();
74157
74158 lcg.setSeed(seed);
74159 perlin = new Array(PERLIN_SIZE + 1);
74160 for (var i = 0; i < PERLIN_SIZE + 1; i++) {
74161 perlin[i] = lcg.rand();
74162 }
74163 };
74164 var _default = _main.default;
74165 exports.default = _default;
74166 },
74167 { '../core/main': 54 }
74168 ],
74169 87: [
74170 function(_dereq_, module, exports) {
74171 'use strict';
74172 function _typeof(obj) {
74173 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
74174 _typeof = function _typeof(obj) {
74175 return typeof obj;
74176 };
74177 } else {
74178 _typeof = function _typeof(obj) {
74179 return obj &&
74180 typeof Symbol === 'function' &&
74181 obj.constructor === Symbol &&
74182 obj !== Symbol.prototype
74183 ? 'symbol'
74184 : typeof obj;
74185 };
74186 }
74187 return _typeof(obj);
74188 }
74189 Object.defineProperty(exports, '__esModule', { value: true });
74190 exports.default = void 0;
74191
74192 var _main = _interopRequireDefault(_dereq_('../core/main'));
74193 var constants = _interopRequireWildcard(_dereq_('../core/constants'));
74194 function _getRequireWildcardCache() {
74195 if (typeof WeakMap !== 'function') return null;
74196 var cache = new WeakMap();
74197 _getRequireWildcardCache = function _getRequireWildcardCache() {
74198 return cache;
74199 };
74200 return cache;
74201 }
74202 function _interopRequireWildcard(obj) {
74203 if (obj && obj.__esModule) {
74204 return obj;
74205 }
74206 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) {
74207 return { default: obj };
74208 }
74209 var cache = _getRequireWildcardCache();
74210 if (cache && cache.has(obj)) {
74211 return cache.get(obj);
74212 }
74213 var newObj = {};
74214 var hasPropertyDescriptor =
74215 Object.defineProperty && Object.getOwnPropertyDescriptor;
74216 for (var key in obj) {
74217 if (Object.prototype.hasOwnProperty.call(obj, key)) {
74218 var desc = hasPropertyDescriptor
74219 ? Object.getOwnPropertyDescriptor(obj, key)
74220 : null;
74221 if (desc && (desc.get || desc.set)) {
74222 Object.defineProperty(newObj, key, desc);
74223 } else {
74224 newObj[key] = obj[key];
74225 }
74226 }
74227 }
74228 newObj.default = obj;
74229 if (cache) {
74230 cache.set(obj, newObj);
74231 }
74232 return newObj;
74233 }
74234 function _interopRequireDefault(obj) {
74235 return obj && obj.__esModule ? obj : { default: obj };
74236 }
74237 /**
74238 * @module Math
74239 * @submodule Vector
74240 * @requires constants
74241 */ /**
74242 * A class to describe a two or three dimensional vector, specifically
74243 * a Euclidean (also known as geometric) vector. A vector is an entity
74244 * that has both magnitude and direction. The datatype, however, stores
74245 * the components of the vector (x, y for 2D, and x, y, z for 3D). The magnitude
74246 * and direction can be accessed via the methods <a href="#/p5.Vector/mag">mag()</a> and <a href="#/p5.Vector/heading">heading()</a>.
74247 *
74248 * In many of the p5.js examples, you will see <a href="#/p5.Vector">p5.Vector</a> used to describe a
74249 * position, velocity, or acceleration. For example, if you consider a rectangle
74250 * moving across the screen, at any given instant it has a position (a vector
74251 * that points from the origin to its location), a velocity (the rate at which
74252 * the object's position changes per time unit, expressed as a vector), and
74253 * acceleration (the rate at which the object's velocity changes per time
74254 * unit, expressed as a vector).
74255 *
74256 * Since vectors represent groupings of values, we cannot simply use
74257 * traditional addition/multiplication/etc. Instead, we'll need to do some
74258 * "vector" math, which is made easy by the methods inside the <a href="#/p5.Vector">p5.Vector</a> class.
74259 *
74260 * @class p5.Vector
74261 * @constructor
74262 * @param {Number} [x] x component of the vector
74263 * @param {Number} [y] y component of the vector
74264 * @param {Number} [z] z component of the vector
74265 * @example
74266 * <div>
74267 * <code>
74268 * let v1 = createVector(40, 50);
74269 * let v2 = createVector(40, 50);
74270 *
74271 * ellipse(v1.x, v1.y, 50, 50);
74272 * ellipse(v2.x, v2.y, 50, 50);
74273 * v1.add(v2);
74274 * ellipse(v1.x, v1.y, 50, 50);
74275 * </code>
74276 * </div>
74277 *
74278 * @alt
74279 * 2 white ellipses. One center-left the other bottom right and off canvas
74280 */ _main.default.Vector = function Vector() {
74281 var x, y, z;
74282 // This is how it comes in with createVector()
74283 if (arguments[0] instanceof _main.default) {
74284 // save reference to p5 if passed in
74285 this.p5 = arguments[0];
74286 x = arguments[1][0] || 0;
74287 y = arguments[1][1] || 0;
74288 z = arguments[1][2] || 0;
74289 // This is what we'll get with new p5.Vector()
74290 } else {
74291 x = arguments[0] || 0;
74292 y = arguments[1] || 0;
74293 z = arguments[2] || 0;
74294 }
74295 /**
74296 * The x component of the vector
74297 * @property x {Number}
74298 */
74299 this.x = x;
74300 /**
74301 * The y component of the vector
74302 * @property y {Number}
74303 */
74304 this.y = y;
74305 /**
74306 * The z component of the vector
74307 * @property z {Number}
74308 */
74309 this.z = z;
74310 };
74311
74312 /**
74313 * Returns a string representation of a vector v by calling String(v)
74314 * or v.toString(). This method is useful for logging vectors in the
74315 * console.
74316 * @method toString
74317 * @return {String}
74318 * @example
74319 * <div class = "norender">
74320 * <code>
74321 * function setup() {
74322 * let v = createVector(20, 30);
74323 * print(String(v)); // prints "p5.Vector Object : [20, 30, 0]"
74324 * }
74325 * </code>
74326 * </div>
74327 *
74328 * <div>
74329 * <code>
74330 * function draw() {
74331 * background(240);
74332 *
74333 * let v0 = createVector(0, 0);
74334 * let v1 = createVector(mouseX, mouseY);
74335 * drawArrow(v0, v1, 'black');
74336 *
74337 * noStroke();
74338 * text(v1.toString(), 10, 25, 90, 75);
74339 * }
74340 *
74341 * // draw an arrow for a vector at a given base position
74342 * function drawArrow(base, vec, myColor) {
74343 * push();
74344 * stroke(myColor);
74345 * strokeWeight(3);
74346 * fill(myColor);
74347 * translate(base.x, base.y);
74348 * line(0, 0, vec.x, vec.y);
74349 * rotate(vec.heading());
74350 * let arrowSize = 7;
74351 * translate(vec.mag() - arrowSize, 0);
74352 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
74353 * pop();
74354 * }
74355 * </code>
74356 * </div>
74357 */
74358 _main.default.Vector.prototype.toString = function p5VectorToString() {
74359 return 'p5.Vector Object : ['
74360 .concat(this.x, ', ')
74361 .concat(this.y, ', ')
74362 .concat(this.z, ']');
74363 };
74364
74365 /**
74366 * Sets the x, y, and z component of the vector using two or three separate
74367 * variables, the data from a <a href="#/p5.Vector">p5.Vector</a>, or the values from a float array.
74368 * @method set
74369 * @param {Number} [x] the x component of the vector
74370 * @param {Number} [y] the y component of the vector
74371 * @param {Number} [z] the z component of the vector
74372 * @chainable
74373 * @example
74374 * <div class="norender">
74375 * <code>
74376 * function setup() {
74377 * let v = createVector(1, 2, 3);
74378 * v.set(4, 5, 6); // Sets vector to [4, 5, 6]
74379 *
74380 * let v1 = createVector(0, 0, 0);
74381 * let arr = [1, 2, 3];
74382 * v1.set(arr); // Sets vector to [1, 2, 3]
74383 * }
74384 * </code>
74385 * </div>
74386 *
74387 * <div>
74388 * <code>
74389 * let v0, v1;
74390 * function setup() {
74391 * createCanvas(100, 100);
74392 *
74393 * v0 = createVector(0, 0);
74394 * v1 = createVector(50, 50);
74395 * }
74396 *
74397 * function draw() {
74398 * background(240);
74399 *
74400 * drawArrow(v0, v1, 'black');
74401 * v1.set(v1.x + random(-1, 1), v1.y + random(-1, 1));
74402 *
74403 * noStroke();
74404 * text('x: ' + round(v1.x) + ' y: ' + round(v1.y), 20, 90);
74405 * }
74406 *
74407 * // draw an arrow for a vector at a given base position
74408 * function drawArrow(base, vec, myColor) {
74409 * push();
74410 * stroke(myColor);
74411 * strokeWeight(3);
74412 * fill(myColor);
74413 * translate(base.x, base.y);
74414 * line(0, 0, vec.x, vec.y);
74415 * rotate(vec.heading());
74416 * let arrowSize = 7;
74417 * translate(vec.mag() - arrowSize, 0);
74418 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
74419 * pop();
74420 * }
74421 * </code>
74422 * </div>
74423 */
74424 /**
74425 * @method set
74426 * @param {p5.Vector|Number[]} value the vector to set
74427 * @chainable
74428 */
74429 _main.default.Vector.prototype.set = function set(x, y, z) {
74430 if (x instanceof _main.default.Vector) {
74431 this.x = x.x || 0;
74432 this.y = x.y || 0;
74433 this.z = x.z || 0;
74434 return this;
74435 }
74436 if (x instanceof Array) {
74437 this.x = x[0] || 0;
74438 this.y = x[1] || 0;
74439 this.z = x[2] || 0;
74440 return this;
74441 }
74442 this.x = x || 0;
74443 this.y = y || 0;
74444 this.z = z || 0;
74445 return this;
74446 };
74447
74448 /**
74449 * Gets a copy of the vector, returns a <a href="#/p5.Vector">p5.Vector</a> object.
74450 *
74451 * @method copy
74452 * @return {p5.Vector} the copy of the <a href="#/p5.Vector">p5.Vector</a> object
74453 * @example
74454 * <div class="norender">
74455 * <code>
74456 * let v1 = createVector(1, 2, 3);
74457 * let v2 = v1.copy();
74458 * print(v1.x === v2.x && v1.y === v2.y && v1.z === v2.z);
74459 * // Prints "true"
74460 * </code>
74461 * </div>
74462 */
74463 _main.default.Vector.prototype.copy = function copy() {
74464 if (this.p5) {
74465 return new _main.default.Vector(this.p5, [this.x, this.y, this.z]);
74466 } else {
74467 return new _main.default.Vector(this.x, this.y, this.z);
74468 }
74469 };
74470
74471 /**
74472 * Adds x, y, and z components to a vector, adds one vector to another, or
74473 * adds two independent vectors together. The version of the method that adds
74474 * two vectors together is a static method and returns a <a href="#/p5.Vector">p5.Vector</a>, the others
74475 * acts directly on the vector. Additionally, you may provide arguments to this function as an array.
74476 * See the examples for more context.
74477 *
74478 * @method add
74479 * @param {Number} x the x component of the vector to be added
74480 * @param {Number} [y] the y component of the vector to be added
74481 * @param {Number} [z] the z component of the vector to be added
74482 * @chainable
74483 * @example
74484 * <div class="norender">
74485 * <code>
74486 * let v = createVector(1, 2, 3);
74487 * v.add(4, 5, 6);
74488 * // v's components are set to [5, 7, 9]
74489 * </code>
74490 * </div>
74491 *
74492 * <div class="norender">
74493 * <code>
74494 * let v = createVector(1, 2, 3);
74495 * // Provide arguments as an array
74496 * let arr = [4, 5, 6];
74497 * v.add(arr);
74498 * // v's components are set to [5, 7, 9]
74499 * </code>
74500 * </div>
74501 *
74502 * <div class="norender">
74503 * <code>
74504 * // Static method
74505 * let v1 = createVector(1, 2, 3);
74506 * let v2 = createVector(2, 3, 4);
74507 *
74508 * let v3 = p5.Vector.add(v1, v2);
74509 * // v3 has components [3, 5, 7]
74510 * print(v3);
74511 * </code>
74512 * </div>
74513 *
74514 * <div>
74515 * <code>
74516 * // red vector + blue vector = purple vector
74517 * function draw() {
74518 * background(240);
74519 *
74520 * let v0 = createVector(0, 0);
74521 * let v1 = createVector(mouseX, mouseY);
74522 * drawArrow(v0, v1, 'red');
74523 *
74524 * let v2 = createVector(-30, 20);
74525 * drawArrow(v1, v2, 'blue');
74526 *
74527 * let v3 = p5.Vector.add(v1, v2);
74528 * drawArrow(v0, v3, 'purple');
74529 * }
74530 *
74531 * // draw an arrow for a vector at a given base position
74532 * function drawArrow(base, vec, myColor) {
74533 * push();
74534 * stroke(myColor);
74535 * strokeWeight(3);
74536 * fill(myColor);
74537 * translate(base.x, base.y);
74538 * line(0, 0, vec.x, vec.y);
74539 * rotate(vec.heading());
74540 * let arrowSize = 7;
74541 * translate(vec.mag() - arrowSize, 0);
74542 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
74543 * pop();
74544 * }
74545 * </code>
74546 * </div>
74547 */
74548 /**
74549 * @method add
74550 * @param {p5.Vector|Number[]} value the vector to add
74551 * @chainable
74552 */
74553 _main.default.Vector.prototype.add = function add(x, y, z) {
74554 if (x instanceof _main.default.Vector) {
74555 this.x += x.x || 0;
74556 this.y += x.y || 0;
74557 this.z += x.z || 0;
74558 return this;
74559 }
74560 if (x instanceof Array) {
74561 this.x += x[0] || 0;
74562 this.y += x[1] || 0;
74563 this.z += x[2] || 0;
74564 return this;
74565 }
74566 this.x += x || 0;
74567 this.y += y || 0;
74568 this.z += z || 0;
74569 return this;
74570 };
74571
74572 /// HELPERS FOR REMAINDER METHOD
74573 var calculateRemainder2D = function calculateRemainder2D(xComponent, yComponent) {
74574 if (xComponent !== 0) {
74575 this.x = this.x % xComponent;
74576 }
74577 if (yComponent !== 0) {
74578 this.y = this.y % yComponent;
74579 }
74580 return this;
74581 };
74582
74583 var calculateRemainder3D = function calculateRemainder3D(
74584 xComponent,
74585 yComponent,
74586 zComponent
74587 ) {
74588 if (xComponent !== 0) {
74589 this.x = this.x % xComponent;
74590 }
74591 if (yComponent !== 0) {
74592 this.y = this.y % yComponent;
74593 }
74594 if (zComponent !== 0) {
74595 this.z = this.z % zComponent;
74596 }
74597 return this;
74598 };
74599 /**
74600 * Gives remainder of a vector when it is divided by another vector.
74601 * See examples for more context.
74602 *
74603 * @method rem
74604 * @param {Number} x the x component of divisor vector
74605 * @param {Number} y the y component of divisor vector
74606 * @param {Number} z the z component of divisor vector
74607 * @chainable
74608 * @example
74609 * <div class='norender'>
74610 * <code>
74611 * let v = createVector(3, 4, 5);
74612 * v.rem(2, 3, 4);
74613 * // v's components are set to [1, 1, 1]
74614 * </code>
74615 * </div>
74616 * <div class="norender">
74617 * <code>
74618 * // Static method
74619 * let v1 = createVector(3, 4, 5);
74620 * let v2 = createVector(2, 3, 4);
74621 *
74622 * let v3 = p5.Vector.rem(v1, v2);
74623 * // v3 has components [1, 1, 1]
74624 * print(v3);
74625 * </code>
74626 * </div>
74627 */
74628 /**
74629 * @method rem
74630 * @param {p5.Vector | Number[]} value divisor vector
74631 * @chainable
74632 */
74633 _main.default.Vector.prototype.rem = function rem(x, y, z) {
74634 if (x instanceof _main.default.Vector) {
74635 if (Number.isFinite(x.x) && Number.isFinite(x.y) && Number.isFinite(x.z)) {
74636 var xComponent = parseFloat(x.x);
74637 var yComponent = parseFloat(x.y);
74638 var zComponent = parseFloat(x.z);
74639 calculateRemainder3D.call(this, xComponent, yComponent, zComponent);
74640 }
74641 } else if (x instanceof Array) {
74642 if (
74643 x.every(function(element) {
74644 return Number.isFinite(element);
74645 })
74646 ) {
74647 if (x.length === 2) {
74648 calculateRemainder2D.call(this, x[0], x[1]);
74649 }
74650 if (x.length === 3) {
74651 calculateRemainder3D.call(this, x[0], x[1], x[2]);
74652 }
74653 }
74654 } else if (arguments.length === 1) {
74655 if (Number.isFinite(arguments[0]) && arguments[0] !== 0) {
74656 this.x = this.x % arguments[0];
74657 this.y = this.y % arguments[0];
74658 this.z = this.z % arguments[0];
74659 return this;
74660 }
74661 } else if (arguments.length === 2) {
74662 var vectorComponents = Array.prototype.slice.call(arguments);
74663 if (
74664 vectorComponents.every(function(element) {
74665 return Number.isFinite(element);
74666 })
74667 ) {
74668 if (vectorComponents.length === 2) {
74669 calculateRemainder2D.call(this, vectorComponents[0], vectorComponents[1]);
74670 }
74671 }
74672 } else if (arguments.length === 3) {
74673 var _vectorComponents = Array.prototype.slice.call(arguments);
74674 if (
74675 _vectorComponents.every(function(element) {
74676 return Number.isFinite(element);
74677 })
74678 ) {
74679 if (_vectorComponents.length === 3) {
74680 calculateRemainder3D.call(
74681 this,
74682 _vectorComponents[0],
74683 _vectorComponents[1],
74684 _vectorComponents[2]
74685 );
74686 }
74687 }
74688 }
74689 };
74690
74691 /**
74692 * Subtracts x, y, and z components from a vector, subtracts one vector from
74693 * another, or subtracts two independent vectors. The version of the method
74694 * that subtracts two vectors is a static method and returns a <a href="#/p5.Vector">p5.Vector</a>, the
74695 * other acts directly on the vector. Additionally, you may provide arguments to this function as an array.
74696 * See the examples for more context.
74697 *
74698 * @method sub
74699 * @param {Number} x the x component of the vector to subtract
74700 * @param {Number} [y] the y component of the vector to subtract
74701 * @param {Number} [z] the z component of the vector to subtract
74702 * @chainable
74703 * @example
74704 * <div class="norender">
74705 * <code>
74706 * let v = createVector(4, 5, 6);
74707 * v.sub(1, 1, 1);
74708 * // v's components are set to [3, 4, 5]
74709 * </code>
74710 * </div>
74711 *
74712 * <div class="norender">
74713 * <code>
74714 * let v = createVector(4, 5, 6);
74715 * // Provide arguments as an array
74716 * let arr = [1, 1, 1];
74717 * v.sub(arr);
74718 * // v's components are set to [3, 4, 5]
74719 * </code>
74720 * </div>
74721 *
74722 * <div class="norender">
74723 * <code>
74724 * // Static method
74725 * let v1 = createVector(2, 3, 4);
74726 * let v2 = createVector(1, 2, 3);
74727 *
74728 * let v3 = p5.Vector.sub(v1, v2);
74729 * // v3 has components [1, 1, 1]
74730 * print(v3);
74731 * </code>
74732 * </div>
74733 *
74734 * <div>
74735 * <code>
74736 * // red vector - blue vector = purple vector
74737 * function draw() {
74738 * background(240);
74739 *
74740 * let v0 = createVector(0, 0);
74741 * let v1 = createVector(70, 50);
74742 * drawArrow(v0, v1, 'red');
74743 *
74744 * let v2 = createVector(mouseX, mouseY);
74745 * drawArrow(v0, v2, 'blue');
74746 *
74747 * let v3 = p5.Vector.sub(v1, v2);
74748 * drawArrow(v2, v3, 'purple');
74749 * }
74750 *
74751 * // draw an arrow for a vector at a given base position
74752 * function drawArrow(base, vec, myColor) {
74753 * push();
74754 * stroke(myColor);
74755 * strokeWeight(3);
74756 * fill(myColor);
74757 * translate(base.x, base.y);
74758 * line(0, 0, vec.x, vec.y);
74759 * rotate(vec.heading());
74760 * let arrowSize = 7;
74761 * translate(vec.mag() - arrowSize, 0);
74762 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
74763 * pop();
74764 * }
74765 * </code>
74766 * </div>
74767 */
74768 /**
74769 * @method sub
74770 * @param {p5.Vector|Number[]} value the vector to subtract
74771 * @chainable
74772 */
74773 _main.default.Vector.prototype.sub = function sub(x, y, z) {
74774 if (x instanceof _main.default.Vector) {
74775 this.x -= x.x || 0;
74776 this.y -= x.y || 0;
74777 this.z -= x.z || 0;
74778 return this;
74779 }
74780 if (x instanceof Array) {
74781 this.x -= x[0] || 0;
74782 this.y -= x[1] || 0;
74783 this.z -= x[2] || 0;
74784 return this;
74785 }
74786 this.x -= x || 0;
74787 this.y -= y || 0;
74788 this.z -= z || 0;
74789 return this;
74790 };
74791
74792 /**
74793 * Multiplies the vector by a scalar, multiplies the x, y, and z components from a vector, or multiplies
74794 * the x, y, and z components of two independent vectors. When multiplying a vector by a scalar, the x, y,
74795 * and z components of the vector are all multiplied by the scalar. When multiplying a vector by a vector,
74796 * the x, y, z components of both vectors are multiplied by each other
74797 * (for example, with two vectors a and b: a.x * b.x, a.y * b.y, a.z * b.z). The static version of this method
74798 * creates a new <a href="#/p5.Vector">p5.Vector</a> while the non static version acts on the vector
74799 * directly. Additionally, you may provide arguments to this function as an array.
74800 * See the examples for more context.
74801 *
74802 * @method mult
74803 * @param {Number} n The number to multiply with the vector
74804 * @chainable
74805 * @example
74806 * <div class="norender">
74807 * <code>
74808 * let v = createVector(1, 2, 3);
74809 * v.mult(2);
74810 * // v's components are set to [2, 4, 6]
74811 * </code>
74812 * </div>
74813 *
74814 * <div class="norender">
74815 * <code>
74816 * let v0 = createVector(1, 2, 3);
74817 * let v1 = createVector(2, 3, 4);
74818 * v0.mult(v1); // v0's components are set to [2, 6, 12]
74819 * </code>
74820 * </div>
74821 *
74822 * <div class="norender">
74823 * <code>
74824 * let v0 = createVector(1, 2, 3);
74825 * // Provide arguments as an array
74826 * let arr = [2, 3, 4];
74827 * v0.mult(arr); // v0's components are set to [2, 6, 12]
74828 * </code>
74829 * </div>
74830 *
74831 * <div class="norender">
74832 * <code>
74833 * let v0 = createVector(1, 2, 3);
74834 * let v1 = createVector(2, 3, 4);
74835 * const result = p5.Vector.mult(v0, v1);
74836 * print(result); // result's components are set to [2, 6, 12]
74837 * </code>
74838 * </div>
74839 *
74840 * <div class="norender">
74841 * <code>
74842 * // Static method
74843 * let v1 = createVector(1, 2, 3);
74844 * let v2 = p5.Vector.mult(v1, 2);
74845 * // v2 has components [2, 4, 6]
74846 * print(v2);
74847 * </code>
74848 * </div>
74849 *
74850 * <div>
74851 * <code>
74852 * function draw() {
74853 * background(240);
74854 *
74855 * let v0 = createVector(50, 50);
74856 * let v1 = createVector(25, -25);
74857 * drawArrow(v0, v1, 'red');
74858 *
74859 * let num = map(mouseX, 0, width, -2, 2, true);
74860 * let v2 = p5.Vector.mult(v1, num);
74861 * drawArrow(v0, v2, 'blue');
74862 *
74863 * noStroke();
74864 * text('multiplied by ' + num.toFixed(2), 5, 90);
74865 * }
74866 *
74867 * // draw an arrow for a vector at a given base position
74868 * function drawArrow(base, vec, myColor) {
74869 * push();
74870 * stroke(myColor);
74871 * strokeWeight(3);
74872 * fill(myColor);
74873 * translate(base.x, base.y);
74874 * line(0, 0, vec.x, vec.y);
74875 * rotate(vec.heading());
74876 * let arrowSize = 7;
74877 * translate(vec.mag() - arrowSize, 0);
74878 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
74879 * pop();
74880 * }
74881 * </code>
74882 * </div>
74883 */
74884
74885 /**
74886 * @method mult
74887 * @param {Number} x The number to multiply with the x component of the vector
74888 * @param {Number} y The number to multiply with the y component of the vector
74889 * @param {Number} [z] The number to multiply with the z component of the vector
74890 * @chainable
74891 */
74892
74893 /**
74894 * @method mult
74895 * @param {Number[]} arr The array to multiply with the components of the vector
74896 * @chainable
74897 */
74898
74899 /**
74900 * @method mult
74901 * @param {p5.Vector} v The vector to multiply with the components of the original vector
74902 * @chainable
74903 */
74904
74905 _main.default.Vector.prototype.mult = function mult(x, y, z) {
74906 if (x instanceof _main.default.Vector) {
74907 // new p5.Vector will check that values are valid upon construction but it's possible
74908 // that someone could change the value of a component after creation, which is why we still
74909 // perform this check
74910 if (
74911 Number.isFinite(x.x) &&
74912 Number.isFinite(x.y) &&
74913 Number.isFinite(x.z) &&
74914 typeof x.x === 'number' &&
74915 typeof x.y === 'number' &&
74916 typeof x.z === 'number'
74917 ) {
74918 this.x *= x.x;
74919 this.y *= x.y;
74920 this.z *= x.z;
74921 } else {
74922 console.warn(
74923 'p5.Vector.prototype.mult:',
74924 'x contains components that are either undefined or not finite numbers'
74925 );
74926 }
74927 return this;
74928 }
74929 if (x instanceof Array) {
74930 if (
74931 x.every(function(element) {
74932 return Number.isFinite(element);
74933 }) &&
74934 x.every(function(element) {
74935 return typeof element === 'number';
74936 })
74937 ) {
74938 if (x.length === 1) {
74939 this.x *= x[0];
74940 this.y *= x[0];
74941 this.z *= x[0];
74942 } else if (x.length === 2) {
74943 this.x *= x[0];
74944 this.y *= x[1];
74945 } else if (x.length === 3) {
74946 this.x *= x[0];
74947 this.y *= x[1];
74948 this.z *= x[2];
74949 }
74950 } else {
74951 console.warn(
74952 'p5.Vector.prototype.mult:',
74953 'x contains elements that are either undefined or not finite numbers'
74954 );
74955 }
74956 return this;
74957 }
74958
74959 var vectorComponents = Array.prototype.slice.call(arguments);
74960 if (
74961 vectorComponents.every(function(element) {
74962 return Number.isFinite(element);
74963 }) &&
74964 vectorComponents.every(function(element) {
74965 return typeof element === 'number';
74966 })
74967 ) {
74968 if (arguments.length === 1) {
74969 this.x *= x;
74970 this.y *= x;
74971 this.z *= x;
74972 }
74973 if (arguments.length === 2) {
74974 this.x *= x;
74975 this.y *= y;
74976 }
74977 if (arguments.length === 3) {
74978 this.x *= x;
74979 this.y *= y;
74980 this.z *= z;
74981 }
74982 } else {
74983 console.warn(
74984 'p5.Vector.prototype.mult:',
74985 'x, y, or z arguments are either undefined or not a finite number'
74986 );
74987 }
74988
74989 return this;
74990 };
74991
74992 /**
74993 * Divides the vector by a scalar, divides a vector by the x, y, and z arguments, or divides the x, y, and
74994 * z components of two vectors against each other. When dividing a vector by a scalar, the x, y,
74995 * and z components of the vector are all divided by the scalar. When dividing a vector by a vector,
74996 * the x, y, z components of the source vector are treated as the dividend, and the x, y, z components
74997 * of the argument is treated as the divisor (for example with two vectors a and b: a.x / b.x, a.y / b.y, a.z / b.z).
74998 * The static version of this method creates a
74999 * new <a href="#/p5.Vector">p5.Vector</a> while the non static version acts on the vector directly.
75000 * Additionally, you may provide arguments to this function as an array.
75001 * See the examples for more context.
75002 *
75003 * @method div
75004 * @param {number} n The number to divide the vector by
75005 * @chainable
75006 * @example
75007 * <div class="norender">
75008 * <code>
75009 * let v = createVector(6, 4, 2);
75010 * v.div(2); //v's components are set to [3, 2, 1]
75011 * </code>
75012 * </div>
75013 *
75014 * <div class="norender">
75015 * <code>
75016 * let v0 = createVector(9, 4, 2);
75017 * let v1 = createVector(3, 2, 4);
75018 * v0.div(v1); // v0's components are set to [3, 2, 0.5]
75019 * </code>
75020 * </div>
75021 *
75022 * <div class="norender">
75023 * <code>
75024 * let v0 = createVector(9, 4, 2);
75025 * // Provide arguments as an array
75026 * let arr = [3, 2, 4];
75027 * v0.div(arr); // v0's components are set to [3, 2, 0.5]
75028 * </code>
75029 * </div>
75030 *
75031 * <div class="norender">
75032 * <code>
75033 * let v0 = createVector(9, 4, 2);
75034 * let v1 = createVector(3, 2, 4);
75035 * let result = p5.Vector.div(v0, v1);
75036 * print(result); // result's components are set to [3, 2, 0.5]
75037 * </code>
75038 * </div>
75039 *
75040 * <div class="norender">
75041 * <code>
75042 * // Static method
75043 * let v1 = createVector(6, 4, 2);
75044 * let v2 = p5.Vector.div(v1, 2);
75045 * // v2 has components [3, 2, 1]
75046 * print(v2);
75047 * </code>
75048 * </div>
75049 *
75050 * <div>
75051 * <code>
75052 * function draw() {
75053 * background(240);
75054 *
75055 * let v0 = createVector(0, 100);
75056 * let v1 = createVector(50, -50);
75057 * drawArrow(v0, v1, 'red');
75058 *
75059 * let num = map(mouseX, 0, width, 10, 0.5, true);
75060 * let v2 = p5.Vector.div(v1, num);
75061 * drawArrow(v0, v2, 'blue');
75062 *
75063 * noStroke();
75064 * text('divided by ' + num.toFixed(2), 10, 90);
75065 * }
75066 *
75067 * // draw an arrow for a vector at a given base position
75068 * function drawArrow(base, vec, myColor) {
75069 * push();
75070 * stroke(myColor);
75071 * strokeWeight(3);
75072 * fill(myColor);
75073 * translate(base.x, base.y);
75074 * line(0, 0, vec.x, vec.y);
75075 * rotate(vec.heading());
75076 * let arrowSize = 7;
75077 * translate(vec.mag() - arrowSize, 0);
75078 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
75079 * pop();
75080 * }
75081 * </code>
75082 * </div>
75083 */
75084
75085 /**
75086 * @method div
75087 * @param {Number} x The number to divide with the x component of the vector
75088 * @param {Number} y The number to divide with the y component of the vector
75089 * @param {Number} [z] The number to divide with the z component of the vector
75090 * @chainable
75091 */
75092
75093 /**
75094 * @method div
75095 * @param {Number[]} arr The array to divide the components of the vector by
75096 * @chainable
75097 */
75098
75099 /**
75100 * @method div
75101 * @param {p5.Vector} v The vector to divide the components of the original vector by
75102 * @chainable
75103 */
75104 _main.default.Vector.prototype.div = function div(x, y, z) {
75105 if (x instanceof _main.default.Vector) {
75106 // new p5.Vector will check that values are valid upon construction but it's possible
75107 // that someone could change the value of a component after creation, which is why we still
75108 // perform this check
75109 if (
75110 Number.isFinite(x.x) &&
75111 Number.isFinite(x.y) &&
75112 Number.isFinite(x.z) &&
75113 typeof x.x === 'number' &&
75114 typeof x.y === 'number' &&
75115 typeof x.z === 'number'
75116 ) {
75117 if (x.x === 0 || x.y === 0 || x.z === 0) {
75118 console.warn('p5.Vector.prototype.div:', 'divide by 0');
75119 return this;
75120 }
75121 this.x /= x.x;
75122 this.y /= x.y;
75123 this.z /= x.z;
75124 } else {
75125 console.warn(
75126 'p5.Vector.prototype.div:',
75127 'x contains components that are either undefined or not finite numbers'
75128 );
75129 }
75130 return this;
75131 }
75132 if (x instanceof Array) {
75133 if (
75134 x.every(function(element) {
75135 return Number.isFinite(element);
75136 }) &&
75137 x.every(function(element) {
75138 return typeof element === 'number';
75139 })
75140 ) {
75141 if (
75142 x.some(function(element) {
75143 return element === 0;
75144 })
75145 ) {
75146 console.warn('p5.Vector.prototype.div:', 'divide by 0');
75147 return this;
75148 }
75149
75150 if (x.length === 1) {
75151 this.x /= x[0];
75152 this.y /= x[0];
75153 this.z /= x[0];
75154 } else if (x.length === 2) {
75155 this.x /= x[0];
75156 this.y /= x[1];
75157 } else if (x.length === 3) {
75158 this.x /= x[0];
75159 this.y /= x[1];
75160 this.z /= x[2];
75161 }
75162 } else {
75163 console.warn(
75164 'p5.Vector.prototype.div:',
75165 'x contains components that are either undefined or not finite numbers'
75166 );
75167 }
75168
75169 return this;
75170 }
75171
75172 var vectorComponents = Array.prototype.slice.call(arguments);
75173 if (
75174 vectorComponents.every(function(element) {
75175 return Number.isFinite(element);
75176 }) &&
75177 vectorComponents.every(function(element) {
75178 return typeof element === 'number';
75179 })
75180 ) {
75181 if (
75182 vectorComponents.some(function(element) {
75183 return element === 0;
75184 })
75185 ) {
75186 console.warn('p5.Vector.prototype.div:', 'divide by 0');
75187 return this;
75188 }
75189
75190 if (arguments.length === 1) {
75191 this.x /= x;
75192 this.y /= x;
75193 this.z /= x;
75194 }
75195 if (arguments.length === 2) {
75196 this.x /= x;
75197 this.y /= y;
75198 }
75199 if (arguments.length === 3) {
75200 this.x /= x;
75201 this.y /= y;
75202 this.z /= z;
75203 }
75204 } else {
75205 console.warn(
75206 'p5.Vector.prototype.div:',
75207 'x, y, or z arguments are either undefined or not a finite number'
75208 );
75209 }
75210
75211 return this;
75212 };
75213 /**
75214 * Calculates the magnitude (length) of the vector and returns the result as
75215 * a float (this is simply the equation sqrt(x\*x + y\*y + z\*z).)
75216 *
75217 * @method mag
75218 * @return {Number} magnitude of the vector
75219 * @example
75220 * <div>
75221 * <code>
75222 * function draw() {
75223 * background(240);
75224 *
75225 * let v0 = createVector(0, 0);
75226 * let v1 = createVector(mouseX, mouseY);
75227 * drawArrow(v0, v1, 'black');
75228 *
75229 * noStroke();
75230 * text('vector length: ' + v1.mag().toFixed(2), 10, 70, 90, 30);
75231 * }
75232 *
75233 * // draw an arrow for a vector at a given base position
75234 * function drawArrow(base, vec, myColor) {
75235 * push();
75236 * stroke(myColor);
75237 * strokeWeight(3);
75238 * fill(myColor);
75239 * translate(base.x, base.y);
75240 * line(0, 0, vec.x, vec.y);
75241 * rotate(vec.heading());
75242 * let arrowSize = 7;
75243 * translate(vec.mag() - arrowSize, 0);
75244 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
75245 * pop();
75246 * }
75247 * </code>
75248 * </div>
75249 * <div class="norender">
75250 * <code>
75251 * let v = createVector(20.0, 30.0, 40.0);
75252 * let m = v.mag();
75253 * print(m); // Prints "53.85164807134504"
75254 * </code>
75255 * </div>
75256 */
75257 _main.default.Vector.prototype.mag = function mag() {
75258 return Math.sqrt(this.magSq());
75259 };
75260
75261 /**
75262 * Calculates the squared magnitude of the vector and returns the result
75263 * as a float (this is simply the equation <em>(x\*x + y\*y + z\*z)</em>.)
75264 * Faster if the real length is not required in the
75265 * case of comparing vectors, etc.
75266 *
75267 * @method magSq
75268 * @return {number} squared magnitude of the vector
75269 * @example
75270 * <div class="norender">
75271 * <code>
75272 * // Static method
75273 * let v1 = createVector(6, 4, 2);
75274 * print(v1.magSq()); // Prints "56"
75275 * </code>
75276 * </div>
75277 *
75278 * <div>
75279 * <code>
75280 * function draw() {
75281 * background(240);
75282 *
75283 * let v0 = createVector(0, 0);
75284 * let v1 = createVector(mouseX, mouseY);
75285 * drawArrow(v0, v1, 'black');
75286 *
75287 * noStroke();
75288 * text('vector length squared: ' + v1.magSq().toFixed(2), 10, 45, 90, 55);
75289 * }
75290 *
75291 * // draw an arrow for a vector at a given base position
75292 * function drawArrow(base, vec, myColor) {
75293 * push();
75294 * stroke(myColor);
75295 * strokeWeight(3);
75296 * fill(myColor);
75297 * translate(base.x, base.y);
75298 * line(0, 0, vec.x, vec.y);
75299 * rotate(vec.heading());
75300 * let arrowSize = 7;
75301 * translate(vec.mag() - arrowSize, 0);
75302 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
75303 * pop();
75304 * }
75305 * </code>
75306 * </div>
75307 */
75308 _main.default.Vector.prototype.magSq = function magSq() {
75309 var x = this.x;
75310 var y = this.y;
75311 var z = this.z;
75312 return x * x + y * y + z * z;
75313 };
75314
75315 /**
75316 * Calculates the dot product of two vectors. The version of the method
75317 * that computes the dot product of two independent vectors is a static
75318 * method. See the examples for more context.
75319 *
75320 * @method dot
75321 * @param {Number} x x component of the vector
75322 * @param {Number} [y] y component of the vector
75323 * @param {Number} [z] z component of the vector
75324 * @return {Number} the dot product
75325 *
75326 * @example
75327 * <div class="norender">
75328 * <code>
75329 * let v1 = createVector(1, 2, 3);
75330 * let v2 = createVector(2, 3, 4);
75331 *
75332 * print(v1.dot(v2)); // Prints "20"
75333 * </code>
75334 * </div>
75335 *
75336 * <div class="norender">
75337 * <code>
75338 * //Static method
75339 * let v1 = createVector(1, 2, 3);
75340 * let v2 = createVector(3, 2, 1);
75341 * print(p5.Vector.dot(v1, v2)); // Prints "10"
75342 * </code>
75343 * </div>
75344 */
75345 /**
75346 * @method dot
75347 * @param {p5.Vector} value value component of the vector or a <a href="#/p5.Vector">p5.Vector</a>
75348 * @return {Number}
75349 */
75350 _main.default.Vector.prototype.dot = function dot(x, y, z) {
75351 if (x instanceof _main.default.Vector) {
75352 return this.dot(x.x, x.y, x.z);
75353 }
75354 return this.x * (x || 0) + this.y * (y || 0) + this.z * (z || 0);
75355 };
75356
75357 /**
75358 * Calculates and returns a vector composed of the cross product between
75359 * two vectors. Both the static and non static methods return a new <a href="#/p5.Vector">p5.Vector</a>.
75360 * See the examples for more context.
75361 *
75362 * @method cross
75363 * @param {p5.Vector} v <a href="#/p5.Vector">p5.Vector</a> to be crossed
75364 * @return {p5.Vector} <a href="#/p5.Vector">p5.Vector</a> composed of cross product
75365 * @example
75366 * <div class="norender">
75367 * <code>
75368 * let v1 = createVector(1, 2, 3);
75369 * let v2 = createVector(1, 2, 3);
75370 *
75371 * let v = v1.cross(v2); // v's components are [0, 0, 0]
75372 * print(v);
75373 * </code>
75374 * </div>
75375 *
75376 * <div class="norender">
75377 * <code>
75378 * // Static method
75379 * let v1 = createVector(1, 0, 0);
75380 * let v2 = createVector(0, 1, 0);
75381 *
75382 * let crossProduct = p5.Vector.cross(v1, v2);
75383 * // crossProduct has components [0, 0, 1]
75384 * print(crossProduct);
75385 * </code>
75386 * </div>
75387 */
75388 _main.default.Vector.prototype.cross = function cross(v) {
75389 var x = this.y * v.z - this.z * v.y;
75390 var y = this.z * v.x - this.x * v.z;
75391 var z = this.x * v.y - this.y * v.x;
75392 if (this.p5) {
75393 return new _main.default.Vector(this.p5, [x, y, z]);
75394 } else {
75395 return new _main.default.Vector(x, y, z);
75396 }
75397 };
75398
75399 /**
75400 * Calculates the Euclidean distance between two points (considering a
75401 * point as a vector object).
75402 *
75403 * @method dist
75404 * @param {p5.Vector} v the x, y, and z coordinates of a <a href="#/p5.Vector">p5.Vector</a>
75405 * @return {Number} the distance
75406 * @example
75407 * <div class="norender">
75408 * <code>
75409 * let v1 = createVector(1, 0, 0);
75410 * let v2 = createVector(0, 1, 0);
75411 *
75412 * let distance = v1.dist(v2); // distance is 1.4142...
75413 * print(distance);
75414 * </code>
75415 * </div>
75416 *
75417 * <div class="norender">
75418 * <code>
75419 * // Static method
75420 * let v1 = createVector(1, 0, 0);
75421 * let v2 = createVector(0, 1, 0);
75422 *
75423 * let distance = p5.Vector.dist(v1, v2);
75424 * // distance is 1.4142...
75425 * print(distance);
75426 * </code>
75427 * </div>
75428 *
75429 * <div>
75430 * <code>
75431 * function draw() {
75432 * background(240);
75433 *
75434 * let v0 = createVector(0, 0);
75435 *
75436 * let v1 = createVector(70, 50);
75437 * drawArrow(v0, v1, 'red');
75438 *
75439 * let v2 = createVector(mouseX, mouseY);
75440 * drawArrow(v0, v2, 'blue');
75441 *
75442 * noStroke();
75443 * text('distance between vectors: ' + v2.dist(v1).toFixed(2), 5, 50, 95, 50);
75444 * }
75445 *
75446 * // draw an arrow for a vector at a given base position
75447 * function drawArrow(base, vec, myColor) {
75448 * push();
75449 * stroke(myColor);
75450 * strokeWeight(3);
75451 * fill(myColor);
75452 * translate(base.x, base.y);
75453 * line(0, 0, vec.x, vec.y);
75454 * rotate(vec.heading());
75455 * let arrowSize = 7;
75456 * translate(vec.mag() - arrowSize, 0);
75457 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
75458 * pop();
75459 * }
75460 * </code>
75461 * </div>
75462 */
75463 _main.default.Vector.prototype.dist = function dist(v) {
75464 return v
75465 .copy()
75466 .sub(this)
75467 .mag();
75468 };
75469
75470 /**
75471 * Normalize the vector to length 1 (make it a unit vector).
75472 *
75473 * @method normalize
75474 * @return {p5.Vector} normalized <a href="#/p5.Vector">p5.Vector</a>
75475 * @example
75476 * <div class="norender">
75477 * <code>
75478 * let v = createVector(10, 20, 2);
75479 * // v has components [10.0, 20.0, 2.0]
75480 * v.normalize();
75481 * // v's components are set to
75482 * // [0.4454354, 0.8908708, 0.089087084]
75483 * </code>
75484 * </div>
75485 * <div>
75486 * <code>
75487 * function draw() {
75488 * background(240);
75489 *
75490 * let v0 = createVector(50, 50);
75491 * let v1 = createVector(mouseX - 50, mouseY - 50);
75492 *
75493 * drawArrow(v0, v1, 'red');
75494 * v1.normalize();
75495 * drawArrow(v0, v1.mult(35), 'blue');
75496 *
75497 * noFill();
75498 * ellipse(50, 50, 35 * 2);
75499 * }
75500 *
75501 * // draw an arrow for a vector at a given base position
75502 * function drawArrow(base, vec, myColor) {
75503 * push();
75504 * stroke(myColor);
75505 * strokeWeight(3);
75506 * fill(myColor);
75507 * translate(base.x, base.y);
75508 * line(0, 0, vec.x, vec.y);
75509 * rotate(vec.heading());
75510 * let arrowSize = 7;
75511 * translate(vec.mag() - arrowSize, 0);
75512 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
75513 * pop();
75514 * }
75515 * </code>
75516 * </div>
75517 */
75518 _main.default.Vector.prototype.normalize = function normalize() {
75519 var len = this.mag();
75520 // here we multiply by the reciprocal instead of calling 'div()'
75521 // since div duplicates this zero check.
75522 if (len !== 0) this.mult(1 / len);
75523 return this;
75524 };
75525
75526 /**
75527 * Limit the magnitude of this vector to the value used for the <b>max</b>
75528 * parameter.
75529 *
75530 * @method limit
75531 * @param {Number} max the maximum magnitude for the vector
75532 * @chainable
75533 * @example
75534 * <div class="norender">
75535 * <code>
75536 * let v = createVector(10, 20, 2);
75537 * // v has components [10.0, 20.0, 2.0]
75538 * v.limit(5);
75539 * // v's components are set to
75540 * // [2.2271771, 4.4543543, 0.4454354]
75541 * </code>
75542 * </div>
75543 * <div>
75544 * <code>
75545 * function draw() {
75546 * background(240);
75547 *
75548 * let v0 = createVector(50, 50);
75549 * let v1 = createVector(mouseX - 50, mouseY - 50);
75550 *
75551 * drawArrow(v0, v1, 'red');
75552 * drawArrow(v0, v1.limit(35), 'blue');
75553 *
75554 * noFill();
75555 * ellipse(50, 50, 35 * 2);
75556 * }
75557 *
75558 * // draw an arrow for a vector at a given base position
75559 * function drawArrow(base, vec, myColor) {
75560 * push();
75561 * stroke(myColor);
75562 * strokeWeight(3);
75563 * fill(myColor);
75564 * translate(base.x, base.y);
75565 * line(0, 0, vec.x, vec.y);
75566 * rotate(vec.heading());
75567 * let arrowSize = 7;
75568 * translate(vec.mag() - arrowSize, 0);
75569 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
75570 * pop();
75571 * }
75572 * </code>
75573 * </div>
75574 */
75575 _main.default.Vector.prototype.limit = function limit(max) {
75576 var mSq = this.magSq();
75577 if (mSq > max * max) {
75578 this.div(Math.sqrt(mSq)) //normalize it
75579 .mult(max);
75580 }
75581 return this;
75582 };
75583
75584 /**
75585 * Set the magnitude of this vector to the value used for the <b>len</b>
75586 * parameter.
75587 *
75588 * @method setMag
75589 * @param {number} len the new length for this vector
75590 * @chainable
75591 * @example
75592 * <div class="norender">
75593 * <code>
75594 * let v = createVector(10, 20, 2);
75595 * // v has components [10.0, 20.0, 2.0]
75596 * v.setMag(10);
75597 * // v's components are set to [6.0, 8.0, 0.0]
75598 * </code>
75599 * </div>
75600 *
75601 * <div>
75602 * <code>
75603 * function draw() {
75604 * background(240);
75605 *
75606 * let v0 = createVector(0, 0);
75607 * let v1 = createVector(50, 50);
75608 *
75609 * drawArrow(v0, v1, 'red');
75610 *
75611 * let length = map(mouseX, 0, width, 0, 141, true);
75612 * v1.setMag(length);
75613 * drawArrow(v0, v1, 'blue');
75614 *
75615 * noStroke();
75616 * text('magnitude set to: ' + length.toFixed(2), 10, 70, 90, 30);
75617 * }
75618 *
75619 * // draw an arrow for a vector at a given base position
75620 * function drawArrow(base, vec, myColor) {
75621 * push();
75622 * stroke(myColor);
75623 * strokeWeight(3);
75624 * fill(myColor);
75625 * translate(base.x, base.y);
75626 * line(0, 0, vec.x, vec.y);
75627 * rotate(vec.heading());
75628 * let arrowSize = 7;
75629 * translate(vec.mag() - arrowSize, 0);
75630 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
75631 * pop();
75632 * }
75633 * </code>
75634 * </div>
75635 */
75636 _main.default.Vector.prototype.setMag = function setMag(n) {
75637 return this.normalize().mult(n);
75638 };
75639
75640 /**
75641 * Calculate the angle of rotation for this vector(only 2D vectors).
75642 * p5.Vectors created using <a src="#/p5/createVector">createVector()</a>
75643 * will take the current <a = src="#/p5/angleMode">angleMode</a> into consideration, and give the angle
75644 * in radians or degree accordingly.
75645 *
75646 * @method heading
75647 * @return {Number} the angle of rotation
75648 * @example
75649 * <div class = "norender">
75650 * <code>
75651 * function setup() {
75652 * let v1 = createVector(30, 50);
75653 * print(v1.heading()); // 1.0303768265243125
75654 *
75655 * v1 = createVector(40, 50);
75656 * print(v1.heading()); // 0.8960553845713439
75657 *
75658 * v1 = createVector(30, 70);
75659 * print(v1.heading()); // 1.1659045405098132
75660 * }
75661 * </code>
75662 * </div>
75663 *
75664 * <div>
75665 * <code>
75666 * function draw() {
75667 * background(240);
75668 *
75669 * let v0 = createVector(50, 50);
75670 * let v1 = createVector(mouseX - 50, mouseY - 50);
75671 *
75672 * drawArrow(v0, v1, 'black');
75673 *
75674 * let myHeading = v1.heading();
75675 * noStroke();
75676 * text(
75677 * 'vector heading: ' +
75678 * myHeading.toFixed(2) +
75679 * ' radians or ' +
75680 * degrees(myHeading).toFixed(2) +
75681 * ' degrees',
75682 * 10,
75683 * 50,
75684 * 90,
75685 * 50
75686 * );
75687 * }
75688 *
75689 * // draw an arrow for a vector at a given base position
75690 * function drawArrow(base, vec, myColor) {
75691 * push();
75692 * stroke(myColor);
75693 * strokeWeight(3);
75694 * fill(myColor);
75695 * translate(base.x, base.y);
75696 * line(0, 0, vec.x, vec.y);
75697 * rotate(vec.heading());
75698 * let arrowSize = 7;
75699 * translate(vec.mag() - arrowSize, 0);
75700 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
75701 * pop();
75702 * }
75703 * </code>
75704 * </div>
75705 */
75706 _main.default.Vector.prototype.heading = function heading() {
75707 var h = Math.atan2(this.y, this.x);
75708 if (this.p5) return this.p5._fromRadians(h);
75709 return h;
75710 };
75711
75712 /**
75713 * Rotate the vector by an angle (only 2D vectors), magnitude remains the
75714 * same
75715 *
75716 * @method rotate
75717 * @param {number} angle the angle of rotation
75718 * @chainable
75719 * @example
75720 * <div class="norender">
75721 * <code>
75722 * let v = createVector(10.0, 20.0);
75723 * // v has components [10.0, 20.0, 0.0]
75724 * v.rotate(HALF_PI);
75725 * // v's components are set to [-20.0, 9.999999, 0.0]
75726 * </code>
75727 * </div>
75728 *
75729 * <div>
75730 * <code>
75731 * let angle = 0;
75732 * function draw() {
75733 * background(240);
75734 *
75735 * let v0 = createVector(50, 50);
75736 * let v1 = createVector(50, 0);
75737 *
75738 * drawArrow(v0, v1.rotate(angle), 'black');
75739 * angle += 0.01;
75740 * }
75741 *
75742 * // draw an arrow for a vector at a given base position
75743 * function drawArrow(base, vec, myColor) {
75744 * push();
75745 * stroke(myColor);
75746 * strokeWeight(3);
75747 * fill(myColor);
75748 * translate(base.x, base.y);
75749 * line(0, 0, vec.x, vec.y);
75750 * rotate(vec.heading());
75751 * let arrowSize = 7;
75752 * translate(vec.mag() - arrowSize, 0);
75753 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
75754 * pop();
75755 * }
75756 * </code>
75757 * </div>
75758 */
75759 _main.default.Vector.prototype.rotate = function rotate(a) {
75760 var newHeading = this.heading() + a;
75761 if (this.p5) newHeading = this.p5._toRadians(newHeading);
75762 var mag = this.mag();
75763 this.x = Math.cos(newHeading) * mag;
75764 this.y = Math.sin(newHeading) * mag;
75765 return this;
75766 };
75767
75768 /**
75769 * Calculates and returns the angle (in radians) between two vectors.
75770 * @method angleBetween
75771 * @param {p5.Vector} value the x, y, and z components of a <a href="#/p5.Vector">p5.Vector</a>
75772 * @return {Number} the angle between (in radians)
75773 * @example
75774 * <div class="norender">
75775 * <code>
75776 * let v1 = createVector(1, 0, 0);
75777 * let v2 = createVector(0, 1, 0);
75778 *
75779 * let angle = v1.angleBetween(v2);
75780 * // angle is PI/2
75781 * print(angle);
75782 * </code>
75783 * </div>
75784 *
75785 * <div>
75786 * <code>
75787 * function draw() {
75788 * background(240);
75789 * let v0 = createVector(50, 50);
75790 *
75791 * let v1 = createVector(50, 0);
75792 * drawArrow(v0, v1, 'red');
75793 *
75794 * let v2 = createVector(mouseX - 50, mouseY - 50);
75795 * drawArrow(v0, v2, 'blue');
75796 *
75797 * let angleBetween = v1.angleBetween(v2);
75798 * noStroke();
75799 * text(
75800 * 'angle between: ' +
75801 * angleBetween.toFixed(2) +
75802 * ' radians or ' +
75803 * degrees(angleBetween).toFixed(2) +
75804 * ' degrees',
75805 * 10,
75806 * 50,
75807 * 90,
75808 * 50
75809 * );
75810 * }
75811 *
75812 * // draw an arrow for a vector at a given base position
75813 * function drawArrow(base, vec, myColor) {
75814 * push();
75815 * stroke(myColor);
75816 * strokeWeight(3);
75817 * fill(myColor);
75818 * translate(base.x, base.y);
75819 * line(0, 0, vec.x, vec.y);
75820 * rotate(vec.heading());
75821 * let arrowSize = 7;
75822 * translate(vec.mag() - arrowSize, 0);
75823 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
75824 * pop();
75825 * }
75826 * </code>
75827 * </div>
75828 */
75829
75830 _main.default.Vector.prototype.angleBetween = function angleBetween(v) {
75831 var dotmagmag = this.dot(v) / (this.mag() * v.mag());
75832 // Mathematically speaking: the dotmagmag variable will be between -1 and 1
75833 // inclusive. Practically though it could be slightly outside this range due
75834 // to floating-point rounding issues. This can make Math.acos return NaN.
75835 //
75836 // Solution: we'll clamp the value to the -1,1 range
75837 var angle;
75838 angle = Math.acos(Math.min(1, Math.max(-1, dotmagmag)));
75839 angle = angle * Math.sign(this.cross(v).z || 1);
75840 if (this.p5) {
75841 angle = this.p5._fromRadians(angle);
75842 }
75843 return angle;
75844 };
75845 /**
75846 * Linear interpolate the vector to another vector
75847 *
75848 * @method lerp
75849 * @param {Number} x the x component
75850 * @param {Number} y the y component
75851 * @param {Number} z the z component
75852 * @param {Number} amt the amount of interpolation; some value between 0.0
75853 * (old vector) and 1.0 (new vector). 0.9 is very near
75854 * the new vector. 0.5 is halfway in between.
75855 * @chainable
75856 *
75857 * @example
75858 * <div class="norender">
75859 * <code>
75860 * let v = createVector(1, 1, 0);
75861 *
75862 * v.lerp(3, 3, 0, 0.5); // v now has components [2,2,0]
75863 * </code>
75864 * </div>
75865 *
75866 * <div class="norender">
75867 * <code>
75868 * let v1 = createVector(0, 0, 0);
75869 * let v2 = createVector(100, 100, 0);
75870 *
75871 * let v3 = p5.Vector.lerp(v1, v2, 0.5);
75872 * // v3 has components [50,50,0]
75873 * print(v3);
75874 * </code>
75875 * </div>
75876 *
75877 * <div>
75878 * <code>
75879 * let step = 0.01;
75880 * let amount = 0;
75881 *
75882 * function draw() {
75883 * background(240);
75884 * let v0 = createVector(0, 0);
75885 *
75886 * let v1 = createVector(mouseX, mouseY);
75887 * drawArrow(v0, v1, 'red');
75888 *
75889 * let v2 = createVector(90, 90);
75890 * drawArrow(v0, v2, 'blue');
75891 *
75892 * if (amount > 1 || amount < 0) {
75893 * step *= -1;
75894 * }
75895 * amount += step;
75896 * let v3 = p5.Vector.lerp(v1, v2, amount);
75897 *
75898 * drawArrow(v0, v3, 'purple');
75899 * }
75900 *
75901 * // draw an arrow for a vector at a given base position
75902 * function drawArrow(base, vec, myColor) {
75903 * push();
75904 * stroke(myColor);
75905 * strokeWeight(3);
75906 * fill(myColor);
75907 * translate(base.x, base.y);
75908 * line(0, 0, vec.x, vec.y);
75909 * rotate(vec.heading());
75910 * let arrowSize = 7;
75911 * translate(vec.mag() - arrowSize, 0);
75912 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
75913 * pop();
75914 * }
75915 * </code>
75916 * </div>
75917 */
75918 /**
75919 * @method lerp
75920 * @param {p5.Vector} v the <a href="#/p5.Vector">p5.Vector</a> to lerp to
75921 * @param {Number} amt
75922 * @chainable
75923 */
75924 _main.default.Vector.prototype.lerp = function lerp(x, y, z, amt) {
75925 if (x instanceof _main.default.Vector) {
75926 return this.lerp(x.x, x.y, x.z, y);
75927 }
75928 this.x += (x - this.x) * amt || 0;
75929 this.y += (y - this.y) * amt || 0;
75930 this.z += (z - this.z) * amt || 0;
75931 return this;
75932 };
75933
75934 /**
75935 * Reflect the incoming vector about a normal to a line in 2D, or about a normal to a plane in 3D
75936 * This method acts on the vector directly
75937 *
75938 * @method reflect
75939 * @param {p5.Vector} surfaceNormal the <a href="#/p5.Vector">p5.Vector</a> to reflect about, will be normalized by this method
75940 * @chainable
75941 * @example
75942 * <div class="norender">
75943 * <code>
75944 * let v = createVector(4, 6); // incoming vector, this example vector is heading to the right and downward
75945 * let n = createVector(0, -1); // surface normal to a plane (this example normal points directly upwards)
75946 * v.reflect(n); // v is reflected about the surface normal n. v's components are now set to [4, -6]
75947 * </code>
75948 * </div>
75949 *
75950 * <div>
75951 * <code>
75952 * function draw() {
75953 * background(240);
75954 *
75955 * let v0 = createVector(0, 0);
75956 * let v1 = createVector(mouseX, mouseY);
75957 * drawArrow(v0, v1, 'red');
75958 *
75959 * let n = createVector(0, -30);
75960 * drawArrow(v1, n, 'blue');
75961 *
75962 * let r = v1.copy();
75963 * r.reflect(n);
75964 * drawArrow(v1, r, 'purple');
75965 * }
75966 *
75967 * // draw an arrow for a vector at a given base position
75968 * function drawArrow(base, vec, myColor) {
75969 * push();
75970 * stroke(myColor);
75971 * strokeWeight(3);
75972 * fill(myColor);
75973 * translate(base.x, base.y);
75974 * line(0, 0, vec.x, vec.y);
75975 * rotate(vec.heading());
75976 * let arrowSize = 7;
75977 * translate(vec.mag() - arrowSize, 0);
75978 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
75979 * pop();
75980 * }
75981 * </code>
75982 * </div>
75983 */
75984 _main.default.Vector.prototype.reflect = function reflect(surfaceNormal) {
75985 surfaceNormal.normalize();
75986 return this.sub(surfaceNormal.mult(2 * this.dot(surfaceNormal)));
75987 };
75988
75989 /**
75990 * Return a representation of this vector as a float array. This is only
75991 * for temporary use. If used in any other fashion, the contents should be
75992 * copied by using the <b>p5.Vector.<a href="#/p5.Vector/copy">copy()</a></b> method to copy into your own
75993 * array.
75994 *
75995 * @method array
75996 * @return {Number[]} an Array with the 3 values
75997 * @example
75998 * <div class = "norender">
75999 * <code>
76000 * function setup() {
76001 * let v = createVector(20, 30);
76002 * print(v.array()); // Prints : Array [20, 30, 0]
76003 * }
76004 * </code>
76005 * </div>
76006 *
76007 * <div class="norender">
76008 * <code>
76009 * let v = createVector(10.0, 20.0, 30.0);
76010 * let f = v.array();
76011 * print(f[0]); // Prints "10.0"
76012 * print(f[1]); // Prints "20.0"
76013 * print(f[2]); // Prints "30.0"
76014 * </code>
76015 * </div>
76016 */
76017 _main.default.Vector.prototype.array = function array() {
76018 return [this.x || 0, this.y || 0, this.z || 0];
76019 };
76020
76021 /**
76022 * Equality check against a <a href="#/p5.Vector">p5.Vector</a>
76023 *
76024 * @method equals
76025 * @param {Number} [x] the x component of the vector
76026 * @param {Number} [y] the y component of the vector
76027 * @param {Number} [z] the z component of the vector
76028 * @return {Boolean} whether the vectors are equals
76029 * @example
76030 * <div class = "norender">
76031 * <code>
76032 * let v1 = createVector(5, 10, 20);
76033 * let v2 = createVector(5, 10, 20);
76034 * let v3 = createVector(13, 10, 19);
76035 *
76036 * print(v1.equals(v2.x, v2.y, v2.z)); // true
76037 * print(v1.equals(v3.x, v3.y, v3.z)); // false
76038 * </code>
76039 * </div>
76040 *
76041 * <div class="norender">
76042 * <code>
76043 * let v1 = createVector(10.0, 20.0, 30.0);
76044 * let v2 = createVector(10.0, 20.0, 30.0);
76045 * let v3 = createVector(0.0, 0.0, 0.0);
76046 * print(v1.equals(v2)); // true
76047 * print(v1.equals(v3)); // false
76048 * </code>
76049 * </div>
76050 */
76051 /**
76052 * @method equals
76053 * @param {p5.Vector|Array} value the vector to compare
76054 * @return {Boolean}
76055 */
76056 _main.default.Vector.prototype.equals = function equals(x, y, z) {
76057 var a, b, c;
76058 if (x instanceof _main.default.Vector) {
76059 a = x.x || 0;
76060 b = x.y || 0;
76061 c = x.z || 0;
76062 } else if (x instanceof Array) {
76063 a = x[0] || 0;
76064 b = x[1] || 0;
76065 c = x[2] || 0;
76066 } else {
76067 a = x || 0;
76068 b = y || 0;
76069 c = z || 0;
76070 }
76071 return this.x === a && this.y === b && this.z === c;
76072 };
76073
76074 // Static Methods
76075
76076 /**
76077 * Make a new 2D vector from an angle
76078 *
76079 * @method fromAngle
76080 * @static
76081 * @param {Number} angle the desired angle, in radians (unaffected by <a href="#/p5/angleMode">angleMode</a>)
76082 * @param {Number} [length] the length of the new vector (defaults to 1)
76083 * @return {p5.Vector} the new <a href="#/p5.Vector">p5.Vector</a> object
76084 * @example
76085 * <div>
76086 * <code>
76087 * function draw() {
76088 * background(200);
76089 *
76090 * // Create a variable, proportional to the mouseX,
76091 * // varying from 0-360, to represent an angle in degrees.
76092 * let myDegrees = map(mouseX, 0, width, 0, 360);
76093 *
76094 * // Display that variable in an onscreen text.
76095 * // (Note the nfc() function to truncate additional decimal places,
76096 * // and the "\xB0" character for the degree symbol.)
76097 * let readout = 'angle = ' + nfc(myDegrees, 1) + '\xB0';
76098 * noStroke();
76099 * fill(0);
76100 * text(readout, 5, 15);
76101 *
76102 * // Create a p5.Vector using the fromAngle function,
76103 * // and extract its x and y components.
76104 * let v = p5.Vector.fromAngle(radians(myDegrees), 30);
76105 * let vx = v.x;
76106 * let vy = v.y;
76107 *
76108 * push();
76109 * translate(width / 2, height / 2);
76110 * noFill();
76111 * stroke(150);
76112 * line(0, 0, 30, 0);
76113 * stroke(0);
76114 * line(0, 0, vx, vy);
76115 * pop();
76116 * }
76117 * </code>
76118 * </div>
76119 */
76120 _main.default.Vector.fromAngle = function fromAngle(angle, length) {
76121 if (typeof length === 'undefined') {
76122 length = 1;
76123 }
76124 return new _main.default.Vector(
76125 length * Math.cos(angle),
76126 length * Math.sin(angle),
76127 0
76128 );
76129 };
76130
76131 /**
76132 * Make a new 3D vector from a pair of ISO spherical angles
76133 *
76134 * @method fromAngles
76135 * @static
76136 * @param {Number} theta the polar angle, in radians (zero is up)
76137 * @param {Number} phi the azimuthal angle, in radians
76138 * (zero is out of the screen)
76139 * @param {Number} [length] the length of the new vector (defaults to 1)
76140 * @return {p5.Vector} the new <a href="#/p5.Vector">p5.Vector</a> object
76141 * @example
76142 * <div modernizr='webgl'>
76143 * <code>
76144 * function setup() {
76145 * createCanvas(100, 100, WEBGL);
76146 * fill(255);
76147 * noStroke();
76148 * }
76149 * function draw() {
76150 * background(255);
76151 *
76152 * let t = millis() / 1000;
76153 *
76154 * // add three point lights
76155 * pointLight(color('#f00'), p5.Vector.fromAngles(t * 1.0, t * 1.3, 100));
76156 * pointLight(color('#0f0'), p5.Vector.fromAngles(t * 1.1, t * 1.2, 100));
76157 * pointLight(color('#00f'), p5.Vector.fromAngles(t * 1.2, t * 1.1, 100));
76158 *
76159 * sphere(35);
76160 * }
76161 * </code>
76162 * </div>
76163 */
76164 _main.default.Vector.fromAngles = function(theta, phi, length) {
76165 if (typeof length === 'undefined') {
76166 length = 1;
76167 }
76168 var cosPhi = Math.cos(phi);
76169 var sinPhi = Math.sin(phi);
76170 var cosTheta = Math.cos(theta);
76171 var sinTheta = Math.sin(theta);
76172
76173 return new _main.default.Vector(
76174 length * sinTheta * sinPhi,
76175 -length * cosTheta,
76176 length * sinTheta * cosPhi
76177 );
76178 };
76179
76180 /**
76181 * Make a new 2D unit vector from a random angle
76182 *
76183 * @method random2D
76184 * @static
76185 * @return {p5.Vector} the new <a href="#/p5.Vector">p5.Vector</a> object
76186 * @example
76187 * <div class="norender">
76188 * <code>
76189 * let v = p5.Vector.random2D();
76190 * // May make v's attributes something like:
76191 * // [0.61554617, -0.51195765, 0.0] or
76192 * // [-0.4695841, -0.14366731, 0.0] or
76193 * // [0.6091097, -0.22805278, 0.0]
76194 * print(v);
76195 * </code>
76196 * </div>
76197 *
76198 * <div>
76199 * <code>
76200 * function setup() {
76201 * frameRate(1);
76202 * }
76203 *
76204 * function draw() {
76205 * background(240);
76206 *
76207 * let v0 = createVector(50, 50);
76208 * let v1 = p5.Vector.random2D();
76209 * drawArrow(v0, v1.mult(50), 'black');
76210 * }
76211 *
76212 * // draw an arrow for a vector at a given base position
76213 * function drawArrow(base, vec, myColor) {
76214 * push();
76215 * stroke(myColor);
76216 * strokeWeight(3);
76217 * fill(myColor);
76218 * translate(base.x, base.y);
76219 * line(0, 0, vec.x, vec.y);
76220 * rotate(vec.heading());
76221 * let arrowSize = 7;
76222 * translate(vec.mag() - arrowSize, 0);
76223 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
76224 * pop();
76225 * }
76226 * </code>
76227 * </div>
76228 */
76229 _main.default.Vector.random2D = function random2D() {
76230 return this.fromAngle(Math.random() * constants.TWO_PI);
76231 };
76232
76233 /**
76234 * Make a new random 3D unit vector.
76235 *
76236 * @method random3D
76237 * @static
76238 * @return {p5.Vector} the new <a href="#/p5.Vector">p5.Vector</a> object
76239 * @example
76240 * <div class="norender">
76241 * <code>
76242 * let v = p5.Vector.random3D();
76243 * // May make v's attributes something like:
76244 * // [0.61554617, -0.51195765, 0.599168] or
76245 * // [-0.4695841, -0.14366731, -0.8711202] or
76246 * // [0.6091097, -0.22805278, -0.7595902]
76247 * print(v);
76248 * </code>
76249 * </div>
76250 */
76251 _main.default.Vector.random3D = function random3D() {
76252 var angle = Math.random() * constants.TWO_PI;
76253 var vz = Math.random() * 2 - 1;
76254 var vzBase = Math.sqrt(1 - vz * vz);
76255 var vx = vzBase * Math.cos(angle);
76256 var vy = vzBase * Math.sin(angle);
76257 return new _main.default.Vector(vx, vy, vz);
76258 };
76259
76260 // Adds two vectors together and returns a new one.
76261 /**
76262 * @method add
76263 * @static
76264 * @param {p5.Vector} v1 a <a href="#/p5.Vector">p5.Vector</a> to add
76265 * @param {p5.Vector} v2 a <a href="#/p5.Vector">p5.Vector</a> to add
76266 * @param {p5.Vector} [target] the vector to receive the result (Optional)
76267 * @return {p5.Vector} the resulting <a href="#/p5.Vector">p5.Vector</a>
76268 */
76269
76270 _main.default.Vector.add = function add(v1, v2, target) {
76271 if (!target) {
76272 target = v1.copy();
76273 if (arguments.length === 3) {
76274 _main.default._friendlyError(
76275 'The target parameter is undefined, it should be of type p5.Vector',
76276 'p5.Vector.add'
76277 );
76278 }
76279 } else {
76280 target.set(v1);
76281 }
76282 target.add(v2);
76283 return target;
76284 };
76285
76286 // Returns a vector remainder when it is divided by another vector
76287 /**
76288 * @method rem
76289 * @static
76290 * @param {p5.Vector} v1 dividend <a href="#/p5.Vector">p5.Vector</a>
76291 * @param {p5.Vector} v2 divisor <a href="#/p5.Vector">p5.Vector</a>
76292 */
76293 /**
76294 * @method rem
76295 * @static
76296 * @param {p5.Vector} v1
76297 * @param {p5.Vector} v2
76298 * @return {p5.Vector} the resulting <a href="#/p5.Vector">p5.Vector</a>
76299 */
76300 _main.default.Vector.rem = function rem(v1, v2) {
76301 if (v1 instanceof _main.default.Vector && v2 instanceof _main.default.Vector) {
76302 var target = v1.copy();
76303 target.rem(v2);
76304 return target;
76305 }
76306 };
76307
76308 /*
76309 * Subtracts one <a href="#/p5.Vector">p5.Vector</a> from another and returns a new one. The second
76310 * vector (v2) is subtracted from the first (v1), resulting in v1-v2.
76311 */
76312 /**
76313 * @method sub
76314 * @static
76315 * @param {p5.Vector} v1 a <a href="#/p5.Vector">p5.Vector</a> to subtract from
76316 * @param {p5.Vector} v2 a <a href="#/p5.Vector">p5.Vector</a> to subtract
76317 * @param {p5.Vector} [target] the vector to receive the result (Optional)
76318 * @return {p5.Vector} the resulting <a href="#/p5.Vector">p5.Vector</a>
76319 */
76320
76321 _main.default.Vector.sub = function sub(v1, v2, target) {
76322 if (!target) {
76323 target = v1.copy();
76324 if (arguments.length === 3) {
76325 _main.default._friendlyError(
76326 'The target parameter is undefined, it should be of type p5.Vector',
76327 'p5.Vector.sub'
76328 );
76329 }
76330 } else {
76331 target.set(v1);
76332 }
76333 target.sub(v2);
76334 return target;
76335 };
76336
76337 /**
76338 * Multiplies a vector by a scalar and returns a new vector.
76339 */
76340
76341 /**
76342 * @method mult
76343 * @static
76344 * @param {Number} x
76345 * @param {Number} y
76346 * @param {Number} [z]
76347 * @return {p5.Vector} The resulting new <a href="#/p5.Vector">p5.Vector</a>
76348 */
76349
76350 /**
76351 * @method mult
76352 * @static
76353 * @param {p5.Vector} v
76354 * @param {Number} n
76355 * @param {p5.Vector} [target] the vector to receive the result (Optional)
76356 */
76357
76358 /**
76359 * @method mult
76360 * @static
76361 * @param {p5.Vector} v0
76362 * @param {p5.Vector} v1
76363 * @param {p5.Vector} [target]
76364 */
76365
76366 /**
76367 * @method mult
76368 * @static
76369 * @param {p5.Vector} v0
76370 * @param {Number[]} arr
76371 * @param {p5.Vector} [target]
76372 */
76373 _main.default.Vector.mult = function mult(v, n, target) {
76374 if (!target) {
76375 target = v.copy();
76376 if (arguments.length === 3) {
76377 _main.default._friendlyError(
76378 'The target parameter is undefined, it should be of type p5.Vector',
76379 'p5.Vector.mult'
76380 );
76381 }
76382 } else {
76383 target.set(v);
76384 }
76385 target.mult(n);
76386 return target;
76387 };
76388
76389 /**
76390 * Divides a vector by a scalar and returns a new vector.
76391 */
76392
76393 /**
76394 * @method div
76395 * @static
76396 * @param {Number} x
76397 * @param {Number} y
76398 * @param {Number} [z]
76399 * @return {p5.Vector} The resulting new <a href="#/p5.Vector">p5.Vector</a>
76400 */
76401
76402 /**
76403 * @method div
76404 * @static
76405 * @param {p5.Vector} v
76406 * @param {Number} n
76407 * @param {p5.Vector} [target] the vector to receive the result (Optional)
76408 */
76409
76410 /**
76411 * @method div
76412 * @static
76413 * @param {p5.Vector} v0
76414 * @param {p5.Vector} v1
76415 * @param {p5.Vector} [target]
76416 */
76417
76418 /**
76419 * @method div
76420 * @static
76421 * @param {p5.Vector} v0
76422 * @param {Number[]} arr
76423 * @param {p5.Vector} [target]
76424 */
76425 _main.default.Vector.div = function div(v, n, target) {
76426 if (!target) {
76427 target = v.copy();
76428
76429 if (arguments.length === 3) {
76430 _main.default._friendlyError(
76431 'The target parameter is undefined, it should be of type p5.Vector',
76432 'p5.Vector.div'
76433 );
76434 }
76435 } else {
76436 target.set(v);
76437 }
76438 target.div(n);
76439 return target;
76440 };
76441
76442 /**
76443 * Calculates the dot product of two vectors.
76444 */
76445 /**
76446 * @method dot
76447 * @static
76448 * @param {p5.Vector} v1 the first <a href="#/p5.Vector">p5.Vector</a>
76449 * @param {p5.Vector} v2 the second <a href="#/p5.Vector">p5.Vector</a>
76450 * @return {Number} the dot product
76451 */
76452 _main.default.Vector.dot = function dot(v1, v2) {
76453 return v1.dot(v2);
76454 };
76455
76456 /**
76457 * Calculates the cross product of two vectors.
76458 */
76459 /**
76460 * @method cross
76461 * @static
76462 * @param {p5.Vector} v1 the first <a href="#/p5.Vector">p5.Vector</a>
76463 * @param {p5.Vector} v2 the second <a href="#/p5.Vector">p5.Vector</a>
76464 * @return {Number} the cross product
76465 */
76466 _main.default.Vector.cross = function cross(v1, v2) {
76467 return v1.cross(v2);
76468 };
76469
76470 /**
76471 * Calculates the Euclidean distance between two points (considering a
76472 * point as a vector object).
76473 */
76474 /**
76475 * @method dist
76476 * @static
76477 * @param {p5.Vector} v1 the first <a href="#/p5.Vector">p5.Vector</a>
76478 * @param {p5.Vector} v2 the second <a href="#/p5.Vector">p5.Vector</a>
76479 * @return {Number} the distance
76480 */
76481 _main.default.Vector.dist = function dist(v1, v2) {
76482 return v1.dist(v2);
76483 };
76484
76485 /**
76486 * Linear interpolate a vector to another vector and return the result as a
76487 * new vector.
76488 */
76489 /**
76490 * @method lerp
76491 * @static
76492 * @param {p5.Vector} v1
76493 * @param {p5.Vector} v2
76494 * @param {Number} amt
76495 * @param {p5.Vector} [target] the vector to receive the result (Optional)
76496 * @return {p5.Vector} the lerped value
76497 */
76498 _main.default.Vector.lerp = function lerp(v1, v2, amt, target) {
76499 if (!target) {
76500 target = v1.copy();
76501 if (arguments.length === 4) {
76502 _main.default._friendlyError(
76503 'The target parameter is undefined, it should be of type p5.Vector',
76504 'p5.Vector.lerp'
76505 );
76506 }
76507 } else {
76508 target.set(v1);
76509 }
76510 target.lerp(v2, amt);
76511 return target;
76512 };
76513
76514 /**
76515 * @method mag
76516 * @param {p5.Vector} vecT the vector to return the magnitude of
76517 * @return {Number} the magnitude of vecT
76518 * @static
76519 */
76520 _main.default.Vector.mag = function mag(vecT) {
76521 var x = vecT.x,
76522 y = vecT.y,
76523 z = vecT.z;
76524 var magSq = x * x + y * y + z * z;
76525 return Math.sqrt(magSq);
76526 };
76527 var _default = _main.default.Vector;
76528 exports.default = _default;
76529 },
76530 { '../core/constants': 43, '../core/main': 54 }
76531 ],
76532 88: [
76533 function(_dereq_, module, exports) {
76534 'use strict';
76535 Object.defineProperty(exports, '__esModule', { value: true });
76536 exports.default = void 0;
76537
76538 var _main = _interopRequireDefault(_dereq_('../core/main'));
76539 function _interopRequireDefault(obj) {
76540 return obj && obj.__esModule ? obj : { default: obj };
76541 } /** // variables used for random number generators
76542 * @module Math
76543 * @submodule Random
76544 * @for p5
76545 * @requires core
76546 */
76547 var randomStateProp = '_lcg_random_state'; // Set to values from http://en.wikipedia.org/wiki/Numerical_Recipes
76548 // m is basically chosen to be large (as it is the max period)
76549 // and for its relationships to a and c
76550 var m = 4294967296; // a - 1 should be divisible by m's prime factors
76551 var a = 1664525; // c and m should be co-prime
76552 var c = 1013904223;
76553 var y2 = 0;
76554
76555 // Linear Congruential Generator that stores its state at instance[stateProperty]
76556 _main.default.prototype._lcg = function(stateProperty) {
76557 // define the recurrence relationship
76558 this[stateProperty] = (a * this[stateProperty] + c) % m;
76559 // return a float in [0, 1)
76560 // we've just used % m, so / m is always < 1
76561 return this[stateProperty] / m;
76562 };
76563
76564 _main.default.prototype._lcgSetSeed = function(stateProperty, val) {
76565 // pick a random seed if val is undefined or null
76566 // the >>> 0 casts the seed to an unsigned 32-bit integer
76567 this[stateProperty] = (val == null ? Math.random() * m : val) >>> 0;
76568 };
76569
76570 /**
76571 * Sets the seed value for <a href="#/p5/random">random()</a>.
76572 *
76573 * By default, <a href="#/p5/random">random()</a> produces different results each time the program
76574 * is run. Set the seed parameter to a constant to return the same
76575 * pseudo-random numbers each time the software is run.
76576 *
76577 * @method randomSeed
76578 * @param {Number} seed the seed value
76579 * @example
76580 * <div>
76581 * <code>
76582 * randomSeed(99);
76583 * for (let i = 0; i < 100; i++) {
76584 * let r = random(0, 255);
76585 * stroke(r);
76586 * line(i, 0, i, 100);
76587 * }
76588 * </code>
76589 * </div>
76590 *
76591 * @alt
76592 * many vertical lines drawn in white, black or grey.
76593 */
76594 _main.default.prototype.randomSeed = function(seed) {
76595 this._lcgSetSeed(randomStateProp, seed);
76596 this._gaussian_previous = false;
76597 };
76598
76599 /**
76600 * Return a random floating-point number.
76601 *
76602 * Takes either 0, 1 or 2 arguments.
76603 *
76604 * If no argument is given, returns a random number from 0
76605 * up to (but not including) 1.
76606 *
76607 * If one argument is given and it is a number, returns a random number from 0
76608 * up to (but not including) the number.
76609 *
76610 * If one argument is given and it is an array, returns a random element from
76611 * that array.
76612 *
76613 * If two arguments are given, returns a random number from the
76614 * first argument up to (but not including) the second argument.
76615 *
76616 * @method random
76617 * @param {Number} [min] the lower bound (inclusive)
76618 * @param {Number} [max] the upper bound (exclusive)
76619 * @return {Number} the random number
76620 * @example
76621 * <div>
76622 * <code>
76623 * for (let i = 0; i < 100; i++) {
76624 * let r = random(50);
76625 * stroke(r * 5);
76626 * line(50, i, 50 + r, i);
76627 * }
76628 * </code>
76629 * </div>
76630 * <div>
76631 * <code>
76632 * for (let i = 0; i < 100; i++) {
76633 * let r = random(-50, 50);
76634 * line(50, i, 50 + r, i);
76635 * }
76636 * </code>
76637 * </div>
76638 * <div>
76639 * <code>
76640 * // Get a random element from an array using the random(Array) syntax
76641 * let words = ['apple', 'bear', 'cat', 'dog'];
76642 * let word = random(words); // select random word
76643 * text(word, 10, 50); // draw the word
76644 * </code>
76645 * </div>
76646 *
76647 * @alt
76648 * 100 horizontal lines from center canvas to right. size+fill change each time
76649 * 100 horizontal lines from center of canvas. height & side change each render
76650 * word displayed at random. Either apple, bear, cat, or dog
76651 */
76652 /**
76653 * @method random
76654 * @param {Array} choices the array to choose from
76655 * @return {*} the random element from the array
76656 * @example
76657 */
76658 _main.default.prototype.random = function(min, max) {
76659 _main.default._validateParameters('random', arguments);
76660 var rand;
76661
76662 if (this[randomStateProp] != null) {
76663 rand = this._lcg(randomStateProp);
76664 } else {
76665 rand = Math.random();
76666 }
76667 if (typeof min === 'undefined') {
76668 return rand;
76669 } else if (typeof max === 'undefined') {
76670 if (min instanceof Array) {
76671 return min[Math.floor(rand * min.length)];
76672 } else {
76673 return rand * min;
76674 }
76675 } else {
76676 if (min > max) {
76677 var tmp = min;
76678 min = max;
76679 max = tmp;
76680 }
76681
76682 return rand * (max - min) + min;
76683 }
76684 };
76685
76686 /**
76687 *
76688 * Returns a random number fitting a Gaussian, or
76689 * normal, distribution. There is theoretically no minimum or maximum
76690 * value that <a href="#/p5/randomGaussian">randomGaussian()</a> might return. Rather, there is
76691 * just a very low probability that values far from the mean will be
76692 * returned; and a higher probability that numbers near the mean will
76693 * be returned.
76694 *
76695 * Takes either 0, 1 or 2 arguments.<br>
76696 * If no args, returns a mean of 0 and standard deviation of 1.<br>
76697 * If one arg, that arg is the mean (standard deviation is 1).<br>
76698 * If two args, first is mean, second is standard deviation.
76699 *
76700 * @method randomGaussian
76701 * @param {Number} mean the mean
76702 * @param {Number} sd the standard deviation
76703 * @return {Number} the random number
76704 * @example
76705 * <div>
76706 * <code>
76707 * for (let y = 0; y < 100; y++) {
76708 * let x = randomGaussian(50, 15);
76709 * line(50, y, x, y);
76710 * }
76711 * </code>
76712 * </div>
76713 * <div>
76714 * <code>
76715 * let distribution = new Array(360);
76716 *
76717 * function setup() {
76718 * createCanvas(100, 100);
76719 * for (let i = 0; i < distribution.length; i++) {
76720 * distribution[i] = floor(randomGaussian(0, 15));
76721 * }
76722 * }
76723 *
76724 * function draw() {
76725 * background(204);
76726 *
76727 * translate(width / 2, width / 2);
76728 *
76729 * for (let i = 0; i < distribution.length; i++) {
76730 * rotate(TWO_PI / distribution.length);
76731 * stroke(0);
76732 * let dist = abs(distribution[i]);
76733 * line(0, 0, dist, 0);
76734 * }
76735 * }
76736 * </code>
76737 * </div>
76738 * @alt
76739 * 100 horizontal lines from center of canvas. height & side change each render
76740 * black lines radiate from center of canvas. size determined each render
76741 */
76742 _main.default.prototype.randomGaussian = function(mean, sd) {
76743 var y1, x1, x2, w;
76744 if (this._gaussian_previous) {
76745 y1 = y2;
76746 this._gaussian_previous = false;
76747 } else {
76748 do {
76749 x1 = this.random(2) - 1;
76750 x2 = this.random(2) - 1;
76751 w = x1 * x1 + x2 * x2;
76752 } while (w >= 1);
76753 w = Math.sqrt(-2 * Math.log(w) / w);
76754 y1 = x1 * w;
76755 y2 = x2 * w;
76756 this._gaussian_previous = true;
76757 }
76758
76759 var m = mean || 0;
76760 var s = sd || 1;
76761 return y1 * s + m;
76762 };
76763 var _default = _main.default;
76764 exports.default = _default;
76765 },
76766 { '../core/main': 54 }
76767 ],
76768 89: [
76769 function(_dereq_, module, exports) {
76770 'use strict';
76771 function _typeof(obj) {
76772 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
76773 _typeof = function _typeof(obj) {
76774 return typeof obj;
76775 };
76776 } else {
76777 _typeof = function _typeof(obj) {
76778 return obj &&
76779 typeof Symbol === 'function' &&
76780 obj.constructor === Symbol &&
76781 obj !== Symbol.prototype
76782 ? 'symbol'
76783 : typeof obj;
76784 };
76785 }
76786 return _typeof(obj);
76787 }
76788 Object.defineProperty(exports, '__esModule', { value: true });
76789 exports.default = void 0;
76790
76791 var _main = _interopRequireDefault(_dereq_('../core/main'));
76792 var constants = _interopRequireWildcard(_dereq_('../core/constants'));
76793 function _getRequireWildcardCache() {
76794 if (typeof WeakMap !== 'function') return null;
76795 var cache = new WeakMap();
76796 _getRequireWildcardCache = function _getRequireWildcardCache() {
76797 return cache;
76798 };
76799 return cache;
76800 }
76801 function _interopRequireWildcard(obj) {
76802 if (obj && obj.__esModule) {
76803 return obj;
76804 }
76805 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) {
76806 return { default: obj };
76807 }
76808 var cache = _getRequireWildcardCache();
76809 if (cache && cache.has(obj)) {
76810 return cache.get(obj);
76811 }
76812 var newObj = {};
76813 var hasPropertyDescriptor =
76814 Object.defineProperty && Object.getOwnPropertyDescriptor;
76815 for (var key in obj) {
76816 if (Object.prototype.hasOwnProperty.call(obj, key)) {
76817 var desc = hasPropertyDescriptor
76818 ? Object.getOwnPropertyDescriptor(obj, key)
76819 : null;
76820 if (desc && (desc.get || desc.set)) {
76821 Object.defineProperty(newObj, key, desc);
76822 } else {
76823 newObj[key] = obj[key];
76824 }
76825 }
76826 }
76827 newObj.default = obj;
76828 if (cache) {
76829 cache.set(obj, newObj);
76830 }
76831 return newObj;
76832 }
76833 function _interopRequireDefault(obj) {
76834 return obj && obj.__esModule ? obj : { default: obj };
76835 }
76836 /**
76837 * @module Math
76838 * @submodule Trigonometry
76839 * @for p5
76840 * @requires core
76841 * @requires constants
76842 */ /*
76843 * all DEGREES/RADIANS conversion should be done in the p5 instance
76844 * if possible, using the p5._toRadians(), p5._fromRadians() methods.
76845 */ _main.default.prototype._angleMode =
76846 constants.RADIANS;
76847 /**
76848 * The inverse of <a href="#/p5/cos">cos()</a>, returns the arc cosine of a value.
76849 * This function expects the values in the range of -1 to 1 and values are returned in
76850 * the range 0 to PI (3.1415927) if the angleMode is RADIANS or 0 to 180 if the
76851 * angle mode is DEGREES.
76852 *
76853 * @method acos
76854 * @param {Number} value the value whose arc cosine is to be returned
76855 * @return {Number} the arc cosine of the given value
76856 *
76857 * @example
76858 * <div class= “norender">
76859 * <code>
76860 * let a = PI;
76861 * let c = cos(a);
76862 * let ac = acos(c);
76863 * // Prints: "3.1415927 : -1.0 : 3.1415927"
76864 * print(a + ' : ' + c + ' : ' + ac);
76865 * </code>
76866 * </div>
76867 *
76868 * <div class= “norender">
76869 * <code>
76870 * let a = PI + PI / 4.0;
76871 * let c = cos(a);
76872 * let ac = acos(c);
76873 * // Prints: "3.926991 : -0.70710665 : 2.3561943"
76874 * print(a + ' : ' + c + ' : ' + ac);
76875 * </code>
76876 * </div>
76877 */ _main.default.prototype.acos = function(ratio) {
76878 return this._fromRadians(Math.acos(ratio));
76879 };
76880
76881 /**
76882 * The inverse of <a href="#/p5/sin">sin()</a>, returns the arc sine of a value.
76883 * This function expects the values in the range of -1 to 1 and values are returned
76884 * in the range -PI/2 to PI/2 if the angleMode is RADIANS or -90 to 90 if the angle
76885 * mode is DEGREES.
76886 *
76887 * @method asin
76888 * @param {Number} value the value whose arc sine is to be returned
76889 * @return {Number} the arc sine of the given value
76890 *
76891 * @example
76892 * <div class= “norender">
76893 * <code>
76894 * let a = PI / 3.0;
76895 * let s = sin(a);
76896 * let as = asin(s);
76897 * // Prints: "1.0471975 : 0.86602540 : 1.0471975"
76898 * print(a + ' : ' + s + ' : ' + as);
76899 * </code>
76900 * </div>
76901 *
76902 * <div class= “norender">
76903 * <code>
76904 * let a = PI + PI / 3.0;
76905 * let s = sin(a);
76906 * let as = asin(s);
76907 * // Prints: "4.1887902 : -0.86602540 : -1.0471975"
76908 * print(a + ' : ' + s + ' : ' + as);
76909 * </code>
76910 * </div>
76911 */
76912 _main.default.prototype.asin = function(ratio) {
76913 return this._fromRadians(Math.asin(ratio));
76914 };
76915
76916 /**
76917 * The inverse of <a href="#/p5/tan">tan()</a>, returns the arc tangent of a value.
76918 * This function expects the values in the range of -Infinity to Infinity (exclusive) and
76919 * values are returned in the range -PI/2 to PI/2 if the angleMode is RADIANS or
76920 * -90 to 90 if the angle mode is DEGREES.
76921 *
76922 * @method atan
76923 * @param {Number} value the value whose arc tangent is to be returned
76924 * @return {Number} the arc tangent of the given value
76925 *
76926 * @example
76927 * <div class= “norender">
76928 * <code>
76929 * let a = PI / 3.0;
76930 * let t = tan(a);
76931 * let at = atan(t);
76932 * // Prints: "1.0471975 : 1.7320508 : 1.0471975"
76933 * print(a + ' : ' + t + ' : ' + at);
76934 * </code>
76935 * </div>
76936 *
76937 * <div class= “norender">
76938 * <code>
76939 * let a = PI + PI / 3.0;
76940 * let t = tan(a);
76941 * let at = atan(t);
76942 * // Prints: "4.1887902 : 1.7320508 : 1.0471975"
76943 * print(a + ' : ' + t + ' : ' + at);
76944 * </code>
76945 * </div>
76946 */
76947 _main.default.prototype.atan = function(ratio) {
76948 return this._fromRadians(Math.atan(ratio));
76949 };
76950
76951 /**
76952 * Calculates the angle (in radians) from a specified point to the coordinate
76953 * origin as measured from the positive x-axis. Values are returned as a
76954 * float in the range from PI to -PI if the angleMode is RADIANS or 180 to
76955 * -180 if the angleMode is DEGREES. The atan2<a href="#/p5/">()</a> function is
76956 * most often used for orienting geometry to the position of the cursor.
76957 *
76958 * Note: The y-coordinate of the point is the first parameter, and the
76959 * x-coordinate is the second parameter, due the the structure of calculating
76960 * the tangent.
76961 *
76962 * @method atan2
76963 * @param {Number} y y-coordinate of the point
76964 * @param {Number} x x-coordinate of the point
76965 * @return {Number} the arc tangent of the given point
76966 *
76967 * @example
76968 * <div>
76969 * <code>
76970 * function draw() {
76971 * background(204);
76972 * translate(width / 2, height / 2);
76973 * let a = atan2(mouseY - height / 2, mouseX - width / 2);
76974 * rotate(a);
76975 * rect(-30, -5, 60, 10);
76976 * }
76977 * </code>
76978 * </div>
76979 *
76980 * @alt
76981 * 60 by 10 rect at center of canvas rotates with mouse movements
76982 */
76983 _main.default.prototype.atan2 = function(y, x) {
76984 return this._fromRadians(Math.atan2(y, x));
76985 };
76986
76987 /**
76988 * Calculates the cosine of an angle. This function takes into account the
76989 * current <a href="#/p5/angleMode">angleMode</a>. Values are returned in the range -1 to 1.
76990 *
76991 * @method cos
76992 * @param {Number} angle the angle
76993 * @return {Number} the cosine of the angle
76994 *
76995 * @example
76996 * <div>
76997 * <code>
76998 * let a = 0.0;
76999 * let inc = TWO_PI / 25.0;
77000 * for (let i = 0; i < 25; i++) {
77001 * line(i * 4, 50, i * 4, 50 + cos(a) * 40.0);
77002 * a = a + inc;
77003 * }
77004 * </code>
77005 * </div>
77006 *
77007 * @alt
77008 * vertical black lines form wave patterns, extend-down on left and right side
77009 */
77010 _main.default.prototype.cos = function(angle) {
77011 return Math.cos(this._toRadians(angle));
77012 };
77013
77014 /**
77015 * Calculates the sine of an angle. This function takes into account the
77016 * current <a href="#/p5/angleMode">angleMode</a>. Values are returned in the range -1 to 1.
77017 *
77018 * @method sin
77019 * @param {Number} angle the angle
77020 * @return {Number} the sine of the angle
77021 *
77022 * @example
77023 * <div>
77024 * <code>
77025 * let a = 0.0;
77026 * let inc = TWO_PI / 25.0;
77027 * for (let i = 0; i < 25; i++) {
77028 * line(i * 4, 50, i * 4, 50 + sin(a) * 40.0);
77029 * a = a + inc;
77030 * }
77031 * </code>
77032 * </div>
77033 *
77034 * @alt
77035 * vertical black lines extend down and up from center to form wave pattern
77036 */
77037 _main.default.prototype.sin = function(angle) {
77038 return Math.sin(this._toRadians(angle));
77039 };
77040
77041 /**
77042 * Calculates the tangent of an angle. This function takes into account
77043 * the current <a href="#/p5/angleMode">angleMode</a>. Values are returned in the range of all real numbers.
77044 *
77045 * @method tan
77046 * @param {Number} angle the angle
77047 * @return {Number} the tangent of the angle
77048 *
77049 * @example
77050 * <div>
77051 * <code>
77052 * let a = 0.0;
77053 * let inc = TWO_PI / 50.0;
77054 * for (let i = 0; i < 100; i = i + 2) {
77055 * line(i, 50, i, 50 + tan(a) * 2.0);
77056 * a = a + inc;
77057 * }
77058 * </code>
77059 *
77060 * @alt
77061 * vertical black lines end down and up from center to form spike pattern
77062 */
77063 _main.default.prototype.tan = function(angle) {
77064 return Math.tan(this._toRadians(angle));
77065 };
77066
77067 /**
77068 * Converts a radian measurement to its corresponding value in degrees.
77069 * Radians and degrees are two ways of measuring the same thing. There are
77070 * 360 degrees in a circle and 2*PI radians in a circle. For example,
77071 * 90° = PI/2 = 1.5707964. This function does not take into account the
77072 * current <a href="#/p5/angleMode">angleMode</a>.
77073 *
77074 * @method degrees
77075 * @param {Number} radians the radians value to convert to degrees
77076 * @return {Number} the converted angle
77077 *
77078 * @example
77079 * <div class= “norender">
77080 * <code>
77081 * let rad = PI / 4;
77082 * let deg = degrees(rad);
77083 * print(rad + ' radians is ' + deg + ' degrees');
77084 * // Prints: 0.7853981633974483 radians is 45 degrees
77085 * </code>
77086 * </div>
77087 */
77088 _main.default.prototype.degrees = function(angle) {
77089 return angle * constants.RAD_TO_DEG;
77090 };
77091
77092 /**
77093 * Converts a degree measurement to its corresponding value in radians.
77094 * Radians and degrees are two ways of measuring the same thing. There are
77095 * 360 degrees in a circle and 2*PI radians in a circle. For example,
77096 * 90° = PI/2 = 1.5707964. This function does not take into account the
77097 * current <a href="#/p5/angleMode">angleMode</a>.
77098 *
77099 * @method radians
77100 * @param {Number} degrees the degree value to convert to radians
77101 * @return {Number} the converted angle
77102 *
77103 * @example
77104 * <div class= “norender">
77105 * <code>
77106 * let deg = 45.0;
77107 * let rad = radians(deg);
77108 * print(deg + ' degrees is ' + rad + ' radians');
77109 * // Prints: 45 degrees is 0.7853981633974483 radians
77110 * </code>
77111 * </div>
77112 */
77113 _main.default.prototype.radians = function(angle) {
77114 return angle * constants.DEG_TO_RAD;
77115 };
77116
77117 /**
77118 * Sets the current mode of p5 to given mode. Default mode is RADIANS.
77119 *
77120 * @method angleMode
77121 * @param {Constant} mode either RADIANS or DEGREES
77122 *
77123 * @example
77124 * <div>
77125 * <code>
77126 * function draw() {
77127 * background(204);
77128 * angleMode(DEGREES); // Change the mode to DEGREES
77129 * let a = atan2(mouseY - height / 2, mouseX - width / 2);
77130 * translate(width / 2, height / 2);
77131 * push();
77132 * rotate(a);
77133 * rect(-20, -5, 40, 10); // Larger rectangle is rotating in degrees
77134 * pop();
77135 * angleMode(RADIANS); // Change the mode to RADIANS
77136 * rotate(a); // variable a stays the same
77137 * rect(-40, -5, 20, 10); // Smaller rectangle is rotating in radians
77138 * }
77139 * </code>
77140 * </div>
77141 *
77142 * @alt
77143 * 40 by 10 rect in center rotates with mouse moves. 20 by 10 rect moves faster.
77144 *
77145 */
77146 _main.default.prototype.angleMode = function(mode) {
77147 if (mode === constants.DEGREES || mode === constants.RADIANS) {
77148 this._angleMode = mode;
77149 }
77150 };
77151
77152 /**
77153 * converts angles from the current angleMode to RADIANS
77154 *
77155 * @method _toRadians
77156 * @private
77157 * @param {Number} angle
77158 * @returns {Number}
77159 */
77160 _main.default.prototype._toRadians = function(angle) {
77161 if (this._angleMode === constants.DEGREES) {
77162 return angle * constants.DEG_TO_RAD;
77163 }
77164 return angle;
77165 };
77166
77167 /**
77168 * converts angles from the current angleMode to DEGREES
77169 *
77170 * @method _toDegrees
77171 * @private
77172 * @param {Number} angle
77173 * @returns {Number}
77174 */
77175 _main.default.prototype._toDegrees = function(angle) {
77176 if (this._angleMode === constants.RADIANS) {
77177 return angle * constants.RAD_TO_DEG;
77178 }
77179 return angle;
77180 };
77181
77182 /**
77183 * converts angles from RADIANS into the current angleMode
77184 *
77185 * @method _fromRadians
77186 * @private
77187 * @param {Number} angle
77188 * @returns {Number}
77189 */
77190 _main.default.prototype._fromRadians = function(angle) {
77191 if (this._angleMode === constants.DEGREES) {
77192 return angle * constants.RAD_TO_DEG;
77193 }
77194 return angle;
77195 };
77196 var _default = _main.default;
77197 exports.default = _default;
77198 },
77199 { '../core/constants': 43, '../core/main': 54 }
77200 ],
77201 90: [
77202 function(_dereq_, module, exports) {
77203 'use strict';
77204 Object.defineProperty(exports, '__esModule', { value: true });
77205 exports.default = void 0;
77206
77207 var _main = _interopRequireDefault(_dereq_('../core/main'));
77208 function _interopRequireDefault(obj) {
77209 return obj && obj.__esModule ? obj : { default: obj };
77210 }
77211 /**
77212 * @module Typography
77213 * @submodule Attributes
77214 * @for p5
77215 * @requires core
77216 * @requires constants
77217 */ /**
77218 * Sets the current alignment for drawing text. Accepts two
77219 * arguments: horizAlign (LEFT, CENTER, or RIGHT) and
77220 * vertAlign (TOP, BOTTOM, CENTER, or BASELINE).
77221 *
77222 * The horizAlign parameter is in reference to the x value
77223 * of the <a href="#/p5/text">text()</a> function, while the vertAlign parameter
77224 * is in reference to the y value.
77225 *
77226 * So if you write textAlign(LEFT), you are aligning the left
77227 * edge of your text to the x value you give in <a href="#/p5/text">text()</a>.
77228 * If you write textAlign(RIGHT, TOP), you are aligning the right edge
77229 * of your text to the x value and the top of edge of the text
77230 * to the y value.
77231 *
77232 * @method textAlign
77233 * @param {Constant} horizAlign horizontal alignment, either LEFT,
77234 * CENTER, or RIGHT
77235 * @param {Constant} [vertAlign] vertical alignment, either TOP,
77236 * BOTTOM, CENTER, or BASELINE
77237 * @chainable
77238 * @example
77239 * <div>
77240 * <code>
77241 * textSize(16);
77242 * textAlign(RIGHT);
77243 * text('ABCD', 50, 30);
77244 * textAlign(CENTER);
77245 * text('EFGH', 50, 50);
77246 * textAlign(LEFT);
77247 * text('IJKL', 50, 70);
77248 * </code>
77249 * </div>
77250 *
77251 * <div>
77252 * <code>
77253 * textSize(16);
77254 * strokeWeight(0.5);
77255 *
77256 * line(0, 12, width, 12);
77257 * textAlign(CENTER, TOP);
77258 * text('TOP', 0, 12, width);
77259 *
77260 * line(0, 37, width, 37);
77261 * textAlign(CENTER, CENTER);
77262 * text('CENTER', 0, 37, width);
77263 *
77264 * line(0, 62, width, 62);
77265 * textAlign(CENTER, BASELINE);
77266 * text('BASELINE', 0, 62, width);
77267 *
77268 * line(0, 87, width, 87);
77269 * textAlign(CENTER, BOTTOM);
77270 * text('BOTTOM', 0, 87, width);
77271 * </code>
77272 * </div>
77273 *
77274 * @alt
77275 * Letters ABCD displayed at top left, EFGH at center and IJKL at bottom right.
77276 * The names of the four vertical alignments (TOP, CENTER, BASELINE & BOTTOM) rendered each showing that alignment's placement relative to a horizontal line.
77277 */ /**
77278 * @method textAlign
77279 * @return {Object}
77280 */ _main.default.prototype.textAlign = function(horizAlign, vertAlign) {
77281 var _this$_renderer;
77282 _main.default._validateParameters('textAlign', arguments);
77283 return (_this$_renderer = this._renderer).textAlign.apply(
77284 _this$_renderer,
77285 arguments
77286 );
77287 };
77288
77289 /**
77290 * Sets/gets the spacing, in pixels, between lines of text. This setting will be
77291 * used in all subsequent calls to the <a href="#/p5/text">text()</a> function.
77292 *
77293 * @method textLeading
77294 * @param {Number} leading the size in pixels for spacing between lines
77295 * @chainable
77296 *
77297 * @example
77298 * <div>
77299 * <code>
77300 * let lines = 'L1\nL2\nL3'; // "\n" is a "new line" character
77301 * textSize(12);
77302 *
77303 * textLeading(10);
77304 * text(lines, 10, 25);
77305 *
77306 * textLeading(20);
77307 * text(lines, 40, 25);
77308 *
77309 * textLeading(30);
77310 * text(lines, 70, 25);
77311 * </code>
77312 * </div>
77313 *
77314 * @alt
77315 * A set of L1 L2 & L3 displayed vertically 3 times. spacing increases for each set
77316 */
77317 /**
77318 * @method textLeading
77319 * @return {Number}
77320 */
77321 _main.default.prototype.textLeading = function(theLeading) {
77322 var _this$_renderer2;
77323 _main.default._validateParameters('textLeading', arguments);
77324 return (_this$_renderer2 = this._renderer).textLeading.apply(
77325 _this$_renderer2,
77326 arguments
77327 );
77328 };
77329
77330 /**
77331 * Sets/gets the current font size. This size will be used in all subsequent
77332 * calls to the <a href="#/p5/text">text()</a> function. Font size is measured in pixels.
77333 *
77334 * @method textSize
77335 * @param {Number} theSize the size of the letters in units of pixels
77336 * @chainable
77337 *
77338 * @example
77339 * <div>
77340 * <code>
77341 * textSize(12);
77342 * text('Font Size 12', 10, 30);
77343 * textSize(14);
77344 * text('Font Size 14', 10, 60);
77345 * textSize(16);
77346 * text('Font Size 16', 10, 90);
77347 * </code>
77348 * </div>
77349 *
77350 * @alt
77351 * 'Font Size 12' displayed small, 'Font Size 14' medium & 'Font Size 16' large
77352 */
77353 /**
77354 * @method textSize
77355 * @return {Number}
77356 */
77357 _main.default.prototype.textSize = function(theSize) {
77358 var _this$_renderer3;
77359 _main.default._validateParameters('textSize', arguments);
77360 return (_this$_renderer3 = this._renderer).textSize.apply(
77361 _this$_renderer3,
77362 arguments
77363 );
77364 };
77365
77366 /**
77367 * Sets/gets the style of the text for system fonts to NORMAL, ITALIC, BOLD or BOLDITALIC.
77368 * Note: this may be is overridden by CSS styling. For non-system fonts
77369 * (opentype, truetype, etc.) please load styled fonts instead.
77370 *
77371 * @method textStyle
77372 * @param {Constant} theStyle styling for text, either NORMAL,
77373 * ITALIC, BOLD or BOLDITALIC
77374 * @chainable
77375 * @example
77376 * <div>
77377 * <code>
77378 * strokeWeight(0);
77379 * textSize(12);
77380 * textStyle(NORMAL);
77381 * text('Font Style Normal', 10, 15);
77382 * textStyle(ITALIC);
77383 * text('Font Style Italic', 10, 40);
77384 * textStyle(BOLD);
77385 * text('Font Style Bold', 10, 65);
77386 * textStyle(BOLDITALIC);
77387 * text('Font Style Bold Italic', 10, 90);
77388 * </code>
77389 * </div>
77390 *
77391 * @alt
77392 * Words Font Style Normal displayed normally, Italic in italic, bold in bold and bold italic in bold italics.
77393 */
77394 /**
77395 * @method textStyle
77396 * @return {String}
77397 */
77398 _main.default.prototype.textStyle = function(theStyle) {
77399 var _this$_renderer4;
77400 _main.default._validateParameters('textStyle', arguments);
77401 return (_this$_renderer4 = this._renderer).textStyle.apply(
77402 _this$_renderer4,
77403 arguments
77404 );
77405 };
77406
77407 /**
77408 * Calculates and returns the width of any character or text string.
77409 *
77410 * @method textWidth
77411 * @param {String} theText the String of characters to measure
77412 * @return {Number} the calculated width
77413 * @example
77414 * <div>
77415 * <code>
77416 * textSize(28);
77417 *
77418 * let aChar = 'P';
77419 * let cWidth = textWidth(aChar);
77420 * text(aChar, 0, 40);
77421 * line(cWidth, 0, cWidth, 50);
77422 *
77423 * let aString = 'p5.js';
77424 * let sWidth = textWidth(aString);
77425 * text(aString, 0, 85);
77426 * line(sWidth, 50, sWidth, 100);
77427 * </code>
77428 * </div>
77429 *
77430 * @alt
77431 * Letter P and p5.js are displayed with vertical lines at end.
77432 */
77433 _main.default.prototype.textWidth = function() {
77434 var _this$_renderer5;
77435 for (
77436 var _len = arguments.length, args = new Array(_len), _key = 0;
77437 _key < _len;
77438 _key++
77439 ) {
77440 args[_key] = arguments[_key];
77441 }
77442 args[0] += '';
77443 _main.default._validateParameters('textWidth', args);
77444 if (args[0].length === 0) {
77445 return 0;
77446 }
77447 return (_this$_renderer5 = this._renderer).textWidth.apply(
77448 _this$_renderer5,
77449 args
77450 );
77451 };
77452
77453 /**
77454 * Returns the ascent of the current font at its current size. The ascent
77455 * represents the distance, in pixels, of the tallest character above
77456 * the baseline.
77457 * @method textAscent
77458 * @return {Number}
77459 * @example
77460 * <div>
77461 * <code>
77462 * let base = height * 0.75;
77463 * let scalar = 0.8; // Different for each font
77464 *
77465 * textSize(32); // Set initial text size
77466 * let asc = textAscent() * scalar; // Calc ascent
77467 * line(0, base - asc, width, base - asc);
77468 * text('dp', 0, base); // Draw text on baseline
77469 *
77470 * textSize(64); // Increase text size
77471 * asc = textAscent() * scalar; // Recalc ascent
77472 * line(40, base - asc, width, base - asc);
77473 * text('dp', 40, base); // Draw text on baseline
77474 * </code>
77475 * </div>
77476 */
77477 _main.default.prototype.textAscent = function() {
77478 for (
77479 var _len2 = arguments.length, args = new Array(_len2), _key2 = 0;
77480 _key2 < _len2;
77481 _key2++
77482 ) {
77483 args[_key2] = arguments[_key2];
77484 }
77485 _main.default._validateParameters('textAscent', args);
77486 return this._renderer.textAscent();
77487 };
77488
77489 /**
77490 * Returns the descent of the current font at its current size. The descent
77491 * represents the distance, in pixels, of the character with the longest
77492 * descender below the baseline.
77493 * @method textDescent
77494 * @return {Number}
77495 * @example
77496 * <div>
77497 * <code>
77498 * let base = height * 0.75;
77499 * let scalar = 0.8; // Different for each font
77500 *
77501 * textSize(32); // Set initial text size
77502 * let desc = textDescent() * scalar; // Calc ascent
77503 * line(0, base + desc, width, base + desc);
77504 * text('dp', 0, base); // Draw text on baseline
77505 *
77506 * textSize(64); // Increase text size
77507 * desc = textDescent() * scalar; // Recalc ascent
77508 * line(40, base + desc, width, base + desc);
77509 * text('dp', 40, base); // Draw text on baseline
77510 * </code>
77511 * </div>
77512 */
77513 _main.default.prototype.textDescent = function() {
77514 for (
77515 var _len3 = arguments.length, args = new Array(_len3), _key3 = 0;
77516 _key3 < _len3;
77517 _key3++
77518 ) {
77519 args[_key3] = arguments[_key3];
77520 }
77521 _main.default._validateParameters('textDescent', args);
77522 return this._renderer.textDescent();
77523 };
77524
77525 /**
77526 * Helper function to measure ascent and descent.
77527 */
77528 _main.default.prototype._updateTextMetrics = function() {
77529 return this._renderer._updateTextMetrics();
77530 };
77531 var _default = _main.default;
77532 exports.default = _default;
77533 },
77534 { '../core/main': 54 }
77535 ],
77536 91: [
77537 function(_dereq_, module, exports) {
77538 'use strict';
77539 function _typeof(obj) {
77540 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
77541 _typeof = function _typeof(obj) {
77542 return typeof obj;
77543 };
77544 } else {
77545 _typeof = function _typeof(obj) {
77546 return obj &&
77547 typeof Symbol === 'function' &&
77548 obj.constructor === Symbol &&
77549 obj !== Symbol.prototype
77550 ? 'symbol'
77551 : typeof obj;
77552 };
77553 }
77554 return _typeof(obj);
77555 }
77556 Object.defineProperty(exports, '__esModule', { value: true });
77557 exports.default = void 0;
77558
77559 var _main = _interopRequireDefault(_dereq_('../core/main'));
77560 var constants = _interopRequireWildcard(_dereq_('../core/constants'));
77561 var opentype = _interopRequireWildcard(_dereq_('opentype.js'));
77562
77563 _dereq_('../core/friendly_errors/validate_params');
77564 _dereq_('../core/friendly_errors/file_errors');
77565 _dereq_('../core/friendly_errors/fes_core');
77566 function _getRequireWildcardCache() {
77567 if (typeof WeakMap !== 'function') return null;
77568 var cache = new WeakMap();
77569 _getRequireWildcardCache = function _getRequireWildcardCache() {
77570 return cache;
77571 };
77572 return cache;
77573 }
77574 function _interopRequireWildcard(obj) {
77575 if (obj && obj.__esModule) {
77576 return obj;
77577 }
77578 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) {
77579 return { default: obj };
77580 }
77581 var cache = _getRequireWildcardCache();
77582 if (cache && cache.has(obj)) {
77583 return cache.get(obj);
77584 }
77585 var newObj = {};
77586 var hasPropertyDescriptor =
77587 Object.defineProperty && Object.getOwnPropertyDescriptor;
77588 for (var key in obj) {
77589 if (Object.prototype.hasOwnProperty.call(obj, key)) {
77590 var desc = hasPropertyDescriptor
77591 ? Object.getOwnPropertyDescriptor(obj, key)
77592 : null;
77593 if (desc && (desc.get || desc.set)) {
77594 Object.defineProperty(newObj, key, desc);
77595 } else {
77596 newObj[key] = obj[key];
77597 }
77598 }
77599 }
77600 newObj.default = obj;
77601 if (cache) {
77602 cache.set(obj, newObj);
77603 }
77604 return newObj;
77605 }
77606 function _interopRequireDefault(obj) {
77607 return obj && obj.__esModule ? obj : { default: obj };
77608 }
77609 /**
77610 * @module Typography
77611 * @submodule Loading & Displaying
77612 * @for p5
77613 * @requires core
77614 */ /**
77615 * Loads an opentype font file (.otf, .ttf) from a file or a URL,
77616 * and returns a PFont Object. This method is asynchronous,
77617 * meaning it may not finish before the next line in your sketch
77618 * is executed.
77619 *
77620 * The path to the font should be relative to the HTML file
77621 * that links in your sketch. Loading fonts from a URL or other
77622 * remote location may be blocked due to your browser's built-in
77623 * security.
77624 *
77625 * @method loadFont
77626 * @param {String} path name of the file or url to load
77627 * @param {Function} [callback] function to be executed after
77628 * <a href="#/p5/loadFont">loadFont()</a> completes
77629 * @param {Function} [onError] function to be executed if
77630 * an error occurs
77631 * @return {p5.Font} <a href="#/p5.Font">p5.Font</a> object
77632 * @example
77633 *
77634 * Calling loadFont() inside <a href="#/p5/preload">preload()</a> guarantees
77635 * that the load operation will have completed before <a href="#/p5/setup">setup()</a>
77636 * and <a href="#/p5/draw">draw()</a> are called.
77637 *
77638 * <div><code>
77639 * let myFont;
77640 * function preload() {
77641 * myFont = loadFont('assets/inconsolata.otf');
77642 * }
77643 *
77644 * function setup() {
77645 * fill('#ED225D');
77646 * textFont(myFont);
77647 * textSize(36);
77648 * text('p5*js', 10, 50);
77649 * }
77650 * </code></div>
77651 *
77652 * Outside of <a href="#/p5/preload">preload()</a>, you may supply a
77653 * callback function to handle the object:
77654 *
77655 * <div><code>
77656 * function setup() {
77657 * loadFont('assets/inconsolata.otf', drawText);
77658 * }
77659 *
77660 * function drawText(font) {
77661 * fill('#ED225D');
77662 * textFont(font, 36);
77663 * text('p5*js', 10, 50);
77664 * }
77665 * </code></div>
77666 *
77667 * You can also use the font filename string (without the file extension) to
77668 * style other HTML elements.
77669 *
77670 * <div><code>
77671 * function preload() {
77672 * loadFont('assets/inconsolata.otf');
77673 * }
77674 *
77675 * function setup() {
77676 * let myDiv = createDiv('hello there');
77677 * myDiv.style('font-family', 'Inconsolata');
77678 * }
77679 * </code></div>
77680 *
77681 * @alt
77682 * p5*js in p5's theme dark pink
77683 * p5*js in p5's theme dark pink
77684 */ _main.default.prototype.loadFont = function(path, onSuccess, onError) {
77685 _main.default._validateParameters('loadFont', arguments);
77686 var p5Font = new _main.default.Font(this);
77687
77688 var self = this;
77689 opentype.load(path, function(err, font) {
77690 if (err) {
77691 _main.default._friendlyFileLoadError(4, path);
77692 if (typeof onError !== 'undefined') {
77693 return onError(err);
77694 }
77695 console.error(err, path);
77696 return;
77697 }
77698
77699 p5Font.font = font;
77700
77701 if (typeof onSuccess !== 'undefined') {
77702 onSuccess(p5Font);
77703 }
77704
77705 self._decrementPreload();
77706
77707 // check that we have an acceptable font type
77708 var validFontTypes = ['ttf', 'otf', 'woff', 'woff2'];
77709
77710 var fileNoPath = path
77711 .split('\\')
77712 .pop()
77713 .split('/')
77714 .pop();
77715
77716 var lastDotIdx = fileNoPath.lastIndexOf('.');
77717 var fontFamily;
77718 var newStyle;
77719 var fileExt = lastDotIdx < 1 ? null : fileNoPath.substr(lastDotIdx + 1);
77720
77721 // if so, add it to the DOM (name-only) for use with DOM module
77722 if (validFontTypes.includes(fileExt)) {
77723 fontFamily = fileNoPath.substr(0, lastDotIdx);
77724 newStyle = document.createElement('style');
77725 newStyle.appendChild(
77726 document.createTextNode(
77727 '\n@font-face {\nfont-family: '
77728 .concat(fontFamily, ';\nsrc: url(')
77729 .concat(path, ');\n}\n')
77730 )
77731 );
77732
77733 document.head.appendChild(newStyle);
77734 }
77735 });
77736
77737 return p5Font;
77738 };
77739
77740 /**
77741 * Draws text to the screen. Displays the information specified in the first
77742 * parameter on the screen in the position specified by the additional
77743 * parameters. A default font will be used unless a font is set with the
77744 * <a href="#/p5/textFont">textFont()</a> function and a default size will be
77745 * used unless a font is set with <a href="#/p5/textSize">textSize()</a>. Change
77746 * the color of the text with the <a href="#/p5/fill">fill()</a> function. Change
77747 * the outline of the text with the <a href="#/p5/stroke">stroke()</a> and
77748 * <a href="#/p5/strokeWeight">strokeWeight()</a> functions.
77749 *
77750 * The text displays in relation to the <a href="#/p5/textAlign">textAlign()</a>
77751 * function, which gives the option to draw to the left, right, and center of the
77752 * coordinates.
77753 *
77754 * The x2 and y2 parameters define a rectangular area to display within and
77755 * may only be used with string data. When these parameters are specified,
77756 * they are interpreted based on the current <a href="#/p5/rectMode">rectMode()</a>
77757 * setting. Text that does not fit completely within the rectangle specified will
77758 * not be drawn to the screen. If x2 and y2 are not specified, the baseline
77759 * alignment is the default, which means that the text will be drawn upwards
77760 * from x and y.
77761 *
77762 * <b>WEBGL</b>: Only opentype/truetype fonts are supported. You must load a font
77763 * using the <a href="#/p5/loadFont">loadFont()</a> method (see the example above).
77764 * <a href="#/p5/stroke">stroke()</a> currently has no effect in webgl mode.
77765 *
77766 * @method text
77767 * @param {String|Object|Array|Number|Boolean} str the alphanumeric
77768 * symbols to be displayed
77769 * @param {Number} x x-coordinate of text
77770 * @param {Number} y y-coordinate of text
77771 * @param {Number} [x2] by default, the width of the text box,
77772 * see <a href="#/p5/rectMode">rectMode()</a> for more info
77773 * @param {Number} [y2] by default, the height of the text box,
77774 * see <a href="#/p5/rectMode">rectMode()</a> for more info
77775 * @chainable
77776 * @example
77777 * <div>
77778 * <code>
77779 * textSize(32);
77780 * text('word', 10, 30);
77781 * fill(0, 102, 153);
77782 * text('word', 10, 60);
77783 * fill(0, 102, 153, 51);
77784 * text('word', 10, 90);
77785 * </code>
77786 * </div>
77787 * <div>
77788 * <code>
77789 * let s = 'The quick brown fox jumped over the lazy dog.';
77790 * fill(50);
77791 * text(s, 10, 10, 70, 80); // Text wraps within text box
77792 * </code>
77793 * </div>
77794 *
77795 * <div modernizr='webgl'>
77796 * <code>
77797 * let inconsolata;
77798 * function preload() {
77799 * inconsolata = loadFont('assets/inconsolata.otf');
77800 * }
77801 * function setup() {
77802 * createCanvas(100, 100, WEBGL);
77803 * textFont(inconsolata);
77804 * textSize(width / 3);
77805 * textAlign(CENTER, CENTER);
77806 * }
77807 * function draw() {
77808 * background(0);
77809 * let time = millis();
77810 * rotateX(time / 1000);
77811 * rotateZ(time / 1234);
77812 * text('p5.js', 0, 0);
77813 * }
77814 * </code>
77815 * </div>
77816 *
77817 * @alt
77818 * 'word' displayed 3 times going from black, blue to translucent blue
77819 * The text 'The quick brown fox jumped over the lazy dog' displayed.
77820 * The text 'p5.js' spinning in 3d
77821 */
77822 _main.default.prototype.text = function(str, x, y, maxWidth, maxHeight) {
77823 var _this$_renderer;
77824 _main.default._validateParameters('text', arguments);
77825 return !(this._renderer._doFill || this._renderer._doStroke)
77826 ? this
77827 : (_this$_renderer = this._renderer).text.apply(_this$_renderer, arguments);
77828 };
77829
77830 /**
77831 * Sets the current font that will be drawn with the <a href="#/p5/text">text()</a> function.
77832 *
77833 * <b>WEBGL</b>: Only fonts loaded via <a href="#/p5/loadFont">loadFont()</a> are supported.
77834 *
77835 * @method textFont
77836 * @return {Object} the current font
77837 *
77838 * @example
77839 * <div>
77840 * <code>
77841 * fill(0);
77842 * textSize(12);
77843 * textFont('Georgia');
77844 * text('Georgia', 12, 30);
77845 * textFont('Helvetica');
77846 * text('Helvetica', 12, 60);
77847 * </code>
77848 * </div>
77849 * <div>
77850 * <code>
77851 * let fontRegular, fontItalic, fontBold;
77852 * function preload() {
77853 * fontRegular = loadFont('assets/Regular.otf');
77854 * fontItalic = loadFont('assets/Italic.ttf');
77855 * fontBold = loadFont('assets/Bold.ttf');
77856 * }
77857 * function setup() {
77858 * background(210);
77859 * fill(0)
77860 .strokeWeight(0)
77861 .textSize(10);
77862 * textFont(fontRegular);
77863 * text('Font Style Normal', 10, 30);
77864 * textFont(fontItalic);
77865 * text('Font Style Italic', 10, 50);
77866 * textFont(fontBold);
77867 * text('Font Style Bold', 10, 70);
77868 * }
77869 * </code>
77870 * </div>
77871 *
77872 * @alt
77873 * word 'Georgia' displayed in font Georgia and 'Helvetica' in font Helvetica
77874 * words Font Style Normal displayed normally, Italic in italic and bold in bold
77875 */
77876 /**
77877 * @method textFont
77878 * @param {Object|String} font a font loaded via <a href="#/p5/loadFont">loadFont()</a>,
77879 * or a String representing a <a href="https://mzl.la/2dOw8WD">web safe font</a>
77880 * (a font that is generally available across all systems)
77881 * @param {Number} [size] the font size to use
77882 * @chainable
77883 */
77884 _main.default.prototype.textFont = function(theFont, theSize) {
77885 _main.default._validateParameters('textFont', arguments);
77886 if (arguments.length) {
77887 if (!theFont) {
77888 throw new Error('null font passed to textFont');
77889 }
77890
77891 this._renderer._setProperty('_textFont', theFont);
77892
77893 if (theSize) {
77894 this._renderer._setProperty('_textSize', theSize);
77895 this._renderer._setProperty(
77896 '_textLeading',
77897 theSize * constants._DEFAULT_LEADMULT
77898 );
77899 }
77900
77901 return this._renderer._applyTextProperties();
77902 }
77903
77904 return this._renderer._textFont;
77905 };
77906 var _default = _main.default;
77907 exports.default = _default;
77908 },
77909 {
77910 '../core/constants': 43,
77911 '../core/friendly_errors/fes_core': 46,
77912 '../core/friendly_errors/file_errors': 47,
77913 '../core/friendly_errors/validate_params': 49,
77914 '../core/main': 54,
77915 'opentype.js': 34
77916 }
77917 ],
77918 92: [
77919 function(_dereq_, module, exports) {
77920 'use strict';
77921 Object.defineProperty(exports, '__esModule', { value: true });
77922 exports.default = void 0;
77923
77924 var _main = _interopRequireDefault(_dereq_('../core/main'));
77925 var constants = _interopRequireWildcard(_dereq_('../core/constants'));
77926 function _getRequireWildcardCache() {
77927 if (typeof WeakMap !== 'function') return null;
77928 var cache = new WeakMap();
77929 _getRequireWildcardCache = function _getRequireWildcardCache() {
77930 return cache;
77931 };
77932 return cache;
77933 }
77934 function _interopRequireWildcard(obj) {
77935 if (obj && obj.__esModule) {
77936 return obj;
77937 }
77938 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) {
77939 return { default: obj };
77940 }
77941 var cache = _getRequireWildcardCache();
77942 if (cache && cache.has(obj)) {
77943 return cache.get(obj);
77944 }
77945 var newObj = {};
77946 var hasPropertyDescriptor =
77947 Object.defineProperty && Object.getOwnPropertyDescriptor;
77948 for (var key in obj) {
77949 if (Object.prototype.hasOwnProperty.call(obj, key)) {
77950 var desc = hasPropertyDescriptor
77951 ? Object.getOwnPropertyDescriptor(obj, key)
77952 : null;
77953 if (desc && (desc.get || desc.set)) {
77954 Object.defineProperty(newObj, key, desc);
77955 } else {
77956 newObj[key] = obj[key];
77957 }
77958 }
77959 }
77960 newObj.default = obj;
77961 if (cache) {
77962 cache.set(obj, newObj);
77963 }
77964 return newObj;
77965 }
77966 function _interopRequireDefault(obj) {
77967 return obj && obj.__esModule ? obj : { default: obj };
77968 }
77969 function _typeof(obj) {
77970 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
77971 _typeof = function _typeof(obj) {
77972 return typeof obj;
77973 };
77974 } else {
77975 _typeof = function _typeof(obj) {
77976 return obj &&
77977 typeof Symbol === 'function' &&
77978 obj.constructor === Symbol &&
77979 obj !== Symbol.prototype
77980 ? 'symbol'
77981 : typeof obj;
77982 };
77983 }
77984 return _typeof(obj);
77985 }
77986
77987 /**
77988 * Base class for font handling
77989 * @class p5.Font
77990 * @constructor
77991 * @param {p5} [pInst] pointer to p5 instance
77992 */
77993 _main.default.Font = function(p) {
77994 this.parent = p;
77995
77996 this.cache = {};
77997
77998 /**
77999 * Underlying opentype font implementation
78000 * @property font
78001 */
78002 this.font = undefined;
78003 };
78004
78005 /**
78006 * Returns a tight bounding box for the given text string using this
78007 * font
78008 *
78009 * @method textBounds
78010 * @param {String} line a line of text
78011 * @param {Number} x x-position
78012 * @param {Number} y y-position
78013 * @param {Number} [fontSize] font size to use (optional) Default is 12.
78014 * @param {Object} [options] opentype options (optional)
78015 * opentype fonts contains alignment and baseline options.
78016 * Default is 'LEFT' and 'alphabetic'
78017 *
78018 * @return {Object} a rectangle object with properties: x, y, w, h
78019 *
78020 * @example
78021 * <div>
78022 * <code>
78023 * let font;
78024 * let textString = 'Lorem ipsum dolor sit amet.';
78025 * function preload() {
78026 * font = loadFont('./assets/Regular.otf');
78027 * }
78028 * function setup() {
78029 * background(210);
78030 *
78031 * let bbox = font.textBounds(textString, 10, 30, 12);
78032 * fill(255);
78033 * stroke(0);
78034 * rect(bbox.x, bbox.y, bbox.w, bbox.h);
78035 * fill(0);
78036 * noStroke();
78037 *
78038 * textFont(font);
78039 * textSize(12);
78040 * text(textString, 10, 30);
78041 * }
78042 * </code>
78043 * </div>
78044 *
78045 * @alt
78046 *words Lorem ipsum dol go off canvas and contained by white bounding box
78047 */
78048 _main.default.Font.prototype.textBounds = function(str) {
78049 var x = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
78050 var y = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
78051 var fontSize = arguments.length > 3 ? arguments[3] : undefined;
78052 var opts = arguments.length > 4 ? arguments[4] : undefined;
78053 // Check cache for existing bounds. Take into consideration the text alignment
78054 // settings. Default alignment should match opentype's origin: left-aligned &
78055 // alphabetic baseline.
78056 var p = (opts && opts.renderer && opts.renderer._pInst) || this.parent;
78057
78058 var ctx = p._renderer.drawingContext;
78059 var alignment = ctx.textAlign || constants.LEFT;
78060 var baseline = ctx.textBaseline || constants.BASELINE;
78061 var cacheResults = false;
78062 var result;
78063 var key;
78064
78065 fontSize = fontSize || p._renderer._textSize;
78066
78067 // NOTE: cache disabled for now pending further discussion of #3436
78068 if (cacheResults) {
78069 key = cacheKey('textBounds', str, x, y, fontSize, alignment, baseline);
78070 result = this.cache[key];
78071 }
78072
78073 if (!result) {
78074 var minX = [];
78075 var minY;
78076 var maxX = [];
78077 var maxY;
78078 var pos;
78079 var xCoords = [];
78080 xCoords[0] = [];
78081 var yCoords = [];
78082 var scale = this._scale(fontSize);
78083 var lineHeight = p._renderer.textLeading();
78084 var lineCount = 0;
78085
78086 this.font.forEachGlyph(str, x, y, fontSize, opts, function(
78087 glyph,
78088 gX,
78089 gY,
78090 gFontSize
78091 ) {
78092 var gm = glyph.getMetrics();
78093 if (glyph.index === 0 || glyph.index === 10) {
78094 lineCount += 1;
78095 xCoords[lineCount] = [];
78096 } else {
78097 xCoords[lineCount].push(gX + gm.xMin * scale);
78098 xCoords[lineCount].push(gX + gm.xMax * scale);
78099 yCoords.push(gY + lineCount * lineHeight + -gm.yMin * scale);
78100 yCoords.push(gY + lineCount * lineHeight + -gm.yMax * scale);
78101 }
78102 });
78103
78104 if (xCoords[lineCount].length > 0) {
78105 minX[lineCount] = Math.min.apply(null, xCoords[lineCount]);
78106 maxX[lineCount] = Math.max.apply(null, xCoords[lineCount]);
78107 }
78108
78109 var finalMaxX = 0;
78110 for (var i = 0; i <= lineCount; i++) {
78111 minX[i] = Math.min.apply(null, xCoords[i]);
78112 maxX[i] = Math.max.apply(null, xCoords[i]);
78113 var lineLength = maxX[i] - minX[i];
78114 if (lineLength > finalMaxX) {
78115 finalMaxX = lineLength;
78116 }
78117 }
78118
78119 var finalMinX = Math.min.apply(null, minX);
78120 minY = Math.min.apply(null, yCoords);
78121 maxY = Math.max.apply(null, yCoords);
78122
78123 result = {
78124 x: finalMinX,
78125 y: minY,
78126 h: maxY - minY,
78127 w: finalMaxX,
78128 advance: finalMinX - x
78129 };
78130
78131 // Bounds are now calculated, so shift the x & y to match alignment settings
78132 pos = this._handleAlignment(
78133 p._renderer,
78134 str,
78135 result.x,
78136 result.y,
78137 result.w + result.advance
78138 );
78139
78140 result.x = pos.x;
78141 result.y = pos.y;
78142
78143 if (cacheResults) {
78144 this.cache[key] = result;
78145 }
78146 }
78147
78148 return result;
78149 };
78150
78151 /**
78152 * Computes an array of points following the path for specified text
78153 *
78154 * @method textToPoints
78155 * @param {String} txt a line of text
78156 * @param {Number} x x-position
78157 * @param {Number} y y-position
78158 * @param {Number} fontSize font size to use (optional)
78159 * @param {Object} [options] an (optional) object that can contain:
78160 *
78161 * <br>sampleFactor - the ratio of path-length to number of samples
78162 * (default=.1); higher values yield more points and are therefore
78163 * more precise
78164 *
78165 * <br>simplifyThreshold - if set to a non-zero value, collinear points will be
78166 * be removed from the polygon; the value represents the threshold angle to use
78167 * when determining whether two edges are collinear
78168 *
78169 * @return {Array} an array of points, each with x, y, alpha (the path angle)
78170 * @example
78171 * <div>
78172 * <code>
78173 * let font;
78174 * function preload() {
78175 * font = loadFont('assets/inconsolata.otf');
78176 * }
78177 *
78178 * let points;
78179 * let bounds;
78180 * function setup() {
78181 * createCanvas(100, 100);
78182 * stroke(0);
78183 * fill(255, 104, 204);
78184 *
78185 * points = font.textToPoints('p5', 0, 0, 10, {
78186 * sampleFactor: 5,
78187 * simplifyThreshold: 0
78188 * });
78189 * bounds = font.textBounds(' p5 ', 0, 0, 10);
78190 * }
78191 *
78192 * function draw() {
78193 * background(255);
78194 * beginShape();
78195 * translate(-bounds.x * width / bounds.w, -bounds.y * height / bounds.h);
78196 * for (let i = 0; i < points.length; i++) {
78197 * let p = points[i];
78198 * vertex(
78199 * p.x * width / bounds.w +
78200 * sin(20 * p.y / bounds.h + millis() / 1000) * width / 30,
78201 * p.y * height / bounds.h
78202 * );
78203 * }
78204 * endShape(CLOSE);
78205 * }
78206 * </code>
78207 * </div>
78208 */
78209 _main.default.Font.prototype.textToPoints = function(
78210 txt,
78211 x,
78212 y,
78213 fontSize,
78214 options
78215 ) {
78216 var xoff = 0;
78217 var result = [];
78218 var glyphs = this._getGlyphs(txt);
78219
78220 function isSpace(i) {
78221 return (
78222 (glyphs[i].name && glyphs[i].name === 'space') ||
78223 (txt.length === glyphs.length && txt[i] === ' ') ||
78224 (glyphs[i].index && glyphs[i].index === 3)
78225 );
78226 }
78227
78228 fontSize = fontSize || this.parent._renderer._textSize;
78229
78230 for (var i = 0; i < glyphs.length; i++) {
78231 if (!isSpace(i)) {
78232 // fix to #1817, #2069
78233
78234 var gpath = glyphs[i].getPath(x, y, fontSize),
78235 paths = splitPaths(gpath.commands);
78236
78237 for (var j = 0; j < paths.length; j++) {
78238 var pts = pathToPoints(paths[j], options);
78239
78240 for (var k = 0; k < pts.length; k++) {
78241 pts[k].x += xoff;
78242 result.push(pts[k]);
78243 }
78244 }
78245 }
78246
78247 xoff += glyphs[i].advanceWidth * this._scale(fontSize);
78248 }
78249
78250 return result;
78251 };
78252
78253 // ----------------------------- End API ------------------------------
78254
78255 /**
78256 * Returns the set of opentype glyphs for the supplied string.
78257 *
78258 * Note that there is not a strict one-to-one mapping between characters
78259 * and glyphs, so the list of returned glyphs can be larger or smaller
78260 * than the length of the given string.
78261 *
78262 * @private
78263 * @param {String} str the string to be converted
78264 * @return {Array} the opentype glyphs
78265 */
78266 _main.default.Font.prototype._getGlyphs = function(str) {
78267 return this.font.stringToGlyphs(str);
78268 };
78269
78270 /**
78271 * Returns an opentype path for the supplied string and position.
78272 *
78273 * @private
78274 * @param {String} line a line of text
78275 * @param {Number} x x-position
78276 * @param {Number} y y-position
78277 * @param {Object} options opentype options (optional)
78278 * @return {Object} the opentype path
78279 */
78280 _main.default.Font.prototype._getPath = function(line, x, y, options) {
78281 var p = (options && options.renderer && options.renderer._pInst) || this.parent,
78282 renderer = p._renderer,
78283 pos = this._handleAlignment(renderer, line, x, y);
78284
78285 return this.font.getPath(line, pos.x, pos.y, renderer._textSize, options);
78286 };
78287
78288 /*
78289 * Creates an SVG-formatted path-data string
78290 * (See http://www.w3.org/TR/SVG/paths.html#PathData)
78291 * from the given opentype path or string/position
78292 *
78293 * @param {Object} path an opentype path, OR the following:
78294 *
78295 * @param {String} line a line of text
78296 * @param {Number} x x-position
78297 * @param {Number} y y-position
78298 * @param {Object} options opentype options (optional), set options.decimals
78299 * to set the decimal precision of the path-data
78300 *
78301 * @return {Object} this p5.Font object
78302 */
78303 _main.default.Font.prototype._getPathData = function(line, x, y, options) {
78304 var decimals = 3;
78305
78306 // create path from string/position
78307 if (typeof line === 'string' && arguments.length > 2) {
78308 line = this._getPath(line, x, y, options);
78309 } else if (_typeof(x) === 'object') {
78310 // handle options specified in 2nd arg
78311 options = x;
78312 }
78313
78314 // handle svg arguments
78315 if (options && typeof options.decimals === 'number') {
78316 decimals = options.decimals;
78317 }
78318
78319 return line.toPathData(decimals);
78320 };
78321
78322 /*
78323 * Creates an SVG <path> element, as a string,
78324 * from the given opentype path or string/position
78325 *
78326 * @param {Object} path an opentype path, OR the following:
78327 *
78328 * @param {String} line a line of text
78329 * @param {Number} x x-position
78330 * @param {Number} y y-position
78331 * @param {Object} options opentype options (optional), set options.decimals
78332 * to set the decimal precision of the path-data in the <path> element,
78333 * options.fill to set the fill color for the <path> element,
78334 * options.stroke to set the stroke color for the <path> element,
78335 * options.strokeWidth to set the strokeWidth for the <path> element.
78336 *
78337 * @return {Object} this p5.Font object
78338 */
78339 _main.default.Font.prototype._getSVG = function(line, x, y, options) {
78340 var decimals = 3;
78341
78342 // create path from string/position
78343 if (typeof line === 'string' && arguments.length > 2) {
78344 line = this._getPath(line, x, y, options);
78345 } else if (_typeof(x) === 'object') {
78346 // handle options specified in 2nd arg
78347 options = x;
78348 }
78349
78350 // handle svg arguments
78351 if (options) {
78352 if (typeof options.decimals === 'number') {
78353 decimals = options.decimals;
78354 }
78355 if (typeof options.strokeWidth === 'number') {
78356 line.strokeWidth = options.strokeWidth;
78357 }
78358 if (typeof options.fill !== 'undefined') {
78359 line.fill = options.fill;
78360 }
78361 if (typeof options.stroke !== 'undefined') {
78362 line.stroke = options.stroke;
78363 }
78364 }
78365
78366 return line.toSVG(decimals);
78367 };
78368
78369 /*
78370 * Renders an opentype path or string/position
78371 * to the current graphics context
78372 *
78373 * @param {Object} path an opentype path, OR the following:
78374 *
78375 * @param {String} line a line of text
78376 * @param {Number} x x-position
78377 * @param {Number} y y-position
78378 * @param {Object} options opentype options (optional)
78379 *
78380 * @return {p5.Font} this p5.Font object
78381 */
78382 _main.default.Font.prototype._renderPath = function(line, x, y, options) {
78383 var pdata;
78384 var pg = (options && options.renderer) || this.parent._renderer;
78385 var ctx = pg.drawingContext;
78386
78387 if (_typeof(line) === 'object' && line.commands) {
78388 pdata = line.commands;
78389 } else {
78390 //pos = handleAlignment(p, ctx, line, x, y);
78391 pdata = this._getPath(line, x, y, options).commands;
78392 }
78393
78394 ctx.beginPath();
78395 var _iteratorNormalCompletion = true;
78396 var _didIteratorError = false;
78397 var _iteratorError = undefined;
78398 try {
78399 for (
78400 var _iterator = pdata[Symbol.iterator](), _step;
78401 !(_iteratorNormalCompletion = (_step = _iterator.next()).done);
78402 _iteratorNormalCompletion = true
78403 ) {
78404 var cmd = _step.value;
78405 if (cmd.type === 'M') {
78406 ctx.moveTo(cmd.x, cmd.y);
78407 } else if (cmd.type === 'L') {
78408 ctx.lineTo(cmd.x, cmd.y);
78409 } else if (cmd.type === 'C') {
78410 ctx.bezierCurveTo(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y);
78411 } else if (cmd.type === 'Q') {
78412 ctx.quadraticCurveTo(cmd.x1, cmd.y1, cmd.x, cmd.y);
78413 } else if (cmd.type === 'Z') {
78414 ctx.closePath();
78415 }
78416 }
78417
78418 // only draw stroke if manually set by user
78419 } catch (err) {
78420 _didIteratorError = true;
78421 _iteratorError = err;
78422 } finally {
78423 try {
78424 if (!_iteratorNormalCompletion && _iterator.return != null) {
78425 _iterator.return();
78426 }
78427 } finally {
78428 if (_didIteratorError) {
78429 throw _iteratorError;
78430 }
78431 }
78432 }
78433 if (pg._doStroke && pg._strokeSet) {
78434 ctx.stroke();
78435 }
78436
78437 if (pg._doFill) {
78438 // if fill hasn't been set by user, use default-text-fill
78439 if (!pg._fillSet) {
78440 pg._setFill(constants._DEFAULT_TEXT_FILL);
78441 }
78442 ctx.fill();
78443 }
78444
78445 return this;
78446 };
78447
78448 _main.default.Font.prototype._textWidth = function(str, fontSize) {
78449 return this.font.getAdvanceWidth(str, fontSize);
78450 };
78451
78452 _main.default.Font.prototype._textAscent = function(fontSize) {
78453 return this.font.ascender * this._scale(fontSize);
78454 };
78455
78456 _main.default.Font.prototype._textDescent = function(fontSize) {
78457 return -this.font.descender * this._scale(fontSize);
78458 };
78459
78460 _main.default.Font.prototype._scale = function(fontSize) {
78461 return 1 / this.font.unitsPerEm * (fontSize || this.parent._renderer._textSize);
78462 };
78463
78464 _main.default.Font.prototype._handleAlignment = function(
78465 renderer,
78466 line,
78467 x,
78468 y,
78469 textWidth
78470 ) {
78471 var fontSize = renderer._textSize;
78472
78473 if (typeof textWidth === 'undefined') {
78474 textWidth = this._textWidth(line, fontSize);
78475 }
78476
78477 switch (renderer._textAlign) {
78478 case constants.CENTER:
78479 x -= textWidth / 2;
78480 break;
78481 case constants.RIGHT:
78482 x -= textWidth;
78483 break;
78484 }
78485
78486 switch (renderer._textBaseline) {
78487 case constants.TOP:
78488 y += this._textAscent(fontSize);
78489 break;
78490 case constants.CENTER:
78491 y += this._textAscent(fontSize) / 2;
78492 break;
78493 case constants.BOTTOM:
78494 y -= this._textDescent(fontSize);
78495 break;
78496 }
78497
78498 return { x: x, y: y };
78499 };
78500
78501 // path-utils
78502
78503 function pathToPoints(cmds, options) {
78504 var opts = parseOpts(options, {
78505 sampleFactor: 0.1,
78506 simplifyThreshold: 0
78507 });
78508
78509 var // total-length
78510 len = pointAtLength(cmds, 0, 1),
78511 t = len / (len * opts.sampleFactor),
78512 pts = [];
78513
78514 for (var i = 0; i < len; i += t) {
78515 pts.push(pointAtLength(cmds, i));
78516 }
78517
78518 if (opts.simplifyThreshold) {
78519 simplify(pts, opts.simplifyThreshold);
78520 }
78521
78522 return pts;
78523 }
78524
78525 function simplify(pts) {
78526 var angle =
78527 arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
78528 var num = 0;
78529 for (var i = pts.length - 1; pts.length > 3 && i >= 0; --i) {
78530 if (collinear(at(pts, i - 1), at(pts, i), at(pts, i + 1), angle)) {
78531 // Remove the middle point
78532 pts.splice(i % pts.length, 1);
78533 num++;
78534 }
78535 }
78536 return num;
78537 }
78538
78539 function splitPaths(cmds) {
78540 var paths = [];
78541 var current;
78542 for (var i = 0; i < cmds.length; i++) {
78543 if (cmds[i].type === 'M') {
78544 if (current) {
78545 paths.push(current);
78546 }
78547 current = [];
78548 }
78549 current.push(cmdToArr(cmds[i]));
78550 }
78551 paths.push(current);
78552
78553 return paths;
78554 }
78555
78556 function cmdToArr(cmd) {
78557 var arr = [cmd.type];
78558 if (cmd.type === 'M' || cmd.type === 'L') {
78559 // moveto or lineto
78560 arr.push(cmd.x, cmd.y);
78561 } else if (cmd.type === 'C') {
78562 arr.push(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y);
78563 } else if (cmd.type === 'Q') {
78564 arr.push(cmd.x1, cmd.y1, cmd.x, cmd.y);
78565 }
78566 // else if (cmd.type === 'Z') { /* no-op */ }
78567 return arr;
78568 }
78569
78570 function parseOpts(options, defaults) {
78571 if (_typeof(options) !== 'object') {
78572 options = defaults;
78573 } else {
78574 for (var key in defaults) {
78575 if (typeof options[key] === 'undefined') {
78576 options[key] = defaults[key];
78577 }
78578 }
78579 }
78580 return options;
78581 }
78582
78583 //////////////////////// Helpers ////////////////////////////
78584
78585 function at(v, i) {
78586 var s = v.length;
78587 return v[i < 0 ? i % s + s : i % s];
78588 }
78589
78590 function collinear(a, b, c, thresholdAngle) {
78591 if (!thresholdAngle) {
78592 return areaTriangle(a, b, c) === 0;
78593 }
78594
78595 if (typeof collinear.tmpPoint1 === 'undefined') {
78596 collinear.tmpPoint1 = [];
78597 collinear.tmpPoint2 = [];
78598 }
78599
78600 var ab = collinear.tmpPoint1,
78601 bc = collinear.tmpPoint2;
78602 ab.x = b.x - a.x;
78603 ab.y = b.y - a.y;
78604 bc.x = c.x - b.x;
78605 bc.y = c.y - b.y;
78606
78607 var dot = ab.x * bc.x + ab.y * bc.y,
78608 magA = Math.sqrt(ab.x * ab.x + ab.y * ab.y),
78609 magB = Math.sqrt(bc.x * bc.x + bc.y * bc.y),
78610 angle = Math.acos(dot / (magA * magB));
78611
78612 return angle < thresholdAngle;
78613 }
78614
78615 function areaTriangle(a, b, c) {
78616 return (b[0] - a[0]) * (c[1] - a[1]) - (c[0] - a[0]) * (b[1] - a[1]);
78617 }
78618
78619 // Portions of below code copyright 2008 Dmitry Baranovskiy (via MIT license)
78620
78621 function findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {
78622 var t1 = 1 - t;
78623 var t13 = Math.pow(t1, 3);
78624 var t12 = Math.pow(t1, 2);
78625 var t2 = t * t;
78626 var t3 = t2 * t;
78627 var x = t13 * p1x + t12 * 3 * t * c1x + t1 * 3 * t * t * c2x + t3 * p2x;
78628 var y = t13 * p1y + t12 * 3 * t * c1y + t1 * 3 * t * t * c2y + t3 * p2y;
78629 var mx = p1x + 2 * t * (c1x - p1x) + t2 * (c2x - 2 * c1x + p1x);
78630 var my = p1y + 2 * t * (c1y - p1y) + t2 * (c2y - 2 * c1y + p1y);
78631 var nx = c1x + 2 * t * (c2x - c1x) + t2 * (p2x - 2 * c2x + c1x);
78632 var ny = c1y + 2 * t * (c2y - c1y) + t2 * (p2y - 2 * c2y + c1y);
78633 var ax = t1 * p1x + t * c1x;
78634 var ay = t1 * p1y + t * c1y;
78635 var cx = t1 * c2x + t * p2x;
78636 var cy = t1 * c2y + t * p2y;
78637 var alpha = 90 - Math.atan2(mx - nx, my - ny) * 180 / Math.PI;
78638
78639 if (mx > nx || my < ny) {
78640 alpha += 180;
78641 }
78642
78643 return {
78644 x: x,
78645 y: y,
78646 m: { x: mx, y: my },
78647 n: { x: nx, y: ny },
78648 start: { x: ax, y: ay },
78649 end: { x: cx, y: cy },
78650 alpha: alpha
78651 };
78652 }
78653
78654 function getPointAtSegmentLength(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length) {
78655 return length == null
78656 ? bezlen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y)
78657 : findDotsAtSegment(
78658 p1x,
78659 p1y,
78660 c1x,
78661 c1y,
78662 c2x,
78663 c2y,
78664 p2x,
78665 p2y,
78666 getTatLen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length)
78667 );
78668 }
78669
78670 function pointAtLength(path, length, istotal) {
78671 path = path2curve(path);
78672 var x;
78673 var y;
78674 var p;
78675 var l;
78676 var sp = '';
78677 var subpaths = {};
78678 var point;
78679 var len = 0;
78680 for (var i = 0, ii = path.length; i < ii; i++) {
78681 p = path[i];
78682 if (p[0] === 'M') {
78683 x = +p[1];
78684 y = +p[2];
78685 } else {
78686 l = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);
78687 if (len + l > length) {
78688 if (!istotal) {
78689 point = getPointAtSegmentLength(
78690 x,
78691 y,
78692 p[1],
78693 p[2],
78694 p[3],
78695 p[4],
78696 p[5],
78697 p[6],
78698 length - len
78699 );
78700
78701 return { x: point.x, y: point.y, alpha: point.alpha };
78702 }
78703 }
78704 len += l;
78705 x = +p[5];
78706 y = +p[6];
78707 }
78708 sp += p.shift() + p;
78709 }
78710 subpaths.end = sp;
78711
78712 point = istotal
78713 ? len
78714 : findDotsAtSegment(x, y, p[0], p[1], p[2], p[3], p[4], p[5], 1);
78715
78716 if (point.alpha) {
78717 point = { x: point.x, y: point.y, alpha: point.alpha };
78718 }
78719
78720 return point;
78721 }
78722
78723 function pathToAbsolute(pathArray) {
78724 var res = [],
78725 x = 0,
78726 y = 0,
78727 mx = 0,
78728 my = 0,
78729 start = 0;
78730 if (!pathArray) {
78731 // console.warn("Unexpected state: undefined pathArray"); // shouldn't happen
78732 return res;
78733 }
78734 if (pathArray[0][0] === 'M') {
78735 x = +pathArray[0][1];
78736 y = +pathArray[0][2];
78737 mx = x;
78738 my = y;
78739 start++;
78740 res[0] = ['M', x, y];
78741 }
78742
78743 var dots;
78744
78745 var crz =
78746 pathArray.length === 3 &&
78747 pathArray[0][0] === 'M' &&
78748 pathArray[1][0].toUpperCase() === 'R' &&
78749 pathArray[2][0].toUpperCase() === 'Z';
78750
78751 for (var r, pa, i = start, ii = pathArray.length; i < ii; i++) {
78752 res.push((r = []));
78753 pa = pathArray[i];
78754 if (pa[0] !== String.prototype.toUpperCase.call(pa[0])) {
78755 r[0] = String.prototype.toUpperCase.call(pa[0]);
78756 switch (r[0]) {
78757 case 'A':
78758 r[1] = pa[1];
78759 r[2] = pa[2];
78760 r[3] = pa[3];
78761 r[4] = pa[4];
78762 r[5] = pa[5];
78763 r[6] = +(pa[6] + x);
78764 r[7] = +(pa[7] + y);
78765 break;
78766 case 'V':
78767 r[1] = +pa[1] + y;
78768 break;
78769 case 'H':
78770 r[1] = +pa[1] + x;
78771 break;
78772 case 'R':
78773 dots = [x, y].concat(pa.slice(1));
78774 for (var j = 2, jj = dots.length; j < jj; j++) {
78775 dots[j] = +dots[j] + x;
78776 dots[++j] = +dots[j] + y;
78777 }
78778 res.pop();
78779 res = res.concat(catmullRom2bezier(dots, crz));
78780 break;
78781 case 'M':
78782 mx = +pa[1] + x;
78783 my = +pa[2] + y;
78784 break;
78785 default:
78786 for (var _j = 1, _jj = pa.length; _j < _jj; _j++) {
78787 r[_j] = +pa[_j] + (_j % 2 ? x : y);
78788 }
78789 }
78790 } else if (pa[0] === 'R') {
78791 dots = [x, y].concat(pa.slice(1));
78792 res.pop();
78793 res = res.concat(catmullRom2bezier(dots, crz));
78794 r = ['R'].concat(pa.slice(-2));
78795 } else {
78796 for (var k = 0, kk = pa.length; k < kk; k++) {
78797 r[k] = pa[k];
78798 }
78799 }
78800 switch (r[0]) {
78801 case 'Z':
78802 x = mx;
78803 y = my;
78804 break;
78805 case 'H':
78806 x = r[1];
78807 break;
78808 case 'V':
78809 y = r[1];
78810 break;
78811 case 'M':
78812 mx = r[r.length - 2];
78813 my = r[r.length - 1];
78814 break;
78815 default:
78816 x = r[r.length - 2];
78817 y = r[r.length - 1];
78818 }
78819 }
78820 return res;
78821 }
78822
78823 function path2curve(path, path2) {
78824 var p = pathToAbsolute(path),
78825 p2 = path2 && pathToAbsolute(path2);
78826 var attrs = { x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null };
78827 var attrs2 = { x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null };
78828 var pcoms1 = []; // path commands of original path p
78829 var pcoms2 = []; // path commands of original path p2
78830 var ii;
78831
78832 var processPath = function processPath(path, d, pcom) {
78833 var nx;
78834 var ny;
78835 var tq = { T: 1, Q: 1 };
78836 if (!path) {
78837 return ['C', d.x, d.y, d.x, d.y, d.x, d.y];
78838 }
78839 if (!(path[0] in tq)) {
78840 d.qx = d.qy = null;
78841 }
78842 switch (path[0]) {
78843 case 'M':
78844 d.X = path[1];
78845 d.Y = path[2];
78846 break;
78847 case 'A':
78848 path = ['C'].concat(a2c.apply(0, [d.x, d.y].concat(path.slice(1))));
78849 break;
78850 case 'S':
78851 if (pcom === 'C' || pcom === 'S') {
78852 nx = d.x * 2 - d.bx;
78853 ny = d.y * 2 - d.by;
78854 } else {
78855 nx = d.x;
78856 ny = d.y;
78857 }
78858 path = ['C', nx, ny].concat(path.slice(1));
78859 break;
78860 case 'T':
78861 if (pcom === 'Q' || pcom === 'T') {
78862 d.qx = d.x * 2 - d.qx;
78863 d.qy = d.y * 2 - d.qy;
78864 } else {
78865 d.qx = d.x;
78866 d.qy = d.y;
78867 }
78868 path = ['C'].concat(q2c(d.x, d.y, d.qx, d.qy, path[1], path[2]));
78869 break;
78870 case 'Q':
78871 d.qx = path[1];
78872 d.qy = path[2];
78873 path = ['C'].concat(q2c(d.x, d.y, path[1], path[2], path[3], path[4]));
78874
78875 break;
78876 case 'L':
78877 path = ['C'].concat(l2c(d.x, d.y, path[1], path[2]));
78878 break;
78879 case 'H':
78880 path = ['C'].concat(l2c(d.x, d.y, path[1], d.y));
78881 break;
78882 case 'V':
78883 path = ['C'].concat(l2c(d.x, d.y, d.x, path[1]));
78884 break;
78885 case 'Z':
78886 path = ['C'].concat(l2c(d.x, d.y, d.X, d.Y));
78887 break;
78888 }
78889
78890 return path;
78891 },
78892 fixArc = function fixArc(pp, i) {
78893 if (pp[i].length > 7) {
78894 pp[i].shift();
78895 var pi = pp[i];
78896 while (pi.length) {
78897 pcoms1[i] = 'A';
78898 if (p2) {
78899 pcoms2[i] = 'A';
78900 }
78901 pp.splice(i++, 0, ['C'].concat(pi.splice(0, 6)));
78902 }
78903 pp.splice(i, 1);
78904 ii = Math.max(p.length, (p2 && p2.length) || 0);
78905 }
78906 },
78907 fixM = function fixM(path1, path2, a1, a2, i) {
78908 if (path1 && path2 && path1[i][0] === 'M' && path2[i][0] !== 'M') {
78909 path2.splice(i, 0, ['M', a2.x, a2.y]);
78910 a1.bx = 0;
78911 a1.by = 0;
78912 a1.x = path1[i][1];
78913 a1.y = path1[i][2];
78914 ii = Math.max(p.length, (p2 && p2.length) || 0);
78915 }
78916 };
78917
78918 var pfirst = ''; // temporary holder for original path command
78919 var pcom = ''; // holder for previous path command of original path
78920
78921 ii = Math.max(p.length, (p2 && p2.length) || 0);
78922 for (var i = 0; i < ii; i++) {
78923 if (p[i]) {
78924 pfirst = p[i][0];
78925 } // save current path command
78926
78927 if (pfirst !== 'C') {
78928 pcoms1[i] = pfirst; // Save current path command
78929 if (i) {
78930 pcom = pcoms1[i - 1];
78931 } // Get previous path command pcom
78932 }
78933 p[i] = processPath(p[i], attrs, pcom);
78934
78935 if (pcoms1[i] !== 'A' && pfirst === 'C') {
78936 pcoms1[i] = 'C';
78937 }
78938
78939 fixArc(p, i); // fixArc adds also the right amount of A:s to pcoms1
78940
78941 if (p2) {
78942 // the same procedures is done to p2
78943 if (p2[i]) {
78944 pfirst = p2[i][0];
78945 }
78946 if (pfirst !== 'C') {
78947 pcoms2[i] = pfirst;
78948 if (i) {
78949 pcom = pcoms2[i - 1];
78950 }
78951 }
78952 p2[i] = processPath(p2[i], attrs2, pcom);
78953
78954 if (pcoms2[i] !== 'A' && pfirst === 'C') {
78955 pcoms2[i] = 'C';
78956 }
78957
78958 fixArc(p2, i);
78959 }
78960 fixM(p, p2, attrs, attrs2, i);
78961 fixM(p2, p, attrs2, attrs, i);
78962 var seg = p[i],
78963 seg2 = p2 && p2[i],
78964 seglen = seg.length,
78965 seg2len = p2 && seg2.length;
78966 attrs.x = seg[seglen - 2];
78967 attrs.y = seg[seglen - 1];
78968 attrs.bx = parseFloat(seg[seglen - 4]) || attrs.x;
78969 attrs.by = parseFloat(seg[seglen - 3]) || attrs.y;
78970 attrs2.bx = p2 && (parseFloat(seg2[seg2len - 4]) || attrs2.x);
78971 attrs2.by = p2 && (parseFloat(seg2[seg2len - 3]) || attrs2.y);
78972 attrs2.x = p2 && seg2[seg2len - 2];
78973 attrs2.y = p2 && seg2[seg2len - 1];
78974 }
78975
78976 return p2 ? [p, p2] : p;
78977 }
78978
78979 function a2c(x1, y1, rx, ry, angle, lac, sweep_flag, x2, y2, recursive) {
78980 // for more information of where this Math came from visit:
78981 // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
78982 var PI = Math.PI;
78983
78984 var _120 = PI * 120 / 180;
78985 var f1;
78986 var f2;
78987 var cx;
78988 var cy;
78989 var rad = PI / 180 * (+angle || 0);
78990 var res = [];
78991 var xy;
78992
78993 var rotate = function rotate(x, y, rad) {
78994 var X = x * Math.cos(rad) - y * Math.sin(rad),
78995 Y = x * Math.sin(rad) + y * Math.cos(rad);
78996 return { x: X, y: Y };
78997 };
78998
78999 if (!recursive) {
79000 xy = rotate(x1, y1, -rad);
79001 x1 = xy.x;
79002 y1 = xy.y;
79003 xy = rotate(x2, y2, -rad);
79004 x2 = xy.x;
79005 y2 = xy.y;
79006 var x = (x1 - x2) / 2;
79007 var y = (y1 - y2) / 2;
79008 var h = x * x / (rx * rx) + y * y / (ry * ry);
79009 if (h > 1) {
79010 h = Math.sqrt(h);
79011 rx = h * rx;
79012 ry = h * ry;
79013 }
79014 var rx2 = rx * rx,
79015 ry2 = ry * ry;
79016 var k =
79017 (lac === sweep_flag ? -1 : 1) *
79018 Math.sqrt(
79019 Math.abs(
79020 (rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x)
79021 )
79022 );
79023
79024 cx = k * rx * y / ry + (x1 + x2) / 2;
79025 cy = k * -ry * x / rx + (y1 + y2) / 2;
79026 f1 = Math.asin(((y1 - cy) / ry).toFixed(9));
79027 f2 = Math.asin(((y2 - cy) / ry).toFixed(9));
79028
79029 f1 = x1 < cx ? PI - f1 : f1;
79030 f2 = x2 < cx ? PI - f2 : f2;
79031
79032 if (f1 < 0) {
79033 f1 = PI * 2 + f1;
79034 }
79035 if (f2 < 0) {
79036 f2 = PI * 2 + f2;
79037 }
79038
79039 if (sweep_flag && f1 > f2) {
79040 f1 = f1 - PI * 2;
79041 }
79042 if (!sweep_flag && f2 > f1) {
79043 f2 = f2 - PI * 2;
79044 }
79045 } else {
79046 f1 = recursive[0];
79047 f2 = recursive[1];
79048 cx = recursive[2];
79049 cy = recursive[3];
79050 }
79051 var df = f2 - f1;
79052 if (Math.abs(df) > _120) {
79053 var f2old = f2,
79054 x2old = x2,
79055 y2old = y2;
79056 f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1);
79057 x2 = cx + rx * Math.cos(f2);
79058 y2 = cy + ry * Math.sin(f2);
79059 res = a2c(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [
79060 f2,
79061 f2old,
79062 cx,
79063 cy
79064 ]);
79065 }
79066 df = f2 - f1;
79067 var c1 = Math.cos(f1),
79068 s1 = Math.sin(f1),
79069 c2 = Math.cos(f2),
79070 s2 = Math.sin(f2),
79071 t = Math.tan(df / 4),
79072 hx = 4 / 3 * rx * t,
79073 hy = 4 / 3 * ry * t,
79074 m1 = [x1, y1],
79075 m2 = [x1 + hx * s1, y1 - hy * c1],
79076 m3 = [x2 + hx * s2, y2 - hy * c2],
79077 m4 = [x2, y2];
79078 m2[0] = 2 * m1[0] - m2[0];
79079 m2[1] = 2 * m1[1] - m2[1];
79080 if (recursive) {
79081 return [m2, m3, m4].concat(res);
79082 } else {
79083 res = [m2, m3, m4]
79084 .concat(res)
79085 .join()
79086 .split(',');
79087 var newres = [];
79088 for (var i = 0, ii = res.length; i < ii; i++) {
79089 newres[i] =
79090 i % 2
79091 ? rotate(res[i - 1], res[i], rad).y
79092 : rotate(res[i], res[i + 1], rad).x;
79093 }
79094 return newres;
79095 }
79096 }
79097
79098 // http://schepers.cc/getting-to-the-point
79099 function catmullRom2bezier(crp, z) {
79100 var d = [];
79101 for (var i = 0, iLen = crp.length; iLen - 2 * !z > i; i += 2) {
79102 var p = [
79103 {
79104 x: +crp[i - 2],
79105 y: +crp[i - 1]
79106 },
79107
79108 {
79109 x: +crp[i],
79110 y: +crp[i + 1]
79111 },
79112
79113 {
79114 x: +crp[i + 2],
79115 y: +crp[i + 3]
79116 },
79117
79118 {
79119 x: +crp[i + 4],
79120 y: +crp[i + 5]
79121 }
79122 ];
79123
79124 if (z) {
79125 if (!i) {
79126 p[0] = {
79127 x: +crp[iLen - 2],
79128 y: +crp[iLen - 1]
79129 };
79130 } else if (iLen - 4 === i) {
79131 p[3] = {
79132 x: +crp[0],
79133 y: +crp[1]
79134 };
79135 } else if (iLen - 2 === i) {
79136 p[2] = {
79137 x: +crp[0],
79138 y: +crp[1]
79139 };
79140
79141 p[3] = {
79142 x: +crp[2],
79143 y: +crp[3]
79144 };
79145 }
79146 } else {
79147 if (iLen - 4 === i) {
79148 p[3] = p[2];
79149 } else if (!i) {
79150 p[0] = {
79151 x: +crp[i],
79152 y: +crp[i + 1]
79153 };
79154 }
79155 }
79156 d.push([
79157 'C',
79158 (-p[0].x + 6 * p[1].x + p[2].x) / 6,
79159 (-p[0].y + 6 * p[1].y + p[2].y) / 6,
79160 (p[1].x + 6 * p[2].x - p[3].x) / 6,
79161 (p[1].y + 6 * p[2].y - p[3].y) / 6,
79162 p[2].x,
79163 p[2].y
79164 ]);
79165 }
79166
79167 return d;
79168 }
79169
79170 function l2c(x1, y1, x2, y2) {
79171 return [x1, y1, x2, y2, x2, y2];
79172 }
79173
79174 function q2c(x1, y1, ax, ay, x2, y2) {
79175 var _13 = 1 / 3,
79176 _23 = 2 / 3;
79177 return [
79178 _13 * x1 + _23 * ax,
79179 _13 * y1 + _23 * ay,
79180 _13 * x2 + _23 * ax,
79181 _13 * y2 + _23 * ay,
79182 x2,
79183 y2
79184 ];
79185 }
79186
79187 function bezlen(x1, y1, x2, y2, x3, y3, x4, y4, z) {
79188 if (z == null) {
79189 z = 1;
79190 }
79191 z = z > 1 ? 1 : z < 0 ? 0 : z;
79192 var z2 = z / 2;
79193 var n = 12;
79194 var Tvalues = [
79195 -0.1252,
79196 0.1252,
79197 -0.3678,
79198 0.3678,
79199 -0.5873,
79200 0.5873,
79201 -0.7699,
79202 0.7699,
79203 -0.9041,
79204 0.9041,
79205 -0.9816,
79206 0.9816
79207 ];
79208
79209 var sum = 0;
79210 var Cvalues = [
79211 0.2491,
79212 0.2491,
79213 0.2335,
79214 0.2335,
79215 0.2032,
79216 0.2032,
79217 0.1601,
79218 0.1601,
79219 0.1069,
79220 0.1069,
79221 0.0472,
79222 0.0472
79223 ];
79224
79225 for (var i = 0; i < n; i++) {
79226 var ct = z2 * Tvalues[i] + z2,
79227 xbase = base3(ct, x1, x2, x3, x4),
79228 ybase = base3(ct, y1, y2, y3, y4),
79229 comb = xbase * xbase + ybase * ybase;
79230 sum += Cvalues[i] * Math.sqrt(comb);
79231 }
79232 return z2 * sum;
79233 }
79234
79235 function getTatLen(x1, y1, x2, y2, x3, y3, x4, y4, ll) {
79236 if (ll < 0 || bezlen(x1, y1, x2, y2, x3, y3, x4, y4) < ll) {
79237 return;
79238 }
79239 var t = 1;
79240 var step = t / 2;
79241 var t2 = t - step;
79242 var l;
79243 var e = 0.01;
79244 l = bezlen(x1, y1, x2, y2, x3, y3, x4, y4, t2);
79245 while (Math.abs(l - ll) > e) {
79246 step /= 2;
79247 t2 += (l < ll ? 1 : -1) * step;
79248 l = bezlen(x1, y1, x2, y2, x3, y3, x4, y4, t2);
79249 }
79250 return t2;
79251 }
79252
79253 function base3(t, p1, p2, p3, p4) {
79254 var t1 = -3 * p1 + 9 * p2 - 9 * p3 + 3 * p4,
79255 t2 = t * t1 + 6 * p1 - 12 * p2 + 6 * p3;
79256 return t * t2 - 3 * p1 + 3 * p2;
79257 }
79258
79259 function cacheKey() {
79260 var hash = '';
79261 for (var i = arguments.length - 1; i >= 0; --i) {
79262 hash += '\uFF1F'.concat(
79263 i < 0 || arguments.length <= i ? undefined : arguments[i]
79264 );
79265 }
79266 return hash;
79267 }
79268 var _default = _main.default;
79269 exports.default = _default;
79270 },
79271 { '../core/constants': 43, '../core/main': 54 }
79272 ],
79273 93: [
79274 function(_dereq_, module, exports) {
79275 'use strict';
79276 Object.defineProperty(exports, '__esModule', { value: true });
79277 exports.default = void 0;
79278
79279 var _main = _interopRequireDefault(_dereq_('../core/main'));
79280 function _interopRequireDefault(obj) {
79281 return obj && obj.__esModule ? obj : { default: obj };
79282 }
79283 /**
79284 * @module Data
79285 * @submodule Array Functions
79286 * @for p5
79287 * @requires core
79288 */ /**
79289 * Adds a value to the end of an array. Extends the length of
79290 * the array by one. Maps to Array.push().
79291 *
79292 * @method append
79293 * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push">array.push(value)</a> instead.
79294 * @param {Array} array Array to append
79295 * @param {any} value to be added to the Array
79296 * @return {Array} the array that was appended to
79297 * @example
79298 * <div class='norender'><code>
79299 * function setup() {
79300 * let myArray = ['Mango', 'Apple', 'Papaya'];
79301 * print(myArray); // ['Mango', 'Apple', 'Papaya']
79302 *
79303 * append(myArray, 'Peach');
79304 * print(myArray); // ['Mango', 'Apple', 'Papaya', 'Peach']
79305 * }
79306 * </code></div>
79307 */ _main.default.prototype.append = function(array, value) {
79308 array.push(value);
79309 return array;
79310 };
79311
79312 /**
79313 * Copies an array (or part of an array) to another array. The src array is
79314 * copied to the dst array, beginning at the position specified by
79315 * srcPosition and into the position specified by dstPosition. The number of
79316 * elements to copy is determined by length. Note that copying values
79317 * overwrites existing values in the destination array. To append values
79318 * instead of overwriting them, use <a href="#/p5/concat">concat()</a>.
79319 *
79320 * The simplified version with only two arguments, arrayCopy(src, dst),
79321 * copies an entire array to another of the same size. It is equivalent to
79322 * arrayCopy(src, 0, dst, 0, src.length).
79323 *
79324 * Using this function is far more efficient for copying array data than
79325 * iterating through a for() loop and copying each element individually.
79326 *
79327 * @method arrayCopy
79328 * @deprecated
79329 * @param {Array} src the source Array
79330 * @param {Integer} srcPosition starting position in the source Array
79331 * @param {Array} dst the destination Array
79332 * @param {Integer} dstPosition starting position in the destination Array
79333 * @param {Integer} length number of Array elements to be copied
79334 *
79335 * @example
79336 * <div class='norender'><code>
79337 * let src = ['A', 'B', 'C'];
79338 * let dst = [1, 2, 3];
79339 * let srcPosition = 1;
79340 * let dstPosition = 0;
79341 * let length = 2;
79342 *
79343 * print(src); // ['A', 'B', 'C']
79344 * print(dst); // [ 1 , 2 , 3 ]
79345 *
79346 * arrayCopy(src, srcPosition, dst, dstPosition, length);
79347 * print(dst); // ['B', 'C', 3]
79348 * </code></div>
79349 */
79350 /**
79351 * @method arrayCopy
79352 * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin">arr1.copyWithin(arr2)</a> instead.
79353 * @param {Array} src
79354 * @param {Array} dst
79355 * @param {Integer} [length]
79356 */
79357 _main.default.prototype.arrayCopy = function(
79358 src,
79359 srcPosition,
79360 dst,
79361 dstPosition,
79362 length
79363 ) {
79364 // the index to begin splicing from dst array
79365 var start;
79366 var end;
79367
79368 if (typeof length !== 'undefined') {
79369 end = Math.min(length, src.length);
79370 start = dstPosition;
79371 src = src.slice(srcPosition, end + srcPosition);
79372 } else {
79373 if (typeof dst !== 'undefined') {
79374 // src, dst, length
79375 // rename so we don't get confused
79376 end = dst;
79377 end = Math.min(end, src.length);
79378 } else {
79379 // src, dst
79380 end = src.length;
79381 }
79382
79383 start = 0;
79384 // rename so we don't get confused
79385 dst = srcPosition;
79386 src = src.slice(0, end);
79387 }
79388
79389 // Since we are not returning the array and JavaScript is pass by reference
79390 // we must modify the actual values of the array
79391 // instead of reassigning arrays
79392 Array.prototype.splice.apply(dst, [start, end].concat(src));
79393 };
79394
79395 /**
79396 * Concatenates two arrays, maps to Array.concat(). Does not modify the
79397 * input arrays.
79398 *
79399 * @method concat
79400 * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat">arr1.concat(arr2)</a> instead.
79401 * @param {Array} a first Array to concatenate
79402 * @param {Array} b second Array to concatenate
79403 * @return {Array} concatenated array
79404 *
79405 * @example
79406 * <div class = 'norender'><code>
79407 * function setup() {
79408 * let arr1 = ['A', 'B', 'C'];
79409 * let arr2 = [1, 2, 3];
79410 *
79411 * print(arr1); // ['A','B','C']
79412 * print(arr2); // [1,2,3]
79413 *
79414 * let arr3 = concat(arr1, arr2);
79415 *
79416 * print(arr1); // ['A','B','C']
79417 * print(arr2); // [1, 2, 3]
79418 * print(arr3); // ['A','B','C', 1, 2, 3]
79419 * }
79420 * </code></div>
79421 */
79422 _main.default.prototype.concat = function(list0, list1) {
79423 return list0.concat(list1);
79424 };
79425
79426 /**
79427 * Reverses the order of an array, maps to Array.reverse()
79428 *
79429 * @method reverse
79430 * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse">array.reverse()</a> instead.
79431 * @param {Array} list Array to reverse
79432 * @return {Array} the reversed list
79433 * @example
79434 * <div class='norender'><code>
79435 * function setup() {
79436 * let myArray = ['A', 'B', 'C'];
79437 * print(myArray); // ['A','B','C']
79438 *
79439 * reverse(myArray);
79440 * print(myArray); // ['C','B','A']
79441 * }
79442 * </code></div>
79443 */
79444 _main.default.prototype.reverse = function(list) {
79445 return list.reverse();
79446 };
79447
79448 /**
79449 * Decreases an array by one element and returns the shortened array,
79450 * maps to Array.pop().
79451 *
79452 * @method shorten
79453 * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/pop">array.pop()</a> instead.
79454 * @param {Array} list Array to shorten
79455 * @return {Array} shortened Array
79456 * @example
79457 * <div class = 'norender'><code>
79458 * function setup() {
79459 * let myArray = ['A', 'B', 'C'];
79460 * print(myArray); // ['A', 'B', 'C']
79461 * let newArray = shorten(myArray);
79462 * print(myArray); // ['A','B','C']
79463 * print(newArray); // ['A','B']
79464 * }
79465 * </code></div>
79466 */
79467 _main.default.prototype.shorten = function(list) {
79468 list.pop();
79469 return list;
79470 };
79471
79472 /**
79473 * Randomizes the order of the elements of an array. Implements
79474 * <a href='http://Bost.Ocks.org/mike/shuffle/' target=_blank>
79475 * Fisher-Yates Shuffle Algorithm</a>.
79476 *
79477 * @method shuffle
79478 * @param {Array} array Array to shuffle
79479 * @param {Boolean} [bool] modify passed array
79480 * @return {Array} shuffled Array
79481 * @example
79482 * <div><code>
79483 * function setup() {
79484 * let regularArr = ['ABC', 'def', createVector(), TAU, Math.E];
79485 * print(regularArr);
79486 * shuffle(regularArr, true); // force modifications to passed array
79487 * print(regularArr);
79488 *
79489 * // By default shuffle() returns a shuffled cloned array:
79490 * let newArr = shuffle(regularArr);
79491 * print(regularArr);
79492 * print(newArr);
79493 * }
79494 * </code></div>
79495 */
79496 _main.default.prototype.shuffle = function(arr, bool) {
79497 var isView = ArrayBuffer && ArrayBuffer.isView && ArrayBuffer.isView(arr);
79498 arr = bool || isView ? arr : arr.slice();
79499
79500 var rnd,
79501 tmp,
79502 idx = arr.length;
79503 while (idx > 1) {
79504 rnd = (this.random(0, 1) * idx) | 0;
79505
79506 tmp = arr[--idx];
79507 arr[idx] = arr[rnd];
79508 arr[rnd] = tmp;
79509 }
79510
79511 return arr;
79512 };
79513
79514 /**
79515 * Sorts an array of numbers from smallest to largest, or puts an array of
79516 * words in alphabetical order. The original array is not modified; a
79517 * re-ordered array is returned. The count parameter states the number of
79518 * elements to sort. For example, if there are 12 elements in an array and
79519 * count is set to 5, only the first 5 elements in the array will be sorted.
79520 *
79521 * @method sort
79522 * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort">array.sort()</a> instead.
79523 * @param {Array} list Array to sort
79524 * @param {Integer} [count] number of elements to sort, starting from 0
79525 * @return {Array} the sorted list
79526 *
79527 * @example
79528 * <div class = 'norender'><code>
79529 * function setup() {
79530 * let words = ['banana', 'apple', 'pear', 'lime'];
79531 * print(words); // ['banana', 'apple', 'pear', 'lime']
79532 * let count = 4; // length of array
79533 *
79534 * words = sort(words, count);
79535 * print(words); // ['apple', 'banana', 'lime', 'pear']
79536 * }
79537 * </code></div>
79538 * <div class = 'norender'><code>
79539 * function setup() {
79540 * let numbers = [2, 6, 1, 5, 14, 9, 8, 12];
79541 * print(numbers); // [2, 6, 1, 5, 14, 9, 8, 12]
79542 * let count = 5; // Less than the length of the array
79543 *
79544 * numbers = sort(numbers, count);
79545 * print(numbers); // [1,2,5,6,14,9,8,12]
79546 * }
79547 * </code></div>
79548 */
79549 _main.default.prototype.sort = function(list, count) {
79550 var arr = count ? list.slice(0, Math.min(count, list.length)) : list;
79551 var rest = count ? list.slice(Math.min(count, list.length)) : [];
79552 if (typeof arr[0] === 'string') {
79553 arr = arr.sort();
79554 } else {
79555 arr = arr.sort(function(a, b) {
79556 return a - b;
79557 });
79558 }
79559 return arr.concat(rest);
79560 };
79561
79562 /**
79563 * Inserts a value or an array of values into an existing array. The first
79564 * parameter specifies the initial array to be modified, and the second
79565 * parameter defines the data to be inserted. The third parameter is an index
79566 * value which specifies the array position from which to insert data.
79567 * (Remember that array index numbering starts at zero, so the first position
79568 * is 0, the second position is 1, and so on.)
79569 *
79570 * @method splice
79571 * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice">array.splice()</a> instead.
79572 * @param {Array} list Array to splice into
79573 * @param {any} value value to be spliced in
79574 * @param {Integer} position in the array from which to insert data
79575 * @return {Array} the list
79576 *
79577 * @example
79578 * <div class = 'norender'><code>
79579 * function setup() {
79580 * let myArray = [0, 1, 2, 3, 4];
79581 * let insArray = ['A', 'B', 'C'];
79582 * print(myArray); // [0, 1, 2, 3, 4]
79583 * print(insArray); // ['A','B','C']
79584 *
79585 * splice(myArray, insArray, 3);
79586 * print(myArray); // [0,1,2,'A','B','C',3,4]
79587 * }
79588 * </code></div>
79589 */
79590 _main.default.prototype.splice = function(list, value, index) {
79591 // note that splice returns spliced elements and not an array
79592 Array.prototype.splice.apply(list, [index, 0].concat(value));
79593
79594 return list;
79595 };
79596
79597 /**
79598 * Extracts an array of elements from an existing array. The list parameter
79599 * defines the array from which the elements will be copied, and the start
79600 * and count parameters specify which elements to extract. If no count is
79601 * given, elements will be extracted from the start to the end of the array.
79602 * When specifying the start, remember that the first array element is 0.
79603 * This function does not change the source array.
79604 *
79605 * @method subset
79606 * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice">array.slice()</a> instead.
79607 * @param {Array} list Array to extract from
79608 * @param {Integer} start position to begin
79609 * @param {Integer} [count] number of values to extract
79610 * @return {Array} Array of extracted elements
79611 *
79612 * @example
79613 * <div class = 'norender'><code>
79614 * function setup() {
79615 * let myArray = [1, 2, 3, 4, 5];
79616 * print(myArray); // [1, 2, 3, 4, 5]
79617 *
79618 * let sub1 = subset(myArray, 0, 3);
79619 * let sub2 = subset(myArray, 2, 2);
79620 * print(sub1); // [1,2,3]
79621 * print(sub2); // [3,4]
79622 * }
79623 * </code></div>
79624 */
79625 _main.default.prototype.subset = function(list, start, count) {
79626 if (typeof count !== 'undefined') {
79627 return list.slice(start, start + count);
79628 } else {
79629 return list.slice(start, list.length);
79630 }
79631 };
79632 var _default = _main.default;
79633 exports.default = _default;
79634 },
79635 { '../core/main': 54 }
79636 ],
79637 94: [
79638 function(_dereq_, module, exports) {
79639 'use strict';
79640 Object.defineProperty(exports, '__esModule', { value: true });
79641 exports.default = void 0;
79642
79643 var _main = _interopRequireDefault(_dereq_('../core/main'));
79644 function _interopRequireDefault(obj) {
79645 return obj && obj.__esModule ? obj : { default: obj };
79646 }
79647 /**
79648 * @module Data
79649 * @submodule Conversion
79650 * @for p5
79651 * @requires core
79652 */ /**
79653 * Converts a string to its floating point representation. The contents of a
79654 * string must resemble a number, or NaN (not a number) will be returned.
79655 * For example, float("1234.56") evaluates to 1234.56, but float("giraffe")
79656 * will return NaN.
79657 *
79658 * When an array of values is passed in, then an array of floats of the same
79659 * length is returned.
79660 *
79661 * @method float
79662 * @param {String} str float string to parse
79663 * @return {Number} floating point representation of string
79664 * @example
79665 * <div><code>
79666 * let str = '20';
79667 * let diameter = float(str);
79668 * ellipse(width / 2, height / 2, diameter, diameter);
79669 * </code></div>
79670 * <div class='norender'><code>
79671 * print(float('10.31')); // 10.31
79672 * print(float('Infinity')); // Infinity
79673 * print(float('-Infinity')); // -Infinity
79674 * </code></div>
79675 *
79676 * @alt
79677 * 20 by 20 white ellipse in the center of the canvas
79678 */ _main.default.prototype.float = function(str) {
79679 if (str instanceof Array) {
79680 return str.map(parseFloat);
79681 }
79682 return parseFloat(str);
79683 };
79684
79685 /**
79686 * Converts a boolean, string, or float to its integer representation.
79687 * When an array of values is passed in, then an int array of the same length
79688 * is returned.
79689 *
79690 * @method int
79691 * @param {String|Boolean|Number} n value to parse
79692 * @param {Integer} [radix] the radix to convert to (default: 10)
79693 * @return {Number} integer representation of value
79694 *
79695 * @example
79696 * <div class='norender'><code>
79697 * print(int('10')); // 10
79698 * print(int(10.31)); // 10
79699 * print(int(-10)); // -10
79700 * print(int(true)); // 1
79701 * print(int(false)); // 0
79702 * print(int([false, true, '10.3', 9.8])); // [0, 1, 10, 9]
79703 * print(int(Infinity)); // Infinity
79704 * print(int('-Infinity')); // -Infinity
79705 * </code></div>
79706 */
79707 /**
79708 * @method int
79709 * @param {Array} ns values to parse
79710 * @return {Number[]} integer representation of values
79711 */
79712 _main.default.prototype.int = function(n) {
79713 var radix =
79714 arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 10;
79715 if (n === Infinity || n === 'Infinity') {
79716 return Infinity;
79717 } else if (n === -Infinity || n === '-Infinity') {
79718 return -Infinity;
79719 } else if (typeof n === 'string') {
79720 return parseInt(n, radix);
79721 } else if (typeof n === 'number') {
79722 return n | 0;
79723 } else if (typeof n === 'boolean') {
79724 return n ? 1 : 0;
79725 } else if (n instanceof Array) {
79726 return n.map(function(n) {
79727 return _main.default.prototype.int(n, radix);
79728 });
79729 }
79730 };
79731
79732 /**
79733 * Converts a boolean, string or number to its string representation.
79734 * When an array of values is passed in, then an array of strings of the same
79735 * length is returned.
79736 *
79737 * @method str
79738 * @param {String|Boolean|Number|Array} n value to parse
79739 * @return {String} string representation of value
79740 * @example
79741 * <div class='norender'><code>
79742 * print(str('10')); // "10"
79743 * print(str(10.31)); // "10.31"
79744 * print(str(-10)); // "-10"
79745 * print(str(true)); // "true"
79746 * print(str(false)); // "false"
79747 * print(str([true, '10.3', 9.8])); // [ "true", "10.3", "9.8" ]
79748 * </code></div>
79749 */
79750 _main.default.prototype.str = function(n) {
79751 if (n instanceof Array) {
79752 return n.map(_main.default.prototype.str);
79753 } else {
79754 return String(n);
79755 }
79756 };
79757
79758 /**
79759 * Converts a number or string to its boolean representation.
79760 * For a number, any non-zero value (positive or negative) evaluates to true,
79761 * while zero evaluates to false. For a string, the value "true" evaluates to
79762 * true, while any other value evaluates to false. When an array of number or
79763 * string values is passed in, then a array of booleans of the same length is
79764 * returned.
79765 *
79766 * @method boolean
79767 * @param {String|Boolean|Number|Array} n value to parse
79768 * @return {Boolean} boolean representation of value
79769 * @example
79770 * <div class='norender'><code>
79771 * print(boolean(0)); // false
79772 * print(boolean(1)); // true
79773 * print(boolean('true')); // true
79774 * print(boolean('abcd')); // false
79775 * print(boolean([0, 12, 'true'])); // [false, true, true]
79776 * </code></div>
79777 */
79778 _main.default.prototype.boolean = function(n) {
79779 if (typeof n === 'number') {
79780 return n !== 0;
79781 } else if (typeof n === 'string') {
79782 return n.toLowerCase() === 'true';
79783 } else if (typeof n === 'boolean') {
79784 return n;
79785 } else if (n instanceof Array) {
79786 return n.map(_main.default.prototype.boolean);
79787 }
79788 };
79789
79790 /**
79791 * Converts a number, string representation of a number, or boolean to its byte
79792 * representation. A byte can be only a whole number between -128 and 127, so
79793 * when a value outside of this range is converted, it wraps around to the
79794 * corresponding byte representation. When an array of number, string or boolean
79795 * values is passed in, then an array of bytes the same length is returned.
79796 *
79797 * @method byte
79798 * @param {String|Boolean|Number} n value to parse
79799 * @return {Number} byte representation of value
79800 *
79801 * @example
79802 * <div class='norender'><code>
79803 * print(byte(127)); // 127
79804 * print(byte(128)); // -128
79805 * print(byte(23.4)); // 23
79806 * print(byte('23.4')); // 23
79807 * print(byte('hello')); // NaN
79808 * print(byte(true)); // 1
79809 * print(byte([0, 255, '100'])); // [0, -1, 100]
79810 * </code></div>
79811 */
79812 /**
79813 * @method byte
79814 * @param {Array} ns values to parse
79815 * @return {Number[]} array of byte representation of values
79816 */
79817 _main.default.prototype.byte = function(n) {
79818 var nn = _main.default.prototype.int(n, 10);
79819 if (typeof nn === 'number') {
79820 return (nn + 128) % 256 - 128;
79821 } else if (nn instanceof Array) {
79822 return nn.map(_main.default.prototype.byte);
79823 }
79824 };
79825
79826 /**
79827 * Converts a number or string to its corresponding single-character
79828 * string representation. If a string parameter is provided, it is first
79829 * parsed as an integer and then translated into a single-character string.
79830 * When an array of number or string values is passed in, then an array of
79831 * single-character strings of the same length is returned.
79832 *
79833 * @method char
79834 * @param {String|Number} n value to parse
79835 * @return {String} string representation of value
79836 *
79837 * @example
79838 * <div class='norender'><code>
79839 * print(char(65)); // "A"
79840 * print(char('65')); // "A"
79841 * print(char([65, 66, 67])); // [ "A", "B", "C" ]
79842 * print(join(char([65, 66, 67]), '')); // "ABC"
79843 * </code></div>
79844 */
79845 /**
79846 * @method char
79847 * @param {Array} ns values to parse
79848 * @return {String[]} array of string representation of values
79849 */
79850 _main.default.prototype.char = function(n) {
79851 if (typeof n === 'number' && !isNaN(n)) {
79852 return String.fromCharCode(n);
79853 } else if (n instanceof Array) {
79854 return n.map(_main.default.prototype.char);
79855 } else if (typeof n === 'string') {
79856 return _main.default.prototype.char(parseInt(n, 10));
79857 }
79858 };
79859
79860 /**
79861 * Converts a single-character string to its corresponding integer
79862 * representation. When an array of single-character string values is passed
79863 * in, then an array of integers of the same length is returned.
79864 *
79865 * @method unchar
79866 * @param {String} n value to parse
79867 * @return {Number} integer representation of value
79868 *
79869 * @example
79870 * <div class='norender'><code>
79871 * print(unchar('A')); // 65
79872 * print(unchar(['A', 'B', 'C'])); // [ 65, 66, 67 ]
79873 * print(unchar(split('ABC', ''))); // [ 65, 66, 67 ]
79874 * </code></div>
79875 */
79876 /**
79877 * @method unchar
79878 * @param {Array} ns values to parse
79879 * @return {Number[]} integer representation of values
79880 */
79881 _main.default.prototype.unchar = function(n) {
79882 if (typeof n === 'string' && n.length === 1) {
79883 return n.charCodeAt(0);
79884 } else if (n instanceof Array) {
79885 return n.map(_main.default.prototype.unchar);
79886 }
79887 };
79888
79889 /**
79890 * Converts a number to a string in its equivalent hexadecimal notation. If a
79891 * second parameter is passed, it is used to set the number of characters to
79892 * generate in the hexadecimal notation. When an array is passed in, an
79893 * array of strings in hexadecimal notation of the same length is returned.
79894 *
79895 * @method hex
79896 * @param {Number} n value to parse
79897 * @param {Number} [digits]
79898 * @return {String} hexadecimal string representation of value
79899 *
79900 * @example
79901 * <div class='norender'><code>
79902 * print(hex(255)); // "000000FF"
79903 * print(hex(255, 6)); // "0000FF"
79904 * print(hex([0, 127, 255], 6)); // [ "000000", "00007F", "0000FF" ]
79905 * print(Infinity); // "FFFFFFFF"
79906 * print(-Infinity); // "00000000"
79907 * </code></div>
79908 */
79909 /**
79910 * @method hex
79911 * @param {Number[]} ns array of values to parse
79912 * @param {Number} [digits]
79913 * @return {String[]} hexadecimal string representation of values
79914 */
79915 _main.default.prototype.hex = function(n, digits) {
79916 digits = digits === undefined || digits === null ? (digits = 8) : digits;
79917 if (n instanceof Array) {
79918 return n.map(function(n) {
79919 return _main.default.prototype.hex(n, digits);
79920 });
79921 } else if (n === Infinity || n === -Infinity) {
79922 var c = n === Infinity ? 'F' : '0';
79923 return c.repeat(digits);
79924 } else if (typeof n === 'number') {
79925 if (n < 0) {
79926 n = 0xffffffff + n + 1;
79927 }
79928 var hex = Number(n)
79929 .toString(16)
79930 .toUpperCase();
79931 while (hex.length < digits) {
79932 hex = '0'.concat(hex);
79933 }
79934 if (hex.length >= digits) {
79935 hex = hex.substring(hex.length - digits, hex.length);
79936 }
79937 return hex;
79938 }
79939 };
79940
79941 /**
79942 * Converts a string representation of a hexadecimal number to its equivalent
79943 * integer value. When an array of strings in hexadecimal notation is passed
79944 * in, an array of integers of the same length is returned.
79945 *
79946 * @method unhex
79947 * @param {String} n value to parse
79948 * @return {Number} integer representation of hexadecimal value
79949 *
79950 * @example
79951 * <div class='norender'><code>
79952 * print(unhex('A')); // 10
79953 * print(unhex('FF')); // 255
79954 * print(unhex(['FF', 'AA', '00'])); // [ 255, 170, 0 ]
79955 * </code></div>
79956 */
79957 /**
79958 * @method unhex
79959 * @param {Array} ns values to parse
79960 * @return {Number[]} integer representations of hexadecimal value
79961 */
79962 _main.default.prototype.unhex = function(n) {
79963 if (n instanceof Array) {
79964 return n.map(_main.default.prototype.unhex);
79965 } else {
79966 return parseInt('0x'.concat(n), 16);
79967 }
79968 };
79969 var _default = _main.default;
79970 exports.default = _default;
79971 },
79972 { '../core/main': 54 }
79973 ],
79974 95: [
79975 function(_dereq_, module, exports) {
79976 'use strict';
79977 Object.defineProperty(exports, '__esModule', { value: true });
79978 exports.default = void 0;
79979
79980 var _main = _interopRequireDefault(_dereq_('../core/main'));
79981 _dereq_('../core/friendly_errors/validate_params');
79982 _dereq_('../core/friendly_errors/file_errors');
79983 _dereq_('../core/friendly_errors/fes_core');
79984 function _interopRequireDefault(obj) {
79985 return obj && obj.__esModule ? obj : { default: obj };
79986 } /** //return p5; //LM is this a mistake?
79987 * @module Data
79988 * @submodule String Functions
79989 * @for p5
79990 * @requires core
79991 */
79992 /**
79993 * Combines an array of Strings into one String, each separated by the
79994 * character(s) used for the separator parameter. To join arrays of ints or
79995 * floats, it's necessary to first convert them to Strings using <a href="#/p5/nf">nf()</a> or
79996 * nfs().
79997 *
79998 * @method join
79999 * @param {Array} list array of Strings to be joined
80000 * @param {String} separator String to be placed between each item
80001 * @return {String} joined String
80002 * @example
80003 * <div>
80004 * <code>
80005 * let array = ['Hello', 'world!'];
80006 * let separator = ' ';
80007 * let message = join(array, separator);
80008 * text(message, 5, 50);
80009 * </code>
80010 * </div>
80011 *
80012 * @alt
80013 * "hello world!" displayed middle left of canvas.
80014 */ _main.default.prototype.join = function(list, separator) {
80015 _main.default._validateParameters('join', arguments);
80016 return list.join(separator);
80017 };
80018
80019 /**
80020 * This function is used to apply a regular expression to a piece of text,
80021 * and return matching groups (elements found inside parentheses) as a
80022 * String array. If there are no matches, a null value will be returned.
80023 * If no groups are specified in the regular expression, but the sequence
80024 * matches, an array of length 1 (with the matched text as the first element
80025 * of the array) will be returned.
80026 *
80027 * To use the function, first check to see if the result is null. If the
80028 * result is null, then the sequence did not match at all. If the sequence
80029 * did match, an array is returned.
80030 *
80031 * If there are groups (specified by sets of parentheses) in the regular
80032 * expression, then the contents of each will be returned in the array.
80033 * Element [0] of a regular expression match returns the entire matching
80034 * string, and the match groups start at element [1] (the first group is [1],
80035 * the second [2], and so on).
80036 *
80037 * @method match
80038 * @param {String} str the String to be searched
80039 * @param {String} regexp the regexp to be used for matching
80040 * @return {String[]} Array of Strings found
80041 * @example
80042 * <div>
80043 * <code>
80044 * let string = 'Hello p5js*!';
80045 * let regexp = 'p5js\\*';
80046 * let m = match(string, regexp);
80047 * text(m, 5, 50);
80048 * </code>
80049 * </div>
80050 *
80051 * @alt
80052 * "p5js*" displayed middle left of canvas.
80053 */
80054 _main.default.prototype.match = function(str, reg) {
80055 _main.default._validateParameters('match', arguments);
80056 return str.match(reg);
80057 };
80058
80059 /**
80060 * This function is used to apply a regular expression to a piece of text,
80061 * and return a list of matching groups (elements found inside parentheses)
80062 * as a two-dimensional String array. If there are no matches, a null value
80063 * will be returned. If no groups are specified in the regular expression,
80064 * but the sequence matches, a two dimensional array is still returned, but
80065 * the second dimension is only of length one.
80066 *
80067 * To use the function, first check to see if the result is null. If the
80068 * result is null, then the sequence did not match at all. If the sequence
80069 * did match, a 2D array is returned.
80070 *
80071 * If there are groups (specified by sets of parentheses) in the regular
80072 * expression, then the contents of each will be returned in the array.
80073 * Assuming a loop with counter variable i, element [i][0] of a regular
80074 * expression match returns the entire matching string, and the match groups
80075 * start at element [i][1] (the first group is [i][1], the second [i][2],
80076 * and so on).
80077 *
80078 * @method matchAll
80079 * @param {String} str the String to be searched
80080 * @param {String} regexp the regexp to be used for matching
80081 * @return {String[]} 2d Array of Strings found
80082 * @example
80083 * <div class="norender">
80084 * <code>
80085 * let string = 'Hello p5js*! Hello world!';
80086 * let regexp = 'Hello';
80087 * matchAll(string, regexp);
80088 * </code>
80089 * </div>
80090 */
80091 _main.default.prototype.matchAll = function(str, reg) {
80092 _main.default._validateParameters('matchAll', arguments);
80093 var re = new RegExp(reg, 'g');
80094 var match = re.exec(str);
80095 var matches = [];
80096 while (match !== null) {
80097 matches.push(match);
80098 // matched text: match[0]
80099 // match start: match.index
80100 // capturing group n: match[n]
80101 match = re.exec(str);
80102 }
80103 return matches;
80104 };
80105
80106 /**
80107 * Utility function for formatting numbers into strings. There are two
80108 * versions: one for formatting floats, and one for formatting ints.
80109 * The values for the digits, left, and right parameters should always
80110 * be positive integers.
80111 * (NOTE): Be cautious when using left and right parameters as it prepends numbers of 0's if the parameter
80112 * if greater than the current length of the number.
80113 * For example if number is 123.2 and left parameter passed is 4 which is greater than length of 123
80114 * (integer part) i.e 3 than result will be 0123.2. Same case for right parameter i.e. if right is 3 than
80115 * the result will be 123.200.
80116 *
80117 * @method nf
80118 * @param {Number|String} num the Number to format
80119 * @param {Integer|String} [left] number of digits to the left of the
80120 * decimal point
80121 * @param {Integer|String} [right] number of digits to the right of the
80122 * decimal point
80123 * @return {String} formatted String
80124 *
80125 * @example
80126 * <div>
80127 * <code>
80128 * let myFont;
80129 * function preload() {
80130 * myFont = loadFont('assets/fonts/inconsolata.ttf');
80131 * }
80132 * function setup() {
80133 * background(200);
80134 * let num1 = 321;
80135 * let num2 = -1321;
80136 *
80137 * noStroke();
80138 * fill(0);
80139 * textFont(myFont);
80140 * textSize(22);
80141 *
80142 * text(nf(num1, 4, 2), 10, 30);
80143 * text(nf(num2, 4, 2), 10, 80);
80144 * // Draw dividing line
80145 * stroke(120);
80146 * line(0, 50, width, 50);
80147 * }
80148 * </code>
80149 * </div>
80150 *
80151 * @alt
80152 * "0321.00" middle top, -1321.00" middle bottom canvas
80153 */
80154 /**
80155 * @method nf
80156 * @param {Array} nums the Numbers to format
80157 * @param {Integer|String} [left]
80158 * @param {Integer|String} [right]
80159 * @return {String[]} formatted Strings
80160 */
80161 _main.default.prototype.nf = function(nums, left, right) {
80162 _main.default._validateParameters('nf', arguments);
80163 if (nums instanceof Array) {
80164 return nums.map(function(x) {
80165 return doNf(x, left, right);
80166 });
80167 } else {
80168 var typeOfFirst = Object.prototype.toString.call(nums);
80169 if (typeOfFirst === '[object Arguments]') {
80170 if (nums.length === 3) {
80171 return this.nf(nums[0], nums[1], nums[2]);
80172 } else if (nums.length === 2) {
80173 return this.nf(nums[0], nums[1]);
80174 } else {
80175 return this.nf(nums[0]);
80176 }
80177 } else {
80178 return doNf(nums, left, right);
80179 }
80180 }
80181 };
80182
80183 function doNf(num, left, right) {
80184 var neg = num < 0;
80185 var n = neg ? num.toString().substring(1) : num.toString();
80186 var decimalInd = n.indexOf('.');
80187 var intPart = decimalInd !== -1 ? n.substring(0, decimalInd) : n;
80188 var decPart = decimalInd !== -1 ? n.substring(decimalInd + 1) : '';
80189 var str = neg ? '-' : '';
80190 if (typeof right !== 'undefined') {
80191 var decimal = '';
80192 if (decimalInd !== -1 || right - decPart.length > 0) {
80193 decimal = '.';
80194 }
80195 if (decPart.length > right) {
80196 decPart = decPart.substring(0, right);
80197 }
80198 for (var i = 0; i < left - intPart.length; i++) {
80199 str += '0';
80200 }
80201 str += intPart;
80202 str += decimal;
80203 str += decPart;
80204 for (var j = 0; j < right - decPart.length; j++) {
80205 str += '0';
80206 }
80207 return str;
80208 } else {
80209 for (var k = 0; k < Math.max(left - intPart.length, 0); k++) {
80210 str += '0';
80211 }
80212 str += n;
80213 return str;
80214 }
80215 }
80216
80217 /**
80218 * Utility function for formatting numbers into strings and placing
80219 * appropriate commas to mark units of 1000. There are two versions: one
80220 * for formatting ints, and one for formatting an array of ints. The value
80221 * for the right parameter should always be a positive integer.
80222 *
80223 * @method nfc
80224 * @param {Number|String} num the Number to format
80225 * @param {Integer|String} [right] number of digits to the right of the
80226 * decimal point
80227 * @return {String} formatted String
80228 *
80229 * @example
80230 * <div>
80231 * <code>
80232 * function setup() {
80233 * background(200);
80234 * let num = 11253106.115;
80235 * let numArr = [1, 1, 2];
80236 *
80237 * noStroke();
80238 * fill(0);
80239 * textSize(12);
80240 *
80241 * // Draw formatted numbers
80242 * text(nfc(num, 4), 10, 30);
80243 * text(nfc(numArr, 2), 10, 80);
80244 *
80245 * // Draw dividing line
80246 * stroke(120);
80247 * line(0, 50, width, 50);
80248 * }
80249 * </code>
80250 * </div>
80251 *
80252 * @alt
80253 * "11,253,106.115" top middle and "1.00,1.00,2.00" displayed bottom mid
80254 */
80255 /**
80256 * @method nfc
80257 * @param {Array} nums the Numbers to format
80258 * @param {Integer|String} [right]
80259 * @return {String[]} formatted Strings
80260 */
80261 _main.default.prototype.nfc = function(num, right) {
80262 _main.default._validateParameters('nfc', arguments);
80263 if (num instanceof Array) {
80264 return num.map(function(x) {
80265 return doNfc(x, right);
80266 });
80267 } else {
80268 return doNfc(num, right);
80269 }
80270 };
80271 function doNfc(num, right) {
80272 num = num.toString();
80273 var dec = num.indexOf('.');
80274 var rem = dec !== -1 ? num.substring(dec) : '';
80275 var n = dec !== -1 ? num.substring(0, dec) : num;
80276 n = n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
80277 if (right === 0) {
80278 rem = '';
80279 } else if (typeof right !== 'undefined') {
80280 if (right > rem.length) {
80281 rem += dec === -1 ? '.' : '';
80282 var len = right - rem.length + 1;
80283 for (var i = 0; i < len; i++) {
80284 rem += '0';
80285 }
80286 } else {
80287 rem = rem.substring(0, right + 1);
80288 }
80289 }
80290 return n + rem;
80291 }
80292
80293 /**
80294 * Utility function for formatting numbers into strings. Similar to <a href="#/p5/nf">nf()</a> but
80295 * puts a "+" in front of positive numbers and a "-" in front of negative
80296 * numbers. There are two versions: one for formatting floats, and one for
80297 * formatting ints. The values for left, and right parameters
80298 * should always be positive integers.
80299 *
80300 * @method nfp
80301 * @param {Number} num the Number to format
80302 * @param {Integer} [left] number of digits to the left of the decimal
80303 * point
80304 * @param {Integer} [right] number of digits to the right of the
80305 * decimal point
80306 * @return {String} formatted String
80307 *
80308 * @example
80309 * <div>
80310 * <code>
80311 * function setup() {
80312 * background(200);
80313 * let num1 = 11253106.115;
80314 * let num2 = -11253106.115;
80315 *
80316 * noStroke();
80317 * fill(0);
80318 * textSize(12);
80319 *
80320 * // Draw formatted numbers
80321 * text(nfp(num1, 4, 2), 10, 30);
80322 * text(nfp(num2, 4, 2), 10, 80);
80323 *
80324 * // Draw dividing line
80325 * stroke(120);
80326 * line(0, 50, width, 50);
80327 * }
80328 * </code>
80329 * </div>
80330 *
80331 * @alt
80332 * "+11253106.11" top middle and "-11253106.11" displayed bottom middle
80333 */
80334 /**
80335 * @method nfp
80336 * @param {Number[]} nums the Numbers to format
80337 * @param {Integer} [left]
80338 * @param {Integer} [right]
80339 * @return {String[]} formatted Strings
80340 */
80341 _main.default.prototype.nfp = function() {
80342 for (
80343 var _len = arguments.length, args = new Array(_len), _key = 0;
80344 _key < _len;
80345 _key++
80346 ) {
80347 args[_key] = arguments[_key];
80348 }
80349 _main.default._validateParameters('nfp', args);
80350 var nfRes = _main.default.prototype.nf.apply(this, args);
80351 if (nfRes instanceof Array) {
80352 return nfRes.map(addNfp);
80353 } else {
80354 return addNfp(nfRes);
80355 }
80356 };
80357
80358 function addNfp(num) {
80359 return parseFloat(num) > 0 ? '+'.concat(num.toString()) : num.toString();
80360 }
80361
80362 /**
80363 * Utility function for formatting numbers into strings. Similar to <a href="#/p5/nf">nf()</a> but
80364 * puts an additional "_" (space) in front of positive numbers just in case to align it with negative
80365 * numbers which includes "-" (minus) sign.
80366 * The main usecase of nfs() can be seen when one wants to align the digits (place values) of a non-negative
80367 * number with some negative number (See the example to get a clear picture).
80368 * There are two versions: one for formatting float, and one for formatting int.
80369 * The values for the digits, left, and right parameters should always be positive integers.
80370 * (IMP): The result on the canvas basically the expected alignment can vary based on the typeface you are using.
80371 * (NOTE): Be cautious when using left and right parameters as it prepends numbers of 0's if the parameter
80372 * if greater than the current length of the number.
80373 * For example if number is 123.2 and left parameter passed is 4 which is greater than length of 123
80374 * (integer part) i.e 3 than result will be 0123.2. Same case for right parameter i.e. if right is 3 than
80375 * the result will be 123.200.
80376 *
80377 * @method nfs
80378 * @param {Number} num the Number to format
80379 * @param {Integer} [left] number of digits to the left of the decimal
80380 * point
80381 * @param {Integer} [right] number of digits to the right of the
80382 * decimal point
80383 * @return {String} formatted String
80384 *
80385 * @example
80386 * <div>
80387 * <code>
80388 * let myFont;
80389 * function preload() {
80390 * myFont = loadFont('assets/fonts/inconsolata.ttf');
80391 * }
80392 * function setup() {
80393 * background(200);
80394 * let num1 = 321;
80395 * let num2 = -1321;
80396 *
80397 * noStroke();
80398 * fill(0);
80399 * textFont(myFont);
80400 * textSize(22);
80401 *
80402 * // nfs() aligns num1 (positive number) with num2 (negative number) by
80403 * // adding a blank space in front of the num1 (positive number)
80404 * // [left = 4] in num1 add one 0 in front, to align the digits with num2
80405 * // [right = 2] in num1 and num2 adds two 0's after both numbers
80406 * // To see the differences check the example of nf() too.
80407 * text(nfs(num1, 4, 2), 10, 30);
80408 * text(nfs(num2, 4, 2), 10, 80);
80409 * // Draw dividing line
80410 * stroke(120);
80411 * line(0, 50, width, 50);
80412 * }
80413 * </code>
80414 * </div>
80415 *
80416 * @alt
80417 * "0321.00" top middle and "-1321.00" displayed bottom middle
80418 */
80419 /**
80420 * @method nfs
80421 * @param {Array} nums the Numbers to format
80422 * @param {Integer} [left]
80423 * @param {Integer} [right]
80424 * @return {String[]} formatted Strings
80425 */
80426 _main.default.prototype.nfs = function() {
80427 for (
80428 var _len2 = arguments.length, args = new Array(_len2), _key2 = 0;
80429 _key2 < _len2;
80430 _key2++
80431 ) {
80432 args[_key2] = arguments[_key2];
80433 }
80434 _main.default._validateParameters('nfs', args);
80435 var nfRes = _main.default.prototype.nf.apply(this, args);
80436 if (nfRes instanceof Array) {
80437 return nfRes.map(addNfs);
80438 } else {
80439 return addNfs(nfRes);
80440 }
80441 };
80442
80443 function addNfs(num) {
80444 return parseFloat(num) >= 0 ? ' '.concat(num.toString()) : num.toString();
80445 }
80446
80447 /**
80448 * The <a href="#/p5/split">split()</a> function maps to String.split(), it breaks a String into
80449 * pieces using a character or string as the delimiter. The delim parameter
80450 * specifies the character or characters that mark the boundaries between
80451 * each piece. A String[] array is returned that contains each of the pieces.
80452 *
80453 * The <a href="#/p5/splitTokens">splitTokens()</a> function works in a similar fashion, except that it
80454 * splits using a range of characters instead of a specific character or
80455 * sequence.
80456 *
80457 * @method split
80458 * @param {String} value the String to be split
80459 * @param {String} delim the String used to separate the data
80460 * @return {String[]} Array of Strings
80461 * @example
80462 * <div>
80463 * <code>
80464 * let names = 'Pat,Xio,Alex';
80465 * let splitString = split(names, ',');
80466 * text(splitString[0], 5, 30);
80467 * text(splitString[1], 5, 50);
80468 * text(splitString[2], 5, 70);
80469 * </code>
80470 * </div>
80471 *
80472 * @alt
80473 * "pat" top left, "Xio" mid left and "Alex" displayed bottom left
80474 */
80475 _main.default.prototype.split = function(str, delim) {
80476 _main.default._validateParameters('split', arguments);
80477 return str.split(delim);
80478 };
80479
80480 /**
80481 * The <a href="#/p5/splitTokens">splitTokens()</a> function splits a String at one or many character
80482 * delimiters or "tokens." The delim parameter specifies the character or
80483 * characters to be used as a boundary.
80484 *
80485 * If no delim characters are specified, any whitespace character is used to
80486 * split. Whitespace characters include tab (\t), line feed (\n), carriage
80487 * return (\r), form feed (\f), and space.
80488 *
80489 * @method splitTokens
80490 * @param {String} value the String to be split
80491 * @param {String} [delim] list of individual Strings that will be used as
80492 * separators
80493 * @return {String[]} Array of Strings
80494 * @example
80495 * <div class = "norender">
80496 * <code>
80497 * function setup() {
80498 * let myStr = 'Mango, Banana, Lime';
80499 * let myStrArr = splitTokens(myStr, ',');
80500 *
80501 * print(myStrArr); // prints : ["Mango"," Banana"," Lime"]
80502 * }
80503 * </code>
80504 * </div>
80505 */
80506 _main.default.prototype.splitTokens = function(value, delims) {
80507 _main.default._validateParameters('splitTokens', arguments);
80508 var d;
80509 if (typeof delims !== 'undefined') {
80510 var str = delims;
80511 var sqc = /\]/g.exec(str);
80512 var sqo = /\[/g.exec(str);
80513 if (sqo && sqc) {
80514 str = str.slice(0, sqc.index) + str.slice(sqc.index + 1);
80515 sqo = /\[/g.exec(str);
80516 str = str.slice(0, sqo.index) + str.slice(sqo.index + 1);
80517 d = new RegExp('[\\['.concat(str, '\\]]'), 'g');
80518 } else if (sqc) {
80519 str = str.slice(0, sqc.index) + str.slice(sqc.index + 1);
80520 d = new RegExp('['.concat(str, '\\]]'), 'g');
80521 } else if (sqo) {
80522 str = str.slice(0, sqo.index) + str.slice(sqo.index + 1);
80523 d = new RegExp('['.concat(str, '\\[]'), 'g');
80524 } else {
80525 d = new RegExp('['.concat(str, ']'), 'g');
80526 }
80527 } else {
80528 d = /\s/g;
80529 }
80530 return value.split(d).filter(function(n) {
80531 return n;
80532 });
80533 };
80534
80535 /**
80536 * Removes whitespace characters from the beginning and end of a String. In
80537 * addition to standard whitespace characters such as space, carriage return,
80538 * and tab, this function also removes the Unicode "nbsp" character.
80539 *
80540 * @method trim
80541 * @param {String} str a String to be trimmed
80542 * @return {String} a trimmed String
80543 *
80544 * @example
80545 * <div>
80546 * <code>
80547 * let string = trim(' No new lines\n ');
80548 * text(string + ' here', 2, 50);
80549 * </code>
80550 * </div>
80551 *
80552 * @alt
80553 * "No new lines here" displayed center canvas
80554 */
80555 /**
80556 * @method trim
80557 * @param {Array} strs an Array of Strings to be trimmed
80558 * @return {String[]} an Array of trimmed Strings
80559 */
80560 _main.default.prototype.trim = function(str) {
80561 _main.default._validateParameters('trim', arguments);
80562 if (str instanceof Array) {
80563 return str.map(this.trim);
80564 } else {
80565 return str.trim();
80566 }
80567 };
80568 var _default = _main.default;
80569 exports.default = _default;
80570 },
80571 {
80572 '../core/friendly_errors/fes_core': 46,
80573 '../core/friendly_errors/file_errors': 47,
80574 '../core/friendly_errors/validate_params': 49,
80575 '../core/main': 54
80576 }
80577 ],
80578 96: [
80579 function(_dereq_, module, exports) {
80580 'use strict';
80581 Object.defineProperty(exports, '__esModule', { value: true });
80582 exports.default = void 0;
80583
80584 var _main = _interopRequireDefault(_dereq_('../core/main'));
80585 function _interopRequireDefault(obj) {
80586 return obj && obj.__esModule ? obj : { default: obj };
80587 }
80588 /**
80589 * @module IO
80590 * @submodule Time & Date
80591 * @for p5
80592 * @requires core
80593 */ /**
80594 * p5.js communicates with the clock on your computer. The <a href="#/p5/day">day()</a> function
80595 * returns the current day as a value from 1 - 31.
80596 *
80597 * @method day
80598 * @return {Integer} the current day
80599 * @example
80600 * <div>
80601 * <code>
80602 * let d = day();
80603 * text('Current day: \n' + d, 5, 50);
80604 * </code>
80605 * </div>
80606 *
80607 * @alt
80608 * Current day is displayed
80609 */ _main.default.prototype.day = function() {
80610 return new Date().getDate();
80611 };
80612
80613 /**
80614 * p5.js communicates with the clock on your computer. The <a href="#/p5/hour">hour()</a> function
80615 * returns the current hour as a value from 0 - 23.
80616 *
80617 * @method hour
80618 * @return {Integer} the current hour
80619 * @example
80620 * <div>
80621 * <code>
80622 * let h = hour();
80623 * text('Current hour:\n' + h, 5, 50);
80624 * </code>
80625 * </div>
80626 *
80627 * @alt
80628 * Current hour is displayed
80629 */
80630 _main.default.prototype.hour = function() {
80631 return new Date().getHours();
80632 };
80633
80634 /**
80635 * p5.js communicates with the clock on your computer. The <a href="#/p5/minute">minute()</a> function
80636 * returns the current minute as a value from 0 - 59.
80637 *
80638 * @method minute
80639 * @return {Integer} the current minute
80640 * @example
80641 * <div>
80642 * <code>
80643 * let m = minute();
80644 * text('Current minute: \n' + m, 5, 50);
80645 * </code>
80646 * </div>
80647 *
80648 * @alt
80649 * Current minute is displayed
80650 */
80651 _main.default.prototype.minute = function() {
80652 return new Date().getMinutes();
80653 };
80654
80655 /**
80656 * Returns the number of milliseconds (thousandths of a second) since
80657 * starting the sketch (when `setup()` is called). This information is often
80658 * used for timing events and animation sequences.
80659 *
80660 * @method millis
80661 * @return {Number} the number of milliseconds since starting the sketch
80662 * @example
80663 * <div>
80664 * <code>
80665 * let millisecond = millis();
80666 * text('Milliseconds \nrunning: \n' + millisecond, 5, 40);
80667 * </code>
80668 * </div>
80669 *
80670 * @alt
80671 * number of milliseconds since sketch has started displayed
80672 */
80673 _main.default.prototype.millis = function() {
80674 if (this._millisStart === -1) {
80675 // Sketch has not started
80676 return 0;
80677 } else {
80678 return window.performance.now() - this._millisStart;
80679 }
80680 };
80681
80682 /**
80683 * p5.js communicates with the clock on your computer. The <a href="#/p5/month">month()</a> function
80684 * returns the current month as a value from 1 - 12.
80685 *
80686 * @method month
80687 * @return {Integer} the current month
80688 * @example
80689 * <div>
80690 * <code>
80691 * let m = month();
80692 * text('Current month: \n' + m, 5, 50);
80693 * </code>
80694 * </div>
80695 *
80696 * @alt
80697 * Current month is displayed
80698 */
80699 _main.default.prototype.month = function() {
80700 //January is 0!
80701 return new Date().getMonth() + 1;
80702 };
80703
80704 /**
80705 * p5.js communicates with the clock on your computer. The <a href="#/p5/second">second()</a> function
80706 * returns the current second as a value from 0 - 59.
80707 *
80708 * @method second
80709 * @return {Integer} the current second
80710 * @example
80711 * <div>
80712 * <code>
80713 * let s = second();
80714 * text('Current second: \n' + s, 5, 50);
80715 * </code>
80716 * </div>
80717 *
80718 * @alt
80719 * Current second is displayed
80720 */
80721 _main.default.prototype.second = function() {
80722 return new Date().getSeconds();
80723 };
80724
80725 /**
80726 * p5.js communicates with the clock on your computer. The <a href="#/p5/year">year()</a> function
80727 * returns the current year as an integer (2014, 2015, 2016, etc).
80728 *
80729 * @method year
80730 * @return {Integer} the current year
80731 * @example
80732 * <div>
80733 * <code>
80734 * let y = year();
80735 * text('Current year: \n' + y, 5, 50);
80736 * </code>
80737 * </div>
80738 *
80739 * @alt
80740 * Current year is displayed
80741 */
80742 _main.default.prototype.year = function() {
80743 return new Date().getFullYear();
80744 };
80745 var _default = _main.default;
80746 exports.default = _default;
80747 },
80748 { '../core/main': 54 }
80749 ],
80750 97: [
80751 function(_dereq_, module, exports) {
80752 'use strict';
80753 function _typeof(obj) {
80754 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
80755 _typeof = function _typeof(obj) {
80756 return typeof obj;
80757 };
80758 } else {
80759 _typeof = function _typeof(obj) {
80760 return obj &&
80761 typeof Symbol === 'function' &&
80762 obj.constructor === Symbol &&
80763 obj !== Symbol.prototype
80764 ? 'symbol'
80765 : typeof obj;
80766 };
80767 }
80768 return _typeof(obj);
80769 }
80770 Object.defineProperty(exports, '__esModule', { value: true });
80771 exports.default = void 0;
80772
80773 var _main = _interopRequireDefault(_dereq_('../core/main'));
80774 _dereq_('./p5.Geometry');
80775 var constants = _interopRequireWildcard(_dereq_('../core/constants'));
80776 function _getRequireWildcardCache() {
80777 if (typeof WeakMap !== 'function') return null;
80778 var cache = new WeakMap();
80779 _getRequireWildcardCache = function _getRequireWildcardCache() {
80780 return cache;
80781 };
80782 return cache;
80783 }
80784 function _interopRequireWildcard(obj) {
80785 if (obj && obj.__esModule) {
80786 return obj;
80787 }
80788 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) {
80789 return { default: obj };
80790 }
80791 var cache = _getRequireWildcardCache();
80792 if (cache && cache.has(obj)) {
80793 return cache.get(obj);
80794 }
80795 var newObj = {};
80796 var hasPropertyDescriptor =
80797 Object.defineProperty && Object.getOwnPropertyDescriptor;
80798 for (var key in obj) {
80799 if (Object.prototype.hasOwnProperty.call(obj, key)) {
80800 var desc = hasPropertyDescriptor
80801 ? Object.getOwnPropertyDescriptor(obj, key)
80802 : null;
80803 if (desc && (desc.get || desc.set)) {
80804 Object.defineProperty(newObj, key, desc);
80805 } else {
80806 newObj[key] = obj[key];
80807 }
80808 }
80809 }
80810 newObj.default = obj;
80811 if (cache) {
80812 cache.set(obj, newObj);
80813 }
80814 return newObj;
80815 }
80816 function _interopRequireDefault(obj) {
80817 return obj && obj.__esModule ? obj : { default: obj };
80818 }
80819 /**
80820 * @module Shape
80821 * @submodule 3D Primitives
80822 * @for p5
80823 * @requires core
80824 * @requires p5.Geometry
80825 */ /**
80826 * Draw a plane with given a width and height
80827 * @method plane
80828 * @param {Number} [width] width of the plane
80829 * @param {Number} [height] height of the plane
80830 * @param {Integer} [detailX] Optional number of triangle
80831 * subdivisions in x-dimension
80832 * @param {Integer} [detailY] Optional number of triangle
80833 * subdivisions in y-dimension
80834 * @chainable
80835 * @example
80836 * <div>
80837 * <code>
80838 * // draw a plane
80839 * // with width 50 and height 50
80840 * function setup() {
80841 * createCanvas(100, 100, WEBGL);
80842 * }
80843 *
80844 * function draw() {
80845 * background(200);
80846 * plane(50, 50);
80847 * }
80848 * </code>
80849 * </div>
80850 *
80851 * @alt
80852 * Nothing displayed on canvas
80853 * Rotating interior view of a box with sides that change color.
80854 * 3d red and green gradient.
80855 * Rotating interior view of a cylinder with sides that change color.
80856 * Rotating view of a cylinder with sides that change color.
80857 * 3d red and green gradient.
80858 * rotating view of a multi-colored cylinder with concave sides.
80859 */ _main.default.prototype.plane = function(width, height, detailX, detailY) {
80860 this._assert3d('plane');
80861 _main.default._validateParameters('plane', arguments);
80862 if (typeof width === 'undefined') {
80863 width = 50;
80864 }
80865 if (typeof height === 'undefined') {
80866 height = width;
80867 }
80868
80869 if (typeof detailX === 'undefined') {
80870 detailX = 1;
80871 }
80872 if (typeof detailY === 'undefined') {
80873 detailY = 1;
80874 }
80875
80876 var gId = 'plane|'.concat(detailX, '|').concat(detailY);
80877
80878 if (!this._renderer.geometryInHash(gId)) {
80879 var _plane = function _plane() {
80880 var u, v, p;
80881 for (var i = 0; i <= this.detailY; i++) {
80882 v = i / this.detailY;
80883 for (var j = 0; j <= this.detailX; j++) {
80884 u = j / this.detailX;
80885 p = new _main.default.Vector(u - 0.5, v - 0.5, 0);
80886 this.vertices.push(p);
80887 this.uvs.push(u, v);
80888 }
80889 }
80890 };
80891 var planeGeom = new _main.default.Geometry(detailX, detailY, _plane);
80892 planeGeom.computeFaces().computeNormals();
80893 if (detailX <= 1 && detailY <= 1) {
80894 planeGeom._makeTriangleEdges()._edgesToVertices();
80895 } else if (this._renderer._doStroke) {
80896 console.log(
80897 'Cannot draw stroke on plane objects with more' +
80898 ' than 1 detailX or 1 detailY'
80899 );
80900 }
80901 this._renderer.createBuffers(gId, planeGeom);
80902 }
80903
80904 this._renderer.drawBuffersScaled(gId, width, height, 1);
80905 return this;
80906 };
80907
80908 /**
80909 * Draw a box with given width, height and depth
80910 * @method box
80911 * @param {Number} [width] width of the box
80912 * @param {Number} [Height] height of the box
80913 * @param {Number} [depth] depth of the box
80914 * @param {Integer} [detailX] Optional number of triangle
80915 * subdivisions in x-dimension
80916 * @param {Integer} [detailY] Optional number of triangle
80917 * subdivisions in y-dimension
80918 * @chainable
80919 * @example
80920 * <div>
80921 * <code>
80922 * // draw a spinning box
80923 * // with width, height and depth of 50
80924 * function setup() {
80925 * createCanvas(100, 100, WEBGL);
80926 * }
80927 *
80928 * function draw() {
80929 * background(200);
80930 * rotateX(frameCount * 0.01);
80931 * rotateY(frameCount * 0.01);
80932 * box(50);
80933 * }
80934 * </code>
80935 * </div>
80936 */
80937 _main.default.prototype.box = function(width, height, depth, detailX, detailY) {
80938 this._assert3d('box');
80939 _main.default._validateParameters('box', arguments);
80940 if (typeof width === 'undefined') {
80941 width = 50;
80942 }
80943 if (typeof height === 'undefined') {
80944 height = width;
80945 }
80946 if (typeof depth === 'undefined') {
80947 depth = height;
80948 }
80949
80950 var perPixelLighting =
80951 this._renderer.attributes && this._renderer.attributes.perPixelLighting;
80952 if (typeof detailX === 'undefined') {
80953 detailX = perPixelLighting ? 1 : 4;
80954 }
80955 if (typeof detailY === 'undefined') {
80956 detailY = perPixelLighting ? 1 : 4;
80957 }
80958
80959 var gId = 'box|'.concat(detailX, '|').concat(detailY);
80960 if (!this._renderer.geometryInHash(gId)) {
80961 var _box = function _box() {
80962 var cubeIndices = [
80963 [0, 4, 2, 6], // -1, 0, 0],// -x
80964 [1, 3, 5, 7], // +1, 0, 0],// +x
80965 [0, 1, 4, 5], // 0, -1, 0],// -y
80966 [2, 6, 3, 7], // 0, +1, 0],// +y
80967 [0, 2, 1, 3], // 0, 0, -1],// -z
80968 [4, 5, 6, 7] // 0, 0, +1] // +z
80969 ];
80970 //using strokeIndices instead of faces for strokes
80971 //to avoid diagonal stroke lines across face of box
80972 this.strokeIndices = [
80973 [0, 1],
80974 [1, 3],
80975 [3, 2],
80976 [6, 7],
80977 [8, 9],
80978 [9, 11],
80979 [14, 15],
80980 [16, 17],
80981 [17, 19],
80982 [18, 19],
80983 [20, 21],
80984 [22, 23]
80985 ];
80986
80987 for (var i = 0; i < cubeIndices.length; i++) {
80988 var cubeIndex = cubeIndices[i];
80989 var v = i * 4;
80990 for (var j = 0; j < 4; j++) {
80991 var d = cubeIndex[j];
80992 //inspired by lightgl:
80993 //https://github.com/evanw/lightgl.js
80994 //octants:https://en.wikipedia.org/wiki/Octant_(solid_geometry)
80995 var octant = new _main.default.Vector(
80996 ((d & 1) * 2 - 1) / 2,
80997 ((d & 2) - 1) / 2,
80998 ((d & 4) / 2 - 1) / 2
80999 );
81000
81001 this.vertices.push(octant);
81002 this.uvs.push(j & 1, (j & 2) / 2);
81003 }
81004 this.faces.push([v, v + 1, v + 2]);
81005 this.faces.push([v + 2, v + 1, v + 3]);
81006 }
81007 };
81008 var boxGeom = new _main.default.Geometry(detailX, detailY, _box);
81009 boxGeom.computeNormals();
81010 if (detailX <= 4 && detailY <= 4) {
81011 boxGeom._makeTriangleEdges()._edgesToVertices();
81012 } else if (this._renderer._doStroke) {
81013 console.log(
81014 'Cannot draw stroke on box objects with more' +
81015 ' than 4 detailX or 4 detailY'
81016 );
81017 }
81018 //initialize our geometry buffer with
81019 //the key val pair:
81020 //geometry Id, Geom object
81021 this._renderer.createBuffers(gId, boxGeom);
81022 }
81023 this._renderer.drawBuffersScaled(gId, width, height, depth);
81024
81025 return this;
81026 };
81027
81028 /**
81029 * Draw a sphere with given radius.
81030 *
81031 * DetailX and detailY determines the number of subdivisions in the x-dimension
81032 * and the y-dimension of a sphere. More subdivisions make the sphere seem
81033 * smoother. The recommended maximum values are both 24. Using a value greater
81034 * than 24 may cause a warning or slow down the browser.
81035 * @method sphere
81036 * @param {Number} [radius] radius of circle
81037 * @param {Integer} [detailX] optional number of subdivisions in x-dimension
81038 * @param {Integer} [detailY] optional number of subdivisions in y-dimension
81039 *
81040 * @chainable
81041 * @example
81042 * <div>
81043 * <code>
81044 * // draw a sphere with radius 40
81045 * function setup() {
81046 * createCanvas(100, 100, WEBGL);
81047 * }
81048 *
81049 * function draw() {
81050 * background(205, 102, 94);
81051 * sphere(40);
81052 * }
81053 * </code>
81054 * </div>
81055 *
81056 * @example
81057 * <div>
81058 * <code>
81059 * let detailX;
81060 * // slide to see how detailX works
81061 * function setup() {
81062 * createCanvas(100, 100, WEBGL);
81063 * detailX = createSlider(3, 24, 3);
81064 * detailX.position(10, height + 5);
81065 * detailX.style('width', '80px');
81066 * }
81067 *
81068 * function draw() {
81069 * background(205, 105, 94);
81070 * rotateY(millis() / 1000);
81071 * sphere(40, detailX.value(), 16);
81072 * }
81073 * </code>
81074 * </div>
81075 *
81076 * @example
81077 * <div>
81078 * <code>
81079 * let detailY;
81080 * // slide to see how detailY works
81081 * function setup() {
81082 * createCanvas(100, 100, WEBGL);
81083 * detailY = createSlider(3, 16, 3);
81084 * detailY.position(10, height + 5);
81085 * detailY.style('width', '80px');
81086 * }
81087 *
81088 * function draw() {
81089 * background(205, 105, 94);
81090 * rotateY(millis() / 1000);
81091 * sphere(40, 16, detailY.value());
81092 * }
81093 * </code>
81094 * </div>
81095 */
81096 _main.default.prototype.sphere = function(radius, detailX, detailY) {
81097 this._assert3d('sphere');
81098 _main.default._validateParameters('sphere', arguments);
81099 if (typeof radius === 'undefined') {
81100 radius = 50;
81101 }
81102 if (typeof detailX === 'undefined') {
81103 detailX = 24;
81104 }
81105 if (typeof detailY === 'undefined') {
81106 detailY = 16;
81107 }
81108
81109 this.ellipsoid(radius, radius, radius, detailX, detailY);
81110
81111 return this;
81112 };
81113
81114 /**
81115 * @private
81116 * Helper function for creating both cones and cylinders
81117 * Will only generate well-defined geometry when bottomRadius, height > 0
81118 * and topRadius >= 0
81119 * If topRadius == 0, topCap should be false
81120 */
81121 var _truncatedCone = function _truncatedCone(
81122 bottomRadius,
81123 topRadius,
81124 height,
81125 detailX,
81126 detailY,
81127 bottomCap,
81128 topCap
81129 ) {
81130 bottomRadius = bottomRadius <= 0 ? 1 : bottomRadius;
81131 topRadius = topRadius < 0 ? 0 : topRadius;
81132 height = height <= 0 ? bottomRadius : height;
81133 detailX = detailX < 3 ? 3 : detailX;
81134 detailY = detailY < 1 ? 1 : detailY;
81135 bottomCap = bottomCap === undefined ? true : bottomCap;
81136 topCap = topCap === undefined ? topRadius !== 0 : topCap;
81137 var start = bottomCap ? -2 : 0;
81138 var end = detailY + (topCap ? 2 : 0);
81139 //ensure constant slant for interior vertex normals
81140 var slant = Math.atan2(bottomRadius - topRadius, height);
81141 var sinSlant = Math.sin(slant);
81142 var cosSlant = Math.cos(slant);
81143 var yy, ii, jj;
81144 for (yy = start; yy <= end; ++yy) {
81145 var v = yy / detailY;
81146 var y = height * v;
81147 var ringRadius = void 0;
81148 if (yy < 0) {
81149 //for the bottomCap edge
81150 y = 0;
81151 v = 0;
81152 ringRadius = bottomRadius;
81153 } else if (yy > detailY) {
81154 //for the topCap edge
81155 y = height;
81156 v = 1;
81157 ringRadius = topRadius;
81158 } else {
81159 //for the middle
81160 ringRadius = bottomRadius + (topRadius - bottomRadius) * v;
81161 }
81162 if (yy === -2 || yy === detailY + 2) {
81163 //center of bottom or top caps
81164 ringRadius = 0;
81165 }
81166
81167 y -= height / 2; //shift coordiate origin to the center of object
81168 for (ii = 0; ii < detailX; ++ii) {
81169 var u = ii / (detailX - 1);
81170 var ur = 2 * Math.PI * u;
81171 var sur = Math.sin(ur);
81172 var cur = Math.cos(ur);
81173
81174 //VERTICES
81175 this.vertices.push(
81176 new _main.default.Vector(sur * ringRadius, y, cur * ringRadius)
81177 );
81178
81179 //VERTEX NORMALS
81180 var vertexNormal = void 0;
81181 if (yy < 0) {
81182 vertexNormal = new _main.default.Vector(0, -1, 0);
81183 } else if (yy > detailY && topRadius) {
81184 vertexNormal = new _main.default.Vector(0, 1, 0);
81185 } else {
81186 vertexNormal = new _main.default.Vector(
81187 sur * cosSlant,
81188 sinSlant,
81189 cur * cosSlant
81190 );
81191 }
81192 this.vertexNormals.push(vertexNormal);
81193 //UVs
81194 this.uvs.push(u, v);
81195 }
81196 }
81197
81198 var startIndex = 0;
81199 if (bottomCap) {
81200 for (jj = 0; jj < detailX; ++jj) {
81201 var nextjj = (jj + 1) % detailX;
81202 this.faces.push([
81203 startIndex + jj,
81204 startIndex + detailX + nextjj,
81205 startIndex + detailX + jj
81206 ]);
81207 }
81208 startIndex += detailX * 2;
81209 }
81210 for (yy = 0; yy < detailY; ++yy) {
81211 for (ii = 0; ii < detailX; ++ii) {
81212 var nextii = (ii + 1) % detailX;
81213 this.faces.push([
81214 startIndex + ii,
81215 startIndex + nextii,
81216 startIndex + detailX + nextii
81217 ]);
81218
81219 this.faces.push([
81220 startIndex + ii,
81221 startIndex + detailX + nextii,
81222 startIndex + detailX + ii
81223 ]);
81224 }
81225 startIndex += detailX;
81226 }
81227 if (topCap) {
81228 startIndex += detailX;
81229 for (ii = 0; ii < detailX; ++ii) {
81230 this.faces.push([
81231 startIndex + ii,
81232 startIndex + (ii + 1) % detailX,
81233 startIndex + detailX
81234 ]);
81235 }
81236 }
81237 };
81238
81239 /**
81240 * Draw a cylinder with given radius and height
81241 *
81242 * DetailX and detailY determines the number of subdivisions in the x-dimension
81243 * and the y-dimension of a cylinder. More subdivisions make the cylinder seem smoother.
81244 * The recommended maximum value for detailX is 24. Using a value greater than 24
81245 * may cause a warning or slow down the browser.
81246 *
81247 * @method cylinder
81248 * @param {Number} [radius] radius of the surface
81249 * @param {Number} [height] height of the cylinder
81250 * @param {Integer} [detailX] number of subdivisions in x-dimension;
81251 * default is 24
81252 * @param {Integer} [detailY] number of subdivisions in y-dimension;
81253 * default is 1
81254 * @param {Boolean} [bottomCap] whether to draw the bottom of the cylinder
81255 * @param {Boolean} [topCap] whether to draw the top of the cylinder
81256 * @chainable
81257 * @example
81258 * <div>
81259 * <code>
81260 * // draw a spinning cylinder
81261 * // with radius 20 and height 50
81262 * function setup() {
81263 * createCanvas(100, 100, WEBGL);
81264 * }
81265 *
81266 * function draw() {
81267 * background(205, 105, 94);
81268 * rotateX(frameCount * 0.01);
81269 * rotateZ(frameCount * 0.01);
81270 * cylinder(20, 50);
81271 * }
81272 * </code>
81273 * </div>
81274 *
81275 * @example
81276 * <div>
81277 * <code>
81278 * // slide to see how detailX works
81279 * let detailX;
81280 * function setup() {
81281 * createCanvas(100, 100, WEBGL);
81282 * detailX = createSlider(3, 24, 3);
81283 * detailX.position(10, height + 5);
81284 * detailX.style('width', '80px');
81285 * }
81286 *
81287 * function draw() {
81288 * background(205, 105, 94);
81289 * rotateY(millis() / 1000);
81290 * cylinder(20, 75, detailX.value(), 1);
81291 * }
81292 * </code>
81293 * </div>
81294 *
81295 * @example
81296 * <div>
81297 * <code>
81298 * // slide to see how detailY works
81299 * let detailY;
81300 * function setup() {
81301 * createCanvas(100, 100, WEBGL);
81302 * detailY = createSlider(1, 16, 1);
81303 * detailY.position(10, height + 5);
81304 * detailY.style('width', '80px');
81305 * }
81306 *
81307 * function draw() {
81308 * background(205, 105, 94);
81309 * rotateY(millis() / 1000);
81310 * cylinder(20, 75, 16, detailY.value());
81311 * }
81312 * </code>
81313 * </div>
81314 */
81315 _main.default.prototype.cylinder = function(
81316 radius,
81317 height,
81318 detailX,
81319 detailY,
81320 bottomCap,
81321 topCap
81322 ) {
81323 this._assert3d('cylinder');
81324 _main.default._validateParameters('cylinder', arguments);
81325 if (typeof radius === 'undefined') {
81326 radius = 50;
81327 }
81328 if (typeof height === 'undefined') {
81329 height = radius;
81330 }
81331 if (typeof detailX === 'undefined') {
81332 detailX = 24;
81333 }
81334 if (typeof detailY === 'undefined') {
81335 detailY = 1;
81336 }
81337 if (typeof topCap === 'undefined') {
81338 topCap = true;
81339 }
81340 if (typeof bottomCap === 'undefined') {
81341 bottomCap = true;
81342 }
81343
81344 var gId = 'cylinder|'
81345 .concat(detailX, '|')
81346 .concat(detailY, '|')
81347 .concat(bottomCap, '|')
81348 .concat(topCap);
81349 if (!this._renderer.geometryInHash(gId)) {
81350 var cylinderGeom = new _main.default.Geometry(detailX, detailY);
81351 _truncatedCone.call(
81352 cylinderGeom,
81353 1,
81354 1,
81355 1,
81356 detailX,
81357 detailY,
81358 bottomCap,
81359 topCap
81360 );
81361
81362 // normals are computed in call to _truncatedCone
81363 if (detailX <= 24 && detailY <= 16) {
81364 cylinderGeom._makeTriangleEdges()._edgesToVertices();
81365 } else if (this._renderer._doStroke) {
81366 console.log(
81367 'Cannot draw stroke on cylinder objects with more' +
81368 ' than 24 detailX or 16 detailY'
81369 );
81370 }
81371 this._renderer.createBuffers(gId, cylinderGeom);
81372 }
81373
81374 this._renderer.drawBuffersScaled(gId, radius, height, radius);
81375
81376 return this;
81377 };
81378
81379 /**
81380 * Draw a cone with given radius and height
81381 *
81382 * DetailX and detailY determine the number of subdivisions in the x-dimension and
81383 * the y-dimension of a cone. More subdivisions make the cone seem smoother. The
81384 * recommended maximum value for detailX is 24. Using a value greater than 24
81385 * may cause a warning or slow down the browser.
81386 * @method cone
81387 * @param {Number} [radius] radius of the bottom surface
81388 * @param {Number} [height] height of the cone
81389 * @param {Integer} [detailX] number of segments,
81390 * the more segments the smoother geometry
81391 * default is 24
81392 * @param {Integer} [detailY] number of segments,
81393 * the more segments the smoother geometry
81394 * default is 1
81395 * @param {Boolean} [cap] whether to draw the base of the cone
81396 * @chainable
81397 * @example
81398 * <div>
81399 * <code>
81400 * // draw a spinning cone
81401 * // with radius 40 and height 70
81402 * function setup() {
81403 * createCanvas(100, 100, WEBGL);
81404 * }
81405 *
81406 * function draw() {
81407 * background(200);
81408 * rotateX(frameCount * 0.01);
81409 * rotateZ(frameCount * 0.01);
81410 * cone(40, 70);
81411 * }
81412 * </code>
81413 * </div>
81414 *
81415 * @example
81416 * <div>
81417 * <code>
81418 * // slide to see how detailx works
81419 * let detailX;
81420 * function setup() {
81421 * createCanvas(100, 100, WEBGL);
81422 * detailX = createSlider(3, 16, 3);
81423 * detailX.position(10, height + 5);
81424 * detailX.style('width', '80px');
81425 * }
81426 *
81427 * function draw() {
81428 * background(205, 102, 94);
81429 * rotateY(millis() / 1000);
81430 * cone(30, 65, detailX.value(), 16);
81431 * }
81432 * </code>
81433 * </div>
81434 *
81435 * @example
81436 * <div>
81437 * <code>
81438 * // slide to see how detailY works
81439 * let detailY;
81440 * function setup() {
81441 * createCanvas(100, 100, WEBGL);
81442 * detailY = createSlider(3, 16, 3);
81443 * detailY.position(10, height + 5);
81444 * detailY.style('width', '80px');
81445 * }
81446 *
81447 * function draw() {
81448 * background(205, 102, 94);
81449 * rotateY(millis() / 1000);
81450 * cone(30, 65, 16, detailY.value());
81451 * }
81452 * </code>
81453 * </div>
81454 */
81455 _main.default.prototype.cone = function(radius, height, detailX, detailY, cap) {
81456 this._assert3d('cone');
81457 _main.default._validateParameters('cone', arguments);
81458 if (typeof radius === 'undefined') {
81459 radius = 50;
81460 }
81461 if (typeof height === 'undefined') {
81462 height = radius;
81463 }
81464 if (typeof detailX === 'undefined') {
81465 detailX = 24;
81466 }
81467 if (typeof detailY === 'undefined') {
81468 detailY = 1;
81469 }
81470 if (typeof cap === 'undefined') {
81471 cap = true;
81472 }
81473
81474 var gId = 'cone|'
81475 .concat(detailX, '|')
81476 .concat(detailY, '|')
81477 .concat(cap);
81478 if (!this._renderer.geometryInHash(gId)) {
81479 var coneGeom = new _main.default.Geometry(detailX, detailY);
81480 _truncatedCone.call(coneGeom, 1, 0, 1, detailX, detailY, cap, false);
81481 if (detailX <= 24 && detailY <= 16) {
81482 coneGeom._makeTriangleEdges()._edgesToVertices();
81483 } else if (this._renderer._doStroke) {
81484 console.log(
81485 'Cannot draw stroke on cone objects with more' +
81486 ' than 24 detailX or 16 detailY'
81487 );
81488 }
81489 this._renderer.createBuffers(gId, coneGeom);
81490 }
81491
81492 this._renderer.drawBuffersScaled(gId, radius, height, radius);
81493
81494 return this;
81495 };
81496
81497 /**
81498 * Draw an ellipsoid with given radius
81499 *
81500 * DetailX and detailY determine the number of subdivisions in the x-dimension and
81501 * the y-dimension of a cone. More subdivisions make the ellipsoid appear to be smoother.
81502 * Avoid detail number above 150, it may crash the browser.
81503 * @method ellipsoid
81504 * @param {Number} [radiusx] x-radius of ellipsoid
81505 * @param {Number} [radiusy] y-radius of ellipsoid
81506 * @param {Number} [radiusz] z-radius of ellipsoid
81507 * @param {Integer} [detailX] number of segments,
81508 * the more segments the smoother geometry
81509 * default is 24. Avoid detail number above
81510 * 150, it may crash the browser.
81511 * @param {Integer} [detailY] number of segments,
81512 * the more segments the smoother geometry
81513 * default is 16. Avoid detail number above
81514 * 150, it may crash the browser.
81515 * @chainable
81516 * @example
81517 * <div>
81518 * <code>
81519 * // draw an ellipsoid
81520 * // with radius 30, 40 and 40.
81521 * function setup() {
81522 * createCanvas(100, 100, WEBGL);
81523 * }
81524 *
81525 * function draw() {
81526 * background(205, 105, 94);
81527 * ellipsoid(30, 40, 40);
81528 * }
81529 * </code>
81530 * </div>
81531 *
81532 * @example
81533 * <div>
81534 * <code>
81535 * // slide to see how detailX works
81536 * let detailX;
81537 * function setup() {
81538 * createCanvas(100, 100, WEBGL);
81539 * detailX = createSlider(2, 24, 12);
81540 * detailX.position(10, height + 5);
81541 * detailX.style('width', '80px');
81542 * }
81543 *
81544 * function draw() {
81545 * background(205, 105, 94);
81546 * rotateY(millis() / 1000);
81547 * ellipsoid(30, 40, 40, detailX.value(), 8);
81548 * }
81549 * </code>
81550 * </div>
81551 *
81552 * @example
81553 * <div>
81554 * <code>
81555 * // slide to see how detailY works
81556 * let detailY;
81557 * function setup() {
81558 * createCanvas(100, 100, WEBGL);
81559 * detailY = createSlider(2, 24, 6);
81560 * detailY.position(10, height + 5);
81561 * detailY.style('width', '80px');
81562 * }
81563 *
81564 * function draw() {
81565 * background(205, 105, 9);
81566 * rotateY(millis() / 1000);
81567 * ellipsoid(30, 40, 40, 12, detailY.value());
81568 * }
81569 * </code>
81570 * </div>
81571 */
81572 _main.default.prototype.ellipsoid = function(
81573 radiusX,
81574 radiusY,
81575 radiusZ,
81576 detailX,
81577 detailY
81578 ) {
81579 this._assert3d('ellipsoid');
81580 _main.default._validateParameters('ellipsoid', arguments);
81581 if (typeof radiusX === 'undefined') {
81582 radiusX = 50;
81583 }
81584 if (typeof radiusY === 'undefined') {
81585 radiusY = radiusX;
81586 }
81587 if (typeof radiusZ === 'undefined') {
81588 radiusZ = radiusX;
81589 }
81590
81591 if (typeof detailX === 'undefined') {
81592 detailX = 24;
81593 }
81594 if (typeof detailY === 'undefined') {
81595 detailY = 16;
81596 }
81597
81598 var gId = 'ellipsoid|'.concat(detailX, '|').concat(detailY);
81599
81600 if (!this._renderer.geometryInHash(gId)) {
81601 var _ellipsoid = function _ellipsoid() {
81602 for (var i = 0; i <= this.detailY; i++) {
81603 var v = i / this.detailY;
81604 var phi = Math.PI * v - Math.PI / 2;
81605 var cosPhi = Math.cos(phi);
81606 var sinPhi = Math.sin(phi);
81607
81608 for (var j = 0; j <= this.detailX; j++) {
81609 var u = j / this.detailX;
81610 var theta = 2 * Math.PI * u;
81611 var cosTheta = Math.cos(theta);
81612 var sinTheta = Math.sin(theta);
81613 var p = new _main.default.Vector(
81614 cosPhi * sinTheta,
81615 sinPhi,
81616 cosPhi * cosTheta
81617 );
81618 this.vertices.push(p);
81619 this.vertexNormals.push(p);
81620 this.uvs.push(u, v);
81621 }
81622 }
81623 };
81624 var ellipsoidGeom = new _main.default.Geometry(detailX, detailY, _ellipsoid);
81625 ellipsoidGeom.computeFaces();
81626 if (detailX <= 24 && detailY <= 24) {
81627 ellipsoidGeom._makeTriangleEdges()._edgesToVertices();
81628 } else if (this._renderer._doStroke) {
81629 console.log(
81630 'Cannot draw stroke on ellipsoids with more' +
81631 ' than 24 detailX or 24 detailY'
81632 );
81633 }
81634 this._renderer.createBuffers(gId, ellipsoidGeom);
81635 }
81636
81637 this._renderer.drawBuffersScaled(gId, radiusX, radiusY, radiusZ);
81638
81639 return this;
81640 };
81641
81642 /**
81643 * Draw a torus with given radius and tube radius
81644 *
81645 * DetailX and detailY determine the number of subdivisions in the x-dimension and
81646 * the y-dimension of a torus. More subdivisions make the torus appear to be smoother.
81647 * The default and maximum values for detailX and detailY are 24 and 16, respectively.
81648 * Setting them to relatively small values like 4 and 6 allows you to create new
81649 * shapes other than a torus.
81650 * @method torus
81651 * @param {Number} [radius] radius of the whole ring
81652 * @param {Number} [tubeRadius] radius of the tube
81653 * @param {Integer} [detailX] number of segments in x-dimension,
81654 * the more segments the smoother geometry
81655 * default is 24
81656 * @param {Integer} [detailY] number of segments in y-dimension,
81657 * the more segments the smoother geometry
81658 * default is 16
81659 * @chainable
81660 * @example
81661 * <div>
81662 * <code>
81663 * // draw a spinning torus
81664 * // with ring radius 30 and tube radius 15
81665 * function setup() {
81666 * createCanvas(100, 100, WEBGL);
81667 * }
81668 *
81669 * function draw() {
81670 * background(205, 102, 94);
81671 * rotateX(frameCount * 0.01);
81672 * rotateY(frameCount * 0.01);
81673 * torus(30, 15);
81674 * }
81675 * </code>
81676 * </div>
81677 *
81678 * @example
81679 * <div>
81680 * <code>
81681 * // slide to see how detailX works
81682 * let detailX;
81683 * function setup() {
81684 * createCanvas(100, 100, WEBGL);
81685 * detailX = createSlider(3, 24, 3);
81686 * detailX.position(10, height + 5);
81687 * detailX.style('width', '80px');
81688 * }
81689 *
81690 * function draw() {
81691 * background(205, 102, 94);
81692 * rotateY(millis() / 1000);
81693 * torus(30, 15, detailX.value(), 12);
81694 * }
81695 * </code>
81696 * </div>
81697 *
81698 * @example
81699 * <div>
81700 * <code>
81701 * // slide to see how detailY works
81702 * let detailY;
81703 * function setup() {
81704 * createCanvas(100, 100, WEBGL);
81705 * detailY = createSlider(3, 16, 3);
81706 * detailY.position(10, height + 5);
81707 * detailY.style('width', '80px');
81708 * }
81709 *
81710 * function draw() {
81711 * background(205, 102, 94);
81712 * rotateY(millis() / 1000);
81713 * torus(30, 15, 16, detailY.value());
81714 * }
81715 * </code>
81716 * </div>
81717 */
81718 _main.default.prototype.torus = function(radius, tubeRadius, detailX, detailY) {
81719 this._assert3d('torus');
81720 _main.default._validateParameters('torus', arguments);
81721 if (typeof radius === 'undefined') {
81722 radius = 50;
81723 } else if (!radius) {
81724 return; // nothing to draw
81725 }
81726
81727 if (typeof tubeRadius === 'undefined') {
81728 tubeRadius = 10;
81729 } else if (!tubeRadius) {
81730 return; // nothing to draw
81731 }
81732
81733 if (typeof detailX === 'undefined') {
81734 detailX = 24;
81735 }
81736 if (typeof detailY === 'undefined') {
81737 detailY = 16;
81738 }
81739
81740 var tubeRatio = (tubeRadius / radius).toPrecision(4);
81741 var gId = 'torus|'
81742 .concat(tubeRatio, '|')
81743 .concat(detailX, '|')
81744 .concat(detailY);
81745
81746 if (!this._renderer.geometryInHash(gId)) {
81747 var _torus = function _torus() {
81748 for (var i = 0; i <= this.detailY; i++) {
81749 var v = i / this.detailY;
81750 var phi = 2 * Math.PI * v;
81751 var cosPhi = Math.cos(phi);
81752 var sinPhi = Math.sin(phi);
81753 var r = 1 + tubeRatio * cosPhi;
81754
81755 for (var j = 0; j <= this.detailX; j++) {
81756 var u = j / this.detailX;
81757 var theta = 2 * Math.PI * u;
81758 var cosTheta = Math.cos(theta);
81759 var sinTheta = Math.sin(theta);
81760
81761 var p = new _main.default.Vector(
81762 r * cosTheta,
81763 r * sinTheta,
81764 tubeRatio * sinPhi
81765 );
81766
81767 var n = new _main.default.Vector(
81768 cosPhi * cosTheta,
81769 cosPhi * sinTheta,
81770 sinPhi
81771 );
81772
81773 this.vertices.push(p);
81774 this.vertexNormals.push(n);
81775 this.uvs.push(u, v);
81776 }
81777 }
81778 };
81779 var torusGeom = new _main.default.Geometry(detailX, detailY, _torus);
81780 torusGeom.computeFaces();
81781 if (detailX <= 24 && detailY <= 16) {
81782 torusGeom._makeTriangleEdges()._edgesToVertices();
81783 } else if (this._renderer._doStroke) {
81784 console.log(
81785 'Cannot draw strokes on torus object with more' +
81786 ' than 24 detailX or 16 detailY'
81787 );
81788 }
81789 this._renderer.createBuffers(gId, torusGeom);
81790 }
81791 this._renderer.drawBuffersScaled(gId, radius, radius, radius);
81792
81793 return this;
81794 };
81795
81796 ///////////////////////
81797 /// 2D primitives
81798 /////////////////////////
81799
81800 /**
81801 * Draws a point, a coordinate in space at the dimension of one pixel,
81802 * given x, y and z coordinates. The color of the point is determined
81803 * by the current stroke, while the point size is determined by current
81804 * stroke weight.
81805 * @private
81806 * @param {Number} x x-coordinate of point
81807 * @param {Number} y y-coordinate of point
81808 * @param {Number} z z-coordinate of point
81809 * @chainable
81810 * @example
81811 * <div>
81812 * <code>
81813 * function setup() {
81814 * createCanvas(100, 100, WEBGL);
81815 * }
81816 *
81817 * function draw() {
81818 * background(50);
81819 * stroke(255);
81820 * strokeWeight(4);
81821 * point(25, 0);
81822 * strokeWeight(3);
81823 * point(-25, 0);
81824 * strokeWeight(2);
81825 * point(0, 25);
81826 * strokeWeight(1);
81827 * point(0, -25);
81828 * }
81829 * </code>
81830 * </div>
81831 */
81832 _main.default.RendererGL.prototype.point = function(x, y, z) {
81833 if (typeof z === 'undefined') {
81834 z = 0;
81835 }
81836
81837 var _vertex = [];
81838 _vertex.push(new _main.default.Vector(x, y, z));
81839 this._drawPoints(_vertex, this.immediateMode.buffers.point);
81840
81841 return this;
81842 };
81843
81844 _main.default.RendererGL.prototype.triangle = function(args) {
81845 var x1 = args[0],
81846 y1 = args[1];
81847 var x2 = args[2],
81848 y2 = args[3];
81849 var x3 = args[4],
81850 y3 = args[5];
81851
81852 var gId = 'tri';
81853 if (!this.geometryInHash(gId)) {
81854 var _triangle = function _triangle() {
81855 var vertices = [];
81856 vertices.push(new _main.default.Vector(0, 0, 0));
81857 vertices.push(new _main.default.Vector(0, 1, 0));
81858 vertices.push(new _main.default.Vector(1, 0, 0));
81859 this.strokeIndices = [[0, 1], [1, 2], [2, 0]];
81860 this.vertices = vertices;
81861 this.faces = [[0, 1, 2]];
81862 this.uvs = [0, 0, 0, 1, 1, 1];
81863 };
81864 var triGeom = new _main.default.Geometry(1, 1, _triangle);
81865 triGeom._makeTriangleEdges()._edgesToVertices();
81866 triGeom.computeNormals();
81867 this.createBuffers(gId, triGeom);
81868 }
81869
81870 // only one triangle is cached, one point is at the origin, and the
81871 // two adjacent sides are tne unit vectors along the X & Y axes.
81872 //
81873 // this matrix multiplication transforms those two unit vectors
81874 // onto the required vector prior to rendering, and moves the
81875 // origin appropriately.
81876 var uMVMatrix = this.uMVMatrix.copy();
81877 try {
81878 // prettier-ignore
81879 var mult = new _main.default.Matrix([
81880 x2 - x1, y2 - y1, 0, 0, // the resulting unit X-axis
81881 x3 - x1, y3 - y1, 0, 0, // the resulting unit Y-axis
81882 0, 0, 1, 0, // the resulting unit Z-axis (unchanged)
81883 x1, y1, 0, 1 // the resulting origin
81884 ]).mult(this.uMVMatrix);
81885
81886 this.uMVMatrix = mult;
81887
81888 this.drawBuffers(gId);
81889 } finally {
81890 this.uMVMatrix = uMVMatrix;
81891 }
81892
81893 return this;
81894 };
81895
81896 _main.default.RendererGL.prototype.ellipse = function(args) {
81897 this.arc(
81898 args[0],
81899 args[1],
81900 args[2],
81901 args[3],
81902 0,
81903 constants.TWO_PI,
81904 constants.OPEN,
81905 args[4]
81906 );
81907 };
81908
81909 _main.default.RendererGL.prototype.arc = function(args) {
81910 var x = arguments[0];
81911 var y = arguments[1];
81912 var width = arguments[2];
81913 var height = arguments[3];
81914 var start = arguments[4];
81915 var stop = arguments[5];
81916 var mode = arguments[6];
81917 var detail = arguments[7] || 25;
81918
81919 var shape;
81920 var gId;
81921
81922 // check if it is an ellipse or an arc
81923 if (Math.abs(stop - start) >= constants.TWO_PI) {
81924 shape = 'ellipse';
81925 gId = ''.concat(shape, '|').concat(detail, '|');
81926 } else {
81927 shape = 'arc';
81928 gId = ''
81929 .concat(shape, '|')
81930 .concat(start, '|')
81931 .concat(stop, '|')
81932 .concat(mode, '|')
81933 .concat(detail, '|');
81934 }
81935
81936 if (!this.geometryInHash(gId)) {
81937 var _arc = function _arc() {
81938 this.strokeIndices = [];
81939
81940 // if the start and stop angles are not the same, push vertices to the array
81941 if (start.toFixed(10) !== stop.toFixed(10)) {
81942 // if the mode specified is PIE or null, push the mid point of the arc in vertices
81943 if (mode === constants.PIE || typeof mode === 'undefined') {
81944 this.vertices.push(new _main.default.Vector(0.5, 0.5, 0));
81945 this.uvs.push([0.5, 0.5]);
81946 }
81947
81948 // vertices for the perimeter of the circle
81949 for (var i = 0; i <= detail; i++) {
81950 var u = i / detail;
81951 var theta = (stop - start) * u + start;
81952
81953 var _x = 0.5 + Math.cos(theta) / 2;
81954 var _y = 0.5 + Math.sin(theta) / 2;
81955
81956 this.vertices.push(new _main.default.Vector(_x, _y, 0));
81957 this.uvs.push([_x, _y]);
81958
81959 if (i < detail - 1) {
81960 this.faces.push([0, i + 1, i + 2]);
81961 this.strokeIndices.push([i + 1, i + 2]);
81962 }
81963 }
81964
81965 // check the mode specified in order to push vertices and faces, different for each mode
81966 switch (mode) {
81967 case constants.PIE:
81968 this.faces.push([
81969 0,
81970 this.vertices.length - 2,
81971 this.vertices.length - 1
81972 ]);
81973
81974 this.strokeIndices.push([0, 1]);
81975 this.strokeIndices.push([
81976 this.vertices.length - 2,
81977 this.vertices.length - 1
81978 ]);
81979
81980 this.strokeIndices.push([0, this.vertices.length - 1]);
81981 break;
81982
81983 case constants.CHORD:
81984 this.strokeIndices.push([0, 1]);
81985 this.strokeIndices.push([0, this.vertices.length - 1]);
81986 break;
81987
81988 case constants.OPEN:
81989 this.strokeIndices.push([0, 1]);
81990 break;
81991
81992 default:
81993 this.faces.push([
81994 0,
81995 this.vertices.length - 2,
81996 this.vertices.length - 1
81997 ]);
81998
81999 this.strokeIndices.push([
82000 this.vertices.length - 2,
82001 this.vertices.length - 1
82002 ]);
82003 }
82004 }
82005 };
82006
82007 var arcGeom = new _main.default.Geometry(detail, 1, _arc);
82008 arcGeom.computeNormals();
82009
82010 if (detail <= 50) {
82011 arcGeom._makeTriangleEdges()._edgesToVertices(arcGeom);
82012 } else if (this._renderer._doStroke) {
82013 console.log('Cannot stroke ${shape} with more than 50 detail');
82014 }
82015
82016 this.createBuffers(gId, arcGeom);
82017 }
82018
82019 var uMVMatrix = this.uMVMatrix.copy();
82020
82021 try {
82022 this.uMVMatrix.translate([x, y, 0]);
82023 this.uMVMatrix.scale(width, height, 1);
82024
82025 this.drawBuffers(gId);
82026 } finally {
82027 this.uMVMatrix = uMVMatrix;
82028 }
82029
82030 return this;
82031 };
82032
82033 _main.default.RendererGL.prototype.rect = function(args) {
82034 var perPixelLighting = this._pInst._glAttributes.perPixelLighting;
82035 var x = args[0];
82036 var y = args[1];
82037 var width = args[2];
82038 var height = args[3];
82039 var detailX = args[4] || (perPixelLighting ? 1 : 24);
82040 var detailY = args[5] || (perPixelLighting ? 1 : 16);
82041 var gId = 'rect|'.concat(detailX, '|').concat(detailY);
82042 if (!this.geometryInHash(gId)) {
82043 var _rect = function _rect() {
82044 for (var i = 0; i <= this.detailY; i++) {
82045 var v = i / this.detailY;
82046 for (var j = 0; j <= this.detailX; j++) {
82047 var u = j / this.detailX;
82048 var p = new _main.default.Vector(u, v, 0);
82049 this.vertices.push(p);
82050 this.uvs.push(u, v);
82051 }
82052 }
82053 // using stroke indices to avoid stroke over face(s) of rectangle
82054 if (detailX > 0 && detailY > 0) {
82055 this.strokeIndices = [
82056 [0, detailX],
82057 [detailX, (detailX + 1) * (detailY + 1) - 1],
82058 [(detailX + 1) * (detailY + 1) - 1, (detailX + 1) * detailY],
82059 [(detailX + 1) * detailY, 0]
82060 ];
82061 }
82062 };
82063 var rectGeom = new _main.default.Geometry(detailX, detailY, _rect);
82064 rectGeom
82065 .computeFaces()
82066 .computeNormals()
82067 ._makeTriangleEdges()
82068 ._edgesToVertices();
82069 this.createBuffers(gId, rectGeom);
82070 }
82071
82072 // only a single rectangle (of a given detail) is cached: a square with
82073 // opposite corners at (0,0) & (1,1).
82074 //
82075 // before rendering, this square is scaled & moved to the required location.
82076 var uMVMatrix = this.uMVMatrix.copy();
82077 try {
82078 this.uMVMatrix.translate([x, y, 0]);
82079 this.uMVMatrix.scale(width, height, 1);
82080
82081 this.drawBuffers(gId);
82082 } finally {
82083 this.uMVMatrix = uMVMatrix;
82084 }
82085 return this;
82086 };
82087
82088 // prettier-ignore
82089 _main.default.RendererGL.prototype.quad = function (x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4) {
82090 var gId = "quad|".concat(
82091 x1, "|").concat(y1, "|").concat(z1, "|").concat(x2, "|").concat(y2, "|").concat(z2, "|").concat(x3, "|").concat(y3, "|").concat(z3, "|").concat(x4, "|").concat(y4, "|").concat(z4);
82092 if (!this.geometryInHash(gId)) {
82093 var _quad = function _quad() {
82094 this.vertices.push(new _main.default.Vector(x1, y1, z1));
82095 this.vertices.push(new _main.default.Vector(x2, y2, z2));
82096 this.vertices.push(new _main.default.Vector(x3, y3, z3));
82097 this.vertices.push(new _main.default.Vector(x4, y4, z4));
82098 this.uvs.push(0, 0, 1, 0, 1, 1, 0, 1);
82099 this.strokeIndices = [[0, 1], [1, 2], [2, 3], [3, 0]];
82100 };
82101 var quadGeom = new _main.default.Geometry(2, 2, _quad);
82102 quadGeom.
82103 computeNormals().
82104 _makeTriangleEdges().
82105 _edgesToVertices();
82106 quadGeom.faces = [[0, 1, 2], [2, 3, 0]];
82107 this.createBuffers(gId, quadGeom);
82108 }
82109 this.drawBuffers(gId);
82110 return this;
82111};
82112
82113 //this implementation of bezier curve
82114 //is based on Bernstein polynomial
82115 // pretier-ignore
82116 _main.default.RendererGL.prototype.bezier = function(
82117 x1,
82118 y1,
82119 z1, // x2
82120 x2, // y2
82121 y2, // x3
82122 z2, // y3
82123 x3, // x4
82124 y3, // y4
82125 z3,
82126 x4,
82127 y4,
82128 z4
82129 ) {
82130 if (arguments.length === 8) {
82131 y4 = y3;
82132 x4 = x3;
82133 y3 = z2;
82134 x3 = y2;
82135 y2 = x2;
82136 x2 = z1;
82137 z1 = z2 = z3 = z4 = 0;
82138 }
82139 var bezierDetail = this._pInst._bezierDetail || 20; //value of Bezier detail
82140 this.beginShape();
82141 for (var i = 0; i <= bezierDetail; i++) {
82142 var c1 = Math.pow(1 - i / bezierDetail, 3);
82143 var c2 = 3 * (i / bezierDetail) * Math.pow(1 - i / bezierDetail, 2);
82144 var c3 = 3 * Math.pow(i / bezierDetail, 2) * (1 - i / bezierDetail);
82145 var c4 = Math.pow(i / bezierDetail, 3);
82146 this.vertex(
82147 x1 * c1 + x2 * c2 + x3 * c3 + x4 * c4,
82148 y1 * c1 + y2 * c2 + y3 * c3 + y4 * c4,
82149 z1 * c1 + z2 * c2 + z3 * c3 + z4 * c4
82150 );
82151 }
82152 this.endShape();
82153 return this;
82154 };
82155
82156 // pretier-ignore
82157 _main.default.RendererGL.prototype.curve = function(
82158 x1,
82159 y1,
82160 z1, // x2
82161 x2, // y2
82162 y2, // x3
82163 z2, // y3
82164 x3, // x4
82165 y3, // y4
82166 z3,
82167 x4,
82168 y4,
82169 z4
82170 ) {
82171 if (arguments.length === 8) {
82172 x4 = x3;
82173 y4 = y3;
82174 x3 = y2;
82175 y3 = x2;
82176 x2 = z1;
82177 y2 = x2;
82178 z1 = z2 = z3 = z4 = 0;
82179 }
82180 var curveDetail = this._pInst._curveDetail;
82181 this.beginShape();
82182 for (var i = 0; i <= curveDetail; i++) {
82183 var c1 = Math.pow(i / curveDetail, 3) * 0.5;
82184 var c2 = Math.pow(i / curveDetail, 2) * 0.5;
82185 var c3 = i / curveDetail * 0.5;
82186 var c4 = 0.5;
82187 var vx =
82188 c1 * (-x1 + 3 * x2 - 3 * x3 + x4) +
82189 c2 * (2 * x1 - 5 * x2 + 4 * x3 - x4) +
82190 c3 * (-x1 + x3) +
82191 c4 * (2 * x2);
82192 var vy =
82193 c1 * (-y1 + 3 * y2 - 3 * y3 + y4) +
82194 c2 * (2 * y1 - 5 * y2 + 4 * y3 - y4) +
82195 c3 * (-y1 + y3) +
82196 c4 * (2 * y2);
82197 var vz =
82198 c1 * (-z1 + 3 * z2 - 3 * z3 + z4) +
82199 c2 * (2 * z1 - 5 * z2 + 4 * z3 - z4) +
82200 c3 * (-z1 + z3) +
82201 c4 * (2 * z2);
82202 this.vertex(vx, vy, vz);
82203 }
82204 this.endShape();
82205 return this;
82206 };
82207
82208 /**
82209 * Draw a line given two points
82210 * @private
82211 * @param {Number} x0 x-coordinate of first vertex
82212 * @param {Number} y0 y-coordinate of first vertex
82213 * @param {Number} z0 z-coordinate of first vertex
82214 * @param {Number} x1 x-coordinate of second vertex
82215 * @param {Number} y1 y-coordinate of second vertex
82216 * @param {Number} z1 z-coordinate of second vertex
82217 * @chainable
82218 * @example
82219 * <div>
82220 * <code>
82221 * //draw a line
82222 * function setup() {
82223 * createCanvas(100, 100, WEBGL);
82224 * }
82225 *
82226 * function draw() {
82227 * background(200);
82228 * rotateX(frameCount * 0.01);
82229 * rotateY(frameCount * 0.01);
82230 * // Use fill instead of stroke to change the color of shape.
82231 * fill(255, 0, 0);
82232 * line(10, 10, 0, 60, 60, 20);
82233 * }
82234 * </code>
82235 * </div>
82236 */
82237 _main.default.RendererGL.prototype.line = function() {
82238 if (arguments.length === 6) {
82239 this.beginShape(constants.LINES);
82240 this.vertex(
82241 arguments.length <= 0 ? undefined : arguments[0],
82242 arguments.length <= 1 ? undefined : arguments[1],
82243 arguments.length <= 2 ? undefined : arguments[2]
82244 );
82245 this.vertex(
82246 arguments.length <= 3 ? undefined : arguments[3],
82247 arguments.length <= 4 ? undefined : arguments[4],
82248 arguments.length <= 5 ? undefined : arguments[5]
82249 );
82250 this.endShape();
82251 } else if (arguments.length === 4) {
82252 this.beginShape(constants.LINES);
82253 this.vertex(
82254 arguments.length <= 0 ? undefined : arguments[0],
82255 arguments.length <= 1 ? undefined : arguments[1],
82256 0
82257 );
82258 this.vertex(
82259 arguments.length <= 2 ? undefined : arguments[2],
82260 arguments.length <= 3 ? undefined : arguments[3],
82261 0
82262 );
82263 this.endShape();
82264 }
82265 return this;
82266 };
82267
82268 _main.default.RendererGL.prototype.bezierVertex = function() {
82269 if (this.immediateMode._bezierVertex.length === 0) {
82270 throw Error('vertex() must be used once before calling bezierVertex()');
82271 } else {
82272 var w_x = [];
82273 var w_y = [];
82274 var w_z = [];
82275 var t, _x, _y, _z, i;
82276 var argLength = arguments.length;
82277
82278 t = 0;
82279
82280 if (
82281 this._lookUpTableBezier.length === 0 ||
82282 this._lutBezierDetail !== this._pInst._curveDetail
82283 ) {
82284 this._lookUpTableBezier = [];
82285 this._lutBezierDetail = this._pInst._curveDetail;
82286 var step = 1 / this._lutBezierDetail;
82287 var start = 0;
82288 var end = 1;
82289 var j = 0;
82290 while (start < 1) {
82291 t = parseFloat(start.toFixed(6));
82292 this._lookUpTableBezier[j] = this._bezierCoefficients(t);
82293 if (end.toFixed(6) === step.toFixed(6)) {
82294 t = parseFloat(end.toFixed(6)) + parseFloat(start.toFixed(6));
82295 ++j;
82296 this._lookUpTableBezier[j] = this._bezierCoefficients(t);
82297 break;
82298 }
82299 start += step;
82300 end -= step;
82301 ++j;
82302 }
82303 }
82304
82305 var LUTLength = this._lookUpTableBezier.length;
82306
82307 if (argLength === 6) {
82308 this.isBezier = true;
82309
82310 w_x = [
82311 this.immediateMode._bezierVertex[0],
82312 arguments.length <= 0 ? undefined : arguments[0],
82313 arguments.length <= 2 ? undefined : arguments[2],
82314 arguments.length <= 4 ? undefined : arguments[4]
82315 ];
82316 w_y = [
82317 this.immediateMode._bezierVertex[1],
82318 arguments.length <= 1 ? undefined : arguments[1],
82319 arguments.length <= 3 ? undefined : arguments[3],
82320 arguments.length <= 5 ? undefined : arguments[5]
82321 ];
82322
82323 for (i = 0; i < LUTLength; i++) {
82324 _x =
82325 w_x[0] * this._lookUpTableBezier[i][0] +
82326 w_x[1] * this._lookUpTableBezier[i][1] +
82327 w_x[2] * this._lookUpTableBezier[i][2] +
82328 w_x[3] * this._lookUpTableBezier[i][3];
82329 _y =
82330 w_y[0] * this._lookUpTableBezier[i][0] +
82331 w_y[1] * this._lookUpTableBezier[i][1] +
82332 w_y[2] * this._lookUpTableBezier[i][2] +
82333 w_y[3] * this._lookUpTableBezier[i][3];
82334 this.vertex(_x, _y);
82335 }
82336 this.immediateMode._bezierVertex[0] =
82337 arguments.length <= 4 ? undefined : arguments[4];
82338 this.immediateMode._bezierVertex[1] =
82339 arguments.length <= 5 ? undefined : arguments[5];
82340 } else if (argLength === 9) {
82341 this.isBezier = true;
82342
82343 w_x = [
82344 this.immediateMode._bezierVertex[0],
82345 arguments.length <= 0 ? undefined : arguments[0],
82346 arguments.length <= 3 ? undefined : arguments[3],
82347 arguments.length <= 6 ? undefined : arguments[6]
82348 ];
82349 w_y = [
82350 this.immediateMode._bezierVertex[1],
82351 arguments.length <= 1 ? undefined : arguments[1],
82352 arguments.length <= 4 ? undefined : arguments[4],
82353 arguments.length <= 7 ? undefined : arguments[7]
82354 ];
82355 w_z = [
82356 this.immediateMode._bezierVertex[2],
82357 arguments.length <= 2 ? undefined : arguments[2],
82358 arguments.length <= 5 ? undefined : arguments[5],
82359 arguments.length <= 8 ? undefined : arguments[8]
82360 ];
82361 for (i = 0; i < LUTLength; i++) {
82362 _x =
82363 w_x[0] * this._lookUpTableBezier[i][0] +
82364 w_x[1] * this._lookUpTableBezier[i][1] +
82365 w_x[2] * this._lookUpTableBezier[i][2] +
82366 w_x[3] * this._lookUpTableBezier[i][3];
82367 _y =
82368 w_y[0] * this._lookUpTableBezier[i][0] +
82369 w_y[1] * this._lookUpTableBezier[i][1] +
82370 w_y[2] * this._lookUpTableBezier[i][2] +
82371 w_y[3] * this._lookUpTableBezier[i][3];
82372 _z =
82373 w_z[0] * this._lookUpTableBezier[i][0] +
82374 w_z[1] * this._lookUpTableBezier[i][1] +
82375 w_z[2] * this._lookUpTableBezier[i][2] +
82376 w_z[3] * this._lookUpTableBezier[i][3];
82377 this.vertex(_x, _y, _z);
82378 }
82379 this.immediateMode._bezierVertex[0] =
82380 arguments.length <= 6 ? undefined : arguments[6];
82381 this.immediateMode._bezierVertex[1] =
82382 arguments.length <= 7 ? undefined : arguments[7];
82383 this.immediateMode._bezierVertex[2] =
82384 arguments.length <= 8 ? undefined : arguments[8];
82385 }
82386 }
82387 };
82388
82389 _main.default.RendererGL.prototype.quadraticVertex = function() {
82390 if (this.immediateMode._quadraticVertex.length === 0) {
82391 throw Error('vertex() must be used once before calling quadraticVertex()');
82392 } else {
82393 var w_x = [];
82394 var w_y = [];
82395 var w_z = [];
82396 var t, _x, _y, _z, i;
82397 var argLength = arguments.length;
82398
82399 t = 0;
82400
82401 if (
82402 this._lookUpTableQuadratic.length === 0 ||
82403 this._lutQuadraticDetail !== this._pInst._curveDetail
82404 ) {
82405 this._lookUpTableQuadratic = [];
82406 this._lutQuadraticDetail = this._pInst._curveDetail;
82407 var step = 1 / this._lutQuadraticDetail;
82408 var start = 0;
82409 var end = 1;
82410 var j = 0;
82411 while (start < 1) {
82412 t = parseFloat(start.toFixed(6));
82413 this._lookUpTableQuadratic[j] = this._quadraticCoefficients(t);
82414 if (end.toFixed(6) === step.toFixed(6)) {
82415 t = parseFloat(end.toFixed(6)) + parseFloat(start.toFixed(6));
82416 ++j;
82417 this._lookUpTableQuadratic[j] = this._quadraticCoefficients(t);
82418 break;
82419 }
82420 start += step;
82421 end -= step;
82422 ++j;
82423 }
82424 }
82425
82426 var LUTLength = this._lookUpTableQuadratic.length;
82427
82428 if (argLength === 4) {
82429 this.isQuadratic = true;
82430
82431 w_x = [
82432 this.immediateMode._quadraticVertex[0],
82433 arguments.length <= 0 ? undefined : arguments[0],
82434 arguments.length <= 2 ? undefined : arguments[2]
82435 ];
82436 w_y = [
82437 this.immediateMode._quadraticVertex[1],
82438 arguments.length <= 1 ? undefined : arguments[1],
82439 arguments.length <= 3 ? undefined : arguments[3]
82440 ];
82441
82442 for (i = 0; i < LUTLength; i++) {
82443 _x =
82444 w_x[0] * this._lookUpTableQuadratic[i][0] +
82445 w_x[1] * this._lookUpTableQuadratic[i][1] +
82446 w_x[2] * this._lookUpTableQuadratic[i][2];
82447 _y =
82448 w_y[0] * this._lookUpTableQuadratic[i][0] +
82449 w_y[1] * this._lookUpTableQuadratic[i][1] +
82450 w_y[2] * this._lookUpTableQuadratic[i][2];
82451 this.vertex(_x, _y);
82452 }
82453
82454 this.immediateMode._quadraticVertex[0] =
82455 arguments.length <= 2 ? undefined : arguments[2];
82456 this.immediateMode._quadraticVertex[1] =
82457 arguments.length <= 3 ? undefined : arguments[3];
82458 } else if (argLength === 6) {
82459 this.isQuadratic = true;
82460
82461 w_x = [
82462 this.immediateMode._quadraticVertex[0],
82463 arguments.length <= 0 ? undefined : arguments[0],
82464 arguments.length <= 3 ? undefined : arguments[3]
82465 ];
82466 w_y = [
82467 this.immediateMode._quadraticVertex[1],
82468 arguments.length <= 1 ? undefined : arguments[1],
82469 arguments.length <= 4 ? undefined : arguments[4]
82470 ];
82471 w_z = [
82472 this.immediateMode._quadraticVertex[2],
82473 arguments.length <= 2 ? undefined : arguments[2],
82474 arguments.length <= 5 ? undefined : arguments[5]
82475 ];
82476
82477 for (i = 0; i < LUTLength; i++) {
82478 _x =
82479 w_x[0] * this._lookUpTableQuadratic[i][0] +
82480 w_x[1] * this._lookUpTableQuadratic[i][1] +
82481 w_x[2] * this._lookUpTableQuadratic[i][2];
82482 _y =
82483 w_y[0] * this._lookUpTableQuadratic[i][0] +
82484 w_y[1] * this._lookUpTableQuadratic[i][1] +
82485 w_y[2] * this._lookUpTableQuadratic[i][2];
82486 _z =
82487 w_z[0] * this._lookUpTableQuadratic[i][0] +
82488 w_z[1] * this._lookUpTableQuadratic[i][1] +
82489 w_z[2] * this._lookUpTableQuadratic[i][2];
82490 this.vertex(_x, _y, _z);
82491 }
82492
82493 this.immediateMode._quadraticVertex[0] =
82494 arguments.length <= 3 ? undefined : arguments[3];
82495 this.immediateMode._quadraticVertex[1] =
82496 arguments.length <= 4 ? undefined : arguments[4];
82497 this.immediateMode._quadraticVertex[2] =
82498 arguments.length <= 5 ? undefined : arguments[5];
82499 }
82500 }
82501 };
82502
82503 _main.default.RendererGL.prototype.curveVertex = function() {
82504 var w_x = [];
82505 var w_y = [];
82506 var w_z = [];
82507 var t, _x, _y, _z, i;
82508 t = 0;
82509 var argLength = arguments.length;
82510
82511 if (
82512 this._lookUpTableBezier.length === 0 ||
82513 this._lutBezierDetail !== this._pInst._curveDetail
82514 ) {
82515 this._lookUpTableBezier = [];
82516 this._lutBezierDetail = this._pInst._curveDetail;
82517 var step = 1 / this._lutBezierDetail;
82518 var start = 0;
82519 var end = 1;
82520 var j = 0;
82521 while (start < 1) {
82522 t = parseFloat(start.toFixed(6));
82523 this._lookUpTableBezier[j] = this._bezierCoefficients(t);
82524 if (end.toFixed(6) === step.toFixed(6)) {
82525 t = parseFloat(end.toFixed(6)) + parseFloat(start.toFixed(6));
82526 ++j;
82527 this._lookUpTableBezier[j] = this._bezierCoefficients(t);
82528 break;
82529 }
82530 start += step;
82531 end -= step;
82532 ++j;
82533 }
82534 }
82535
82536 var LUTLength = this._lookUpTableBezier.length;
82537
82538 if (argLength === 2) {
82539 this.immediateMode._curveVertex.push(
82540 arguments.length <= 0 ? undefined : arguments[0]
82541 );
82542 this.immediateMode._curveVertex.push(
82543 arguments.length <= 1 ? undefined : arguments[1]
82544 );
82545 if (this.immediateMode._curveVertex.length === 8) {
82546 this.isCurve = true;
82547 w_x = this._bezierToCatmull([
82548 this.immediateMode._curveVertex[0],
82549 this.immediateMode._curveVertex[2],
82550 this.immediateMode._curveVertex[4],
82551 this.immediateMode._curveVertex[6]
82552 ]);
82553
82554 w_y = this._bezierToCatmull([
82555 this.immediateMode._curveVertex[1],
82556 this.immediateMode._curveVertex[3],
82557 this.immediateMode._curveVertex[5],
82558 this.immediateMode._curveVertex[7]
82559 ]);
82560
82561 for (i = 0; i < LUTLength; i++) {
82562 _x =
82563 w_x[0] * this._lookUpTableBezier[i][0] +
82564 w_x[1] * this._lookUpTableBezier[i][1] +
82565 w_x[2] * this._lookUpTableBezier[i][2] +
82566 w_x[3] * this._lookUpTableBezier[i][3];
82567 _y =
82568 w_y[0] * this._lookUpTableBezier[i][0] +
82569 w_y[1] * this._lookUpTableBezier[i][1] +
82570 w_y[2] * this._lookUpTableBezier[i][2] +
82571 w_y[3] * this._lookUpTableBezier[i][3];
82572 this.vertex(_x, _y);
82573 }
82574 for (i = 0; i < argLength; i++) {
82575 this.immediateMode._curveVertex.shift();
82576 }
82577 }
82578 } else if (argLength === 3) {
82579 this.immediateMode._curveVertex.push(
82580 arguments.length <= 0 ? undefined : arguments[0]
82581 );
82582 this.immediateMode._curveVertex.push(
82583 arguments.length <= 1 ? undefined : arguments[1]
82584 );
82585 this.immediateMode._curveVertex.push(
82586 arguments.length <= 2 ? undefined : arguments[2]
82587 );
82588 if (this.immediateMode._curveVertex.length === 12) {
82589 this.isCurve = true;
82590 w_x = this._bezierToCatmull([
82591 this.immediateMode._curveVertex[0],
82592 this.immediateMode._curveVertex[3],
82593 this.immediateMode._curveVertex[6],
82594 this.immediateMode._curveVertex[9]
82595 ]);
82596
82597 w_y = this._bezierToCatmull([
82598 this.immediateMode._curveVertex[1],
82599 this.immediateMode._curveVertex[4],
82600 this.immediateMode._curveVertex[7],
82601 this.immediateMode._curveVertex[10]
82602 ]);
82603
82604 w_z = this._bezierToCatmull([
82605 this.immediateMode._curveVertex[2],
82606 this.immediateMode._curveVertex[5],
82607 this.immediateMode._curveVertex[8],
82608 this.immediateMode._curveVertex[11]
82609 ]);
82610
82611 for (i = 0; i < LUTLength; i++) {
82612 _x =
82613 w_x[0] * this._lookUpTableBezier[i][0] +
82614 w_x[1] * this._lookUpTableBezier[i][1] +
82615 w_x[2] * this._lookUpTableBezier[i][2] +
82616 w_x[3] * this._lookUpTableBezier[i][3];
82617 _y =
82618 w_y[0] * this._lookUpTableBezier[i][0] +
82619 w_y[1] * this._lookUpTableBezier[i][1] +
82620 w_y[2] * this._lookUpTableBezier[i][2] +
82621 w_y[3] * this._lookUpTableBezier[i][3];
82622 _z =
82623 w_z[0] * this._lookUpTableBezier[i][0] +
82624 w_z[1] * this._lookUpTableBezier[i][1] +
82625 w_z[2] * this._lookUpTableBezier[i][2] +
82626 w_z[3] * this._lookUpTableBezier[i][3];
82627 this.vertex(_x, _y, _z);
82628 }
82629 for (i = 0; i < argLength; i++) {
82630 this.immediateMode._curveVertex.shift();
82631 }
82632 }
82633 }
82634 };
82635
82636 _main.default.RendererGL.prototype.image = function(
82637 img,
82638 sx,
82639 sy,
82640 sWidth,
82641 sHeight,
82642 dx,
82643 dy,
82644 dWidth,
82645 dHeight
82646 ) {
82647 if (this._isErasing) {
82648 this.blendMode(this._cachedBlendMode);
82649 }
82650
82651 this._pInst.push();
82652
82653 this._pInst.noLights();
82654
82655 this._pInst.texture(img);
82656 this._pInst.textureMode(constants.NORMAL);
82657
82658 var u0 = 0;
82659 if (sx <= img.width) {
82660 u0 = sx / img.width;
82661 }
82662
82663 var u1 = 1;
82664 if (sx + sWidth <= img.width) {
82665 u1 = (sx + sWidth) / img.width;
82666 }
82667
82668 var v0 = 0;
82669 if (sy <= img.height) {
82670 v0 = sy / img.height;
82671 }
82672
82673 var v1 = 1;
82674 if (sy + sHeight <= img.height) {
82675 v1 = (sy + sHeight) / img.height;
82676 }
82677
82678 this.beginShape();
82679 this.vertex(dx, dy, 0, u0, v0);
82680 this.vertex(dx + dWidth, dy, 0, u1, v0);
82681 this.vertex(dx + dWidth, dy + dHeight, 0, u1, v1);
82682 this.vertex(dx, dy + dHeight, 0, u0, v1);
82683 this.endShape(constants.CLOSE);
82684
82685 this._pInst.pop();
82686
82687 if (this._isErasing) {
82688 this.blendMode(constants.REMOVE);
82689 }
82690 };
82691 var _default = _main.default;
82692 exports.default = _default;
82693 },
82694 { '../core/constants': 43, '../core/main': 54, './p5.Geometry': 103 }
82695 ],
82696 98: [
82697 function(_dereq_, module, exports) {
82698 'use strict';
82699 function _typeof(obj) {
82700 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
82701 _typeof = function _typeof(obj) {
82702 return typeof obj;
82703 };
82704 } else {
82705 _typeof = function _typeof(obj) {
82706 return obj &&
82707 typeof Symbol === 'function' &&
82708 obj.constructor === Symbol &&
82709 obj !== Symbol.prototype
82710 ? 'symbol'
82711 : typeof obj;
82712 };
82713 }
82714 return _typeof(obj);
82715 }
82716 Object.defineProperty(exports, '__esModule', { value: true });
82717 exports.default = void 0;
82718
82719 var _main = _interopRequireDefault(_dereq_('../core/main'));
82720 var constants = _interopRequireWildcard(_dereq_('../core/constants'));
82721 function _getRequireWildcardCache() {
82722 if (typeof WeakMap !== 'function') return null;
82723 var cache = new WeakMap();
82724 _getRequireWildcardCache = function _getRequireWildcardCache() {
82725 return cache;
82726 };
82727 return cache;
82728 }
82729 function _interopRequireWildcard(obj) {
82730 if (obj && obj.__esModule) {
82731 return obj;
82732 }
82733 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) {
82734 return { default: obj };
82735 }
82736 var cache = _getRequireWildcardCache();
82737 if (cache && cache.has(obj)) {
82738 return cache.get(obj);
82739 }
82740 var newObj = {};
82741 var hasPropertyDescriptor =
82742 Object.defineProperty && Object.getOwnPropertyDescriptor;
82743 for (var key in obj) {
82744 if (Object.prototype.hasOwnProperty.call(obj, key)) {
82745 var desc = hasPropertyDescriptor
82746 ? Object.getOwnPropertyDescriptor(obj, key)
82747 : null;
82748 if (desc && (desc.get || desc.set)) {
82749 Object.defineProperty(newObj, key, desc);
82750 } else {
82751 newObj[key] = obj[key];
82752 }
82753 }
82754 }
82755 newObj.default = obj;
82756 if (cache) {
82757 cache.set(obj, newObj);
82758 }
82759 return newObj;
82760 }
82761 function _interopRequireDefault(obj) {
82762 return obj && obj.__esModule ? obj : { default: obj };
82763 } /** // implementation based on three.js 'orbitControls':
82764 * @module Lights, Camera
82765 * @submodule Interaction
82766 * @for p5
82767 * @requires core
82768 */ /**
82769 * Allows movement around a 3D sketch using a mouse or trackpad. Left-clicking
82770 * and dragging will rotate the camera position about the center of the sketch,
82771 * right-clicking and dragging will pan the camera position without rotation,
82772 * and using the mouse wheel (scrolling) will move the camera closer or further
82773 * from the center of the sketch. This function can be called with parameters
82774 * dictating sensitivity to mouse movement along the X and Y axes. Calling
82775 * this function without parameters is equivalent to calling orbitControl(1,1).
82776 * To reverse direction of movement in either axis, enter a negative number
82777 * for sensitivity.
82778 * @method orbitControl
82779 * @for p5
82780 * @param {Number} [sensitivityX] sensitivity to mouse movement along X axis
82781 * @param {Number} [sensitivityY] sensitivity to mouse movement along Y axis
82782 * @param {Number} [sensitivityZ] sensitivity to scroll movement along Z axis
82783 * @chainable
82784 * @example
82785 * <div>
82786 * <code>
82787 * function setup() {
82788 * createCanvas(100, 100, WEBGL);
82789 * normalMaterial();
82790 * }
82791 * function draw() {
82792 * background(200);
82793 * orbitControl();
82794 * rotateY(0.5);
82795 * box(30, 50);
82796 * }
82797 * </code>
82798 * </div>
82799 *
82800 * @alt
82801 * Camera orbits around a box when mouse is hold-clicked & then moved.
82802 */
82803 // https://github.com/mrdoob/three.js/blob/dev/examples/js/controls/OrbitControls.js
82804 _main.default.prototype.orbitControl = function(
82805 sensitivityX,
82806 sensitivityY,
82807 sensitivityZ
82808 ) {
82809 this._assert3d('orbitControl');
82810 _main.default._validateParameters('orbitControl', arguments);
82811
82812 // If the mouse is not in bounds of the canvas, disable all behaviors:
82813 var mouseInCanvas =
82814 this.mouseX < this.width &&
82815 this.mouseX > 0 &&
82816 this.mouseY < this.height &&
82817 this.mouseY > 0;
82818 if (!mouseInCanvas) return;
82819
82820 var cam = this._renderer._curCamera;
82821
82822 if (typeof sensitivityX === 'undefined') {
82823 sensitivityX = 1;
82824 }
82825 if (typeof sensitivityY === 'undefined') {
82826 sensitivityY = sensitivityX;
82827 }
82828 if (typeof sensitivityZ === 'undefined') {
82829 sensitivityZ = 0.5;
82830 }
82831
82832 // default right-mouse and mouse-wheel behaviors (context menu and scrolling,
82833 // respectively) are disabled here to allow use of those events for panning and
82834 // zooming
82835
82836 // disable context menu for canvas element and add 'contextMenuDisabled'
82837 // flag to p5 instance
82838 if (this.contextMenuDisabled !== true) {
82839 this.canvas.oncontextmenu = function() {
82840 return false;
82841 };
82842 this._setProperty('contextMenuDisabled', true);
82843 }
82844
82845 // disable default scrolling behavior on the canvas element and add
82846 // 'wheelDefaultDisabled' flag to p5 instance
82847 if (this.wheelDefaultDisabled !== true) {
82848 this.canvas.onwheel = function() {
82849 return false;
82850 };
82851 this._setProperty('wheelDefaultDisabled', true);
82852 }
82853
82854 var scaleFactor = this.height < this.width ? this.height : this.width;
82855
82856 // ZOOM if there is a change in mouseWheelDelta
82857 if (this._mouseWheelDeltaY !== this._pmouseWheelDeltaY) {
82858 // zoom according to direction of mouseWheelDeltaY rather than value
82859 if (this._mouseWheelDeltaY > 0) {
82860 this._renderer._curCamera._orbit(0, 0, sensitivityZ * scaleFactor);
82861 } else {
82862 this._renderer._curCamera._orbit(0, 0, -sensitivityZ * scaleFactor);
82863 }
82864 }
82865
82866 if (this.mouseIsPressed) {
82867 // ORBIT BEHAVIOR
82868 if (this.mouseButton === this.LEFT) {
82869 var deltaTheta = -sensitivityX * (this.mouseX - this.pmouseX) / scaleFactor;
82870 var deltaPhi = sensitivityY * (this.mouseY - this.pmouseY) / scaleFactor;
82871 this._renderer._curCamera._orbit(deltaTheta, deltaPhi, 0);
82872 } else if (this.mouseButton === this.RIGHT) {
82873 // PANNING BEHAVIOR along X/Z camera axes and restricted to X/Z plane
82874 // in world space
82875 var local = cam._getLocalAxes();
82876
82877 // normalize portions along X/Z axes
82878 var xmag = Math.sqrt(local.x[0] * local.x[0] + local.x[2] * local.x[2]);
82879 if (xmag !== 0) {
82880 local.x[0] /= xmag;
82881 local.x[2] /= xmag;
82882 }
82883
82884 // normalize portions along X/Z axes
82885 var ymag = Math.sqrt(local.y[0] * local.y[0] + local.y[2] * local.y[2]);
82886 if (ymag !== 0) {
82887 local.y[0] /= ymag;
82888 local.y[2] /= ymag;
82889 }
82890
82891 // move along those vectors by amount controlled by mouseX, pmouseY
82892 var dx = -1 * sensitivityX * (this.mouseX - this.pmouseX);
82893 var dz = -1 * sensitivityY * (this.mouseY - this.pmouseY);
82894
82895 // restrict movement to XZ plane in world space
82896 cam.setPosition(
82897 cam.eyeX + dx * local.x[0] + dz * local.z[0],
82898 cam.eyeY,
82899 cam.eyeZ + dx * local.x[2] + dz * local.z[2]
82900 );
82901 }
82902 }
82903 return this;
82904 };
82905
82906 /**
82907 * debugMode() helps visualize 3D space by adding a grid to indicate where the
82908 * ‘ground’ is in a sketch and an axes icon which indicates the +X, +Y, and +Z
82909 * directions. This function can be called without parameters to create a
82910 * default grid and axes icon, or it can be called according to the examples
82911 * above to customize the size and position of the grid and/or axes icon. The
82912 * grid is drawn using the most recently set stroke color and weight. To
82913 * specify these parameters, add a call to stroke() and strokeWeight()
82914 * just before the end of the draw() loop.
82915 *
82916 * By default, the grid will run through the origin (0,0,0) of the sketch
82917 * along the XZ plane
82918 * and the axes icon will be offset from the origin. Both the grid and axes
82919 * icon will be sized according to the current canvas size. Note that because the
82920 * grid runs parallel to the default camera view, it is often helpful to use
82921 * debugMode along with orbitControl to allow full view of the grid.
82922 * @method debugMode
82923 * @example
82924 * <div>
82925 * <code>
82926 * function setup() {
82927 * createCanvas(100, 100, WEBGL);
82928 * camera(0, -30, 100, 0, 0, 0, 0, 1, 0);
82929 * normalMaterial();
82930 * debugMode();
82931 * }
82932 *
82933 * function draw() {
82934 * background(200);
82935 * orbitControl();
82936 * box(15, 30);
82937 * // Press the spacebar to turn debugMode off!
82938 * if (keyIsDown(32)) {
82939 * noDebugMode();
82940 * }
82941 * }
82942 * </code>
82943 * </div>
82944 * @alt
82945 * a 3D box is centered on a grid in a 3D sketch. an icon
82946 * indicates the direction of each axis: a red line points +X,
82947 * a green line +Y, and a blue line +Z. the grid and icon disappear when the
82948 * spacebar is pressed.
82949 *
82950 * @example
82951 * <div>
82952 * <code>
82953 * function setup() {
82954 * createCanvas(100, 100, WEBGL);
82955 * camera(0, -30, 100, 0, 0, 0, 0, 1, 0);
82956 * normalMaterial();
82957 * debugMode(GRID);
82958 * }
82959 *
82960 * function draw() {
82961 * background(200);
82962 * orbitControl();
82963 * box(15, 30);
82964 * }
82965 * </code>
82966 * </div>
82967 * @alt
82968 * a 3D box is centered on a grid in a 3D sketch.
82969 *
82970 * @example
82971 * <div>
82972 * <code>
82973 * function setup() {
82974 * createCanvas(100, 100, WEBGL);
82975 * camera(0, -30, 100, 0, 0, 0, 0, 1, 0);
82976 * normalMaterial();
82977 * debugMode(AXES);
82978 * }
82979 *
82980 * function draw() {
82981 * background(200);
82982 * orbitControl();
82983 * box(15, 30);
82984 * }
82985 * </code>
82986 * </div>
82987 * @alt
82988 * a 3D box is centered in a 3D sketch. an icon
82989 * indicates the direction of each axis: a red line points +X,
82990 * a green line +Y, and a blue line +Z.
82991 *
82992 * @example
82993 * <div>
82994 * <code>
82995 * function setup() {
82996 * createCanvas(100, 100, WEBGL);
82997 * camera(0, -30, 100, 0, 0, 0, 0, 1, 0);
82998 * normalMaterial();
82999 * debugMode(GRID, 100, 10, 0, 0, 0);
83000 * }
83001 *
83002 * function draw() {
83003 * background(200);
83004 * orbitControl();
83005 * box(15, 30);
83006 * }
83007 * </code>
83008 * </div>
83009 * @alt
83010 * a 3D box is centered on a grid in a 3D sketch
83011 *
83012 * @example
83013 * <div>
83014 * <code>
83015 * function setup() {
83016 * createCanvas(100, 100, WEBGL);
83017 * camera(0, -30, 100, 0, 0, 0, 0, 1, 0);
83018 * normalMaterial();
83019 * debugMode(100, 10, 0, 0, 0, 20, 0, -40, 0);
83020 * }
83021 *
83022 * function draw() {
83023 * noStroke();
83024 * background(200);
83025 * orbitControl();
83026 * box(15, 30);
83027 * // set the stroke color and weight for the grid!
83028 * stroke(255, 0, 150);
83029 * strokeWeight(0.8);
83030 * }
83031 * </code>
83032 * </div>
83033 * @alt
83034 * a 3D box is centered on a grid in a 3D sketch. an icon
83035 * indicates the direction of each axis: a red line points +X,
83036 * a green line +Y, and a blue line +Z.
83037 */
83038
83039 /**
83040 * @method debugMode
83041 * @param {Constant} mode either GRID or AXES
83042 */
83043
83044 /**
83045 * @method debugMode
83046 * @param {Constant} mode
83047 * @param {Number} [gridSize] size of one side of the grid
83048 * @param {Number} [gridDivisions] number of divisions in the grid
83049 * @param {Number} [xOff] X axis offset from origin (0,0,0)
83050 * @param {Number} [yOff] Y axis offset from origin (0,0,0)
83051 * @param {Number} [zOff] Z axis offset from origin (0,0,0)
83052 */
83053
83054 /**
83055 * @method debugMode
83056 * @param {Constant} mode
83057 * @param {Number} [axesSize] size of axes icon
83058 * @param {Number} [xOff]
83059 * @param {Number} [yOff]
83060 * @param {Number} [zOff]
83061 */
83062
83063 /**
83064 * @method debugMode
83065 * @param {Number} [gridSize]
83066 * @param {Number} [gridDivisions]
83067 * @param {Number} [gridXOff]
83068 * @param {Number} [gridYOff]
83069 * @param {Number} [gridZOff]
83070 * @param {Number} [axesSize]
83071 * @param {Number} [axesXOff]
83072 * @param {Number} [axesYOff]
83073 * @param {Number} [axesZOff]
83074 */
83075
83076 _main.default.prototype.debugMode = function() {
83077 this._assert3d('debugMode');
83078 for (
83079 var _len = arguments.length, args = new Array(_len), _key = 0;
83080 _key < _len;
83081 _key++
83082 ) {
83083 args[_key] = arguments[_key];
83084 }
83085 _main.default._validateParameters('debugMode', args);
83086
83087 // start by removing existing 'post' registered debug methods
83088 for (var i = this._registeredMethods.post.length - 1; i >= 0; i--) {
83089 // test for equality...
83090 if (
83091 this._registeredMethods.post[i].toString() === this._grid().toString() ||
83092 this._registeredMethods.post[i].toString() === this._axesIcon().toString()
83093 ) {
83094 this._registeredMethods.post.splice(i, 1);
83095 }
83096 }
83097
83098 // then add new debugMode functions according to the argument list
83099 if (args[0] === constants.GRID) {
83100 this.registerMethod(
83101 'post',
83102 this._grid.call(this, args[1], args[2], args[3], args[4], args[5])
83103 );
83104 } else if (args[0] === constants.AXES) {
83105 this.registerMethod(
83106 'post',
83107 this._axesIcon.call(this, args[1], args[2], args[3], args[4])
83108 );
83109 } else {
83110 this.registerMethod(
83111 'post',
83112 this._grid.call(this, args[0], args[1], args[2], args[3], args[4])
83113 );
83114
83115 this.registerMethod(
83116 'post',
83117 this._axesIcon.call(this, args[5], args[6], args[7], args[8])
83118 );
83119 }
83120 };
83121
83122 /**
83123 * Turns off debugMode() in a 3D sketch.
83124 * @method noDebugMode
83125 * @example
83126 * <div>
83127 * <code>
83128 * function setup() {
83129 * createCanvas(100, 100, WEBGL);
83130 * camera(0, -30, 100, 0, 0, 0, 0, 1, 0);
83131 * normalMaterial();
83132 * debugMode();
83133 * }
83134 *
83135 * function draw() {
83136 * background(200);
83137 * orbitControl();
83138 * box(15, 30);
83139 * // Press the spacebar to turn debugMode off!
83140 * if (keyIsDown(32)) {
83141 * noDebugMode();
83142 * }
83143 * }
83144 * </code>
83145 * </div>
83146 * @alt
83147 * a 3D box is centered on a grid in a 3D sketch. an icon
83148 * indicates the direction of each axis: a red line points +X,
83149 * a green line +Y, and a blue line +Z. the grid and icon disappear when the
83150 * spacebar is pressed.
83151 */
83152 _main.default.prototype.noDebugMode = function() {
83153 this._assert3d('noDebugMode');
83154
83155 // start by removing existing 'post' registered debug methods
83156 for (var i = this._registeredMethods.post.length - 1; i >= 0; i--) {
83157 // test for equality...
83158 if (
83159 this._registeredMethods.post[i].toString() === this._grid().toString() ||
83160 this._registeredMethods.post[i].toString() === this._axesIcon().toString()
83161 ) {
83162 this._registeredMethods.post.splice(i, 1);
83163 }
83164 }
83165 };
83166
83167 /**
83168 * For use with debugMode
83169 * @private
83170 * @method _grid
83171 * @param {Number} [size] size of grid sides
83172 * @param {Number} [div] number of grid divisions
83173 * @param {Number} [xOff] offset of grid center from origin in X axis
83174 * @param {Number} [yOff] offset of grid center from origin in Y axis
83175 * @param {Number} [zOff] offset of grid center from origin in Z axis
83176 */
83177 _main.default.prototype._grid = function(size, numDivs, xOff, yOff, zOff) {
83178 if (typeof size === 'undefined') {
83179 size = this.width / 2;
83180 }
83181 if (typeof numDivs === 'undefined') {
83182 // ensure at least 2 divisions
83183 numDivs = Math.round(size / 30) < 4 ? 4 : Math.round(size / 30);
83184 }
83185 if (typeof xOff === 'undefined') {
83186 xOff = 0;
83187 }
83188 if (typeof yOff === 'undefined') {
83189 yOff = 0;
83190 }
83191 if (typeof zOff === 'undefined') {
83192 zOff = 0;
83193 }
83194
83195 var spacing = size / numDivs;
83196 var halfSize = size / 2;
83197
83198 return function() {
83199 this.push();
83200 this.stroke(
83201 this._renderer.curStrokeColor[0] * 255,
83202 this._renderer.curStrokeColor[1] * 255,
83203 this._renderer.curStrokeColor[2] * 255
83204 );
83205
83206 this._renderer.uMVMatrix.set(
83207 this._renderer._curCamera.cameraMatrix.mat4[0],
83208 this._renderer._curCamera.cameraMatrix.mat4[1],
83209 this._renderer._curCamera.cameraMatrix.mat4[2],
83210 this._renderer._curCamera.cameraMatrix.mat4[3],
83211 this._renderer._curCamera.cameraMatrix.mat4[4],
83212 this._renderer._curCamera.cameraMatrix.mat4[5],
83213 this._renderer._curCamera.cameraMatrix.mat4[6],
83214 this._renderer._curCamera.cameraMatrix.mat4[7],
83215 this._renderer._curCamera.cameraMatrix.mat4[8],
83216 this._renderer._curCamera.cameraMatrix.mat4[9],
83217 this._renderer._curCamera.cameraMatrix.mat4[10],
83218 this._renderer._curCamera.cameraMatrix.mat4[11],
83219 this._renderer._curCamera.cameraMatrix.mat4[12],
83220 this._renderer._curCamera.cameraMatrix.mat4[13],
83221 this._renderer._curCamera.cameraMatrix.mat4[14],
83222 this._renderer._curCamera.cameraMatrix.mat4[15]
83223 );
83224
83225 // Lines along X axis
83226 for (var q = 0; q <= numDivs; q++) {
83227 this.beginShape(this.LINES);
83228 this.vertex(-halfSize + xOff, yOff, q * spacing - halfSize + zOff);
83229 this.vertex(+halfSize + xOff, yOff, q * spacing - halfSize + zOff);
83230 this.endShape();
83231 }
83232
83233 // Lines along Z axis
83234 for (var i = 0; i <= numDivs; i++) {
83235 this.beginShape(this.LINES);
83236 this.vertex(i * spacing - halfSize + xOff, yOff, -halfSize + zOff);
83237 this.vertex(i * spacing - halfSize + xOff, yOff, +halfSize + zOff);
83238 this.endShape();
83239 }
83240
83241 this.pop();
83242 };
83243 };
83244
83245 /**
83246 * For use with debugMode
83247 * @private
83248 * @method _axesIcon
83249 * @param {Number} [size] size of axes icon lines
83250 * @param {Number} [xOff] offset of icon from origin in X axis
83251 * @param {Number} [yOff] offset of icon from origin in Y axis
83252 * @param {Number} [zOff] offset of icon from origin in Z axis
83253 */
83254 _main.default.prototype._axesIcon = function(size, xOff, yOff, zOff) {
83255 if (typeof size === 'undefined') {
83256 size = this.width / 20 > 40 ? this.width / 20 : 40;
83257 }
83258 if (typeof xOff === 'undefined') {
83259 xOff = -this.width / 4;
83260 }
83261 if (typeof yOff === 'undefined') {
83262 yOff = xOff;
83263 }
83264 if (typeof zOff === 'undefined') {
83265 zOff = xOff;
83266 }
83267
83268 return function() {
83269 this.push();
83270 this._renderer.uMVMatrix.set(
83271 this._renderer._curCamera.cameraMatrix.mat4[0],
83272 this._renderer._curCamera.cameraMatrix.mat4[1],
83273 this._renderer._curCamera.cameraMatrix.mat4[2],
83274 this._renderer._curCamera.cameraMatrix.mat4[3],
83275 this._renderer._curCamera.cameraMatrix.mat4[4],
83276 this._renderer._curCamera.cameraMatrix.mat4[5],
83277 this._renderer._curCamera.cameraMatrix.mat4[6],
83278 this._renderer._curCamera.cameraMatrix.mat4[7],
83279 this._renderer._curCamera.cameraMatrix.mat4[8],
83280 this._renderer._curCamera.cameraMatrix.mat4[9],
83281 this._renderer._curCamera.cameraMatrix.mat4[10],
83282 this._renderer._curCamera.cameraMatrix.mat4[11],
83283 this._renderer._curCamera.cameraMatrix.mat4[12],
83284 this._renderer._curCamera.cameraMatrix.mat4[13],
83285 this._renderer._curCamera.cameraMatrix.mat4[14],
83286 this._renderer._curCamera.cameraMatrix.mat4[15]
83287 );
83288
83289 // X axis
83290 this.strokeWeight(2);
83291 this.stroke(255, 0, 0);
83292 this.beginShape(this.LINES);
83293 this.vertex(xOff, yOff, zOff);
83294 this.vertex(xOff + size, yOff, zOff);
83295 this.endShape();
83296 // Y axis
83297 this.stroke(0, 255, 0);
83298 this.beginShape(this.LINES);
83299 this.vertex(xOff, yOff, zOff);
83300 this.vertex(xOff, yOff + size, zOff);
83301 this.endShape();
83302 // Z axis
83303 this.stroke(0, 0, 255);
83304 this.beginShape(this.LINES);
83305 this.vertex(xOff, yOff, zOff);
83306 this.vertex(xOff, yOff, zOff + size);
83307 this.endShape();
83308 this.pop();
83309 };
83310 };
83311 var _default = _main.default;
83312 exports.default = _default;
83313 },
83314 { '../core/constants': 43, '../core/main': 54 }
83315 ],
83316 99: [
83317 function(_dereq_, module, exports) {
83318 'use strict';
83319 Object.defineProperty(exports, '__esModule', { value: true });
83320 exports.default = void 0;
83321
83322 var _main = _interopRequireDefault(_dereq_('../core/main'));
83323 function _interopRequireDefault(obj) {
83324 return obj && obj.__esModule ? obj : { default: obj };
83325 } /**
83326 * @method ambientLight
83327 * @param {String} value a color string
83328 * @chainable
83329 */ /**
83330 * @module Lights, Camera
83331 * @submodule Lights
83332 * @for p5
83333 * @requires core
83334 */ /**
83335 * Creates an ambient light with a color. Ambient light is light that comes from everywhere on the canvas.
83336 * It has no particular source.
83337 * @method ambientLight
83338 * @param {Number} v1 red or hue value relative to
83339 * the current color range
83340 * @param {Number} v2 green or saturation value
83341 * relative to the current color range
83342 * @param {Number} v3 blue or brightness value
83343 * relative to the current color range
83344 * @param {Number} [alpha] the alpha value
83345 * @chainable
83346 *
83347 * @example
83348 * <div>
83349 * <code>
83350 * createCanvas(100, 100, WEBGL);
83351 * ambientLight(0);
83352 * ambientMaterial(250);
83353 * sphere(40);
83354 * </code>
83355 * </div>
83356 * <div>
83357 * <code>
83358 * function setup() {
83359 * createCanvas(100, 100, WEBGL);
83360 * }
83361 * function draw() {
83362 * background(51);
83363 * ambientLight(100); // white light
83364 * ambientMaterial(255, 102, 94); // magenta material
83365 * box(30);
83366 * }
83367 * </code>
83368 * </div>
83369 * @alt
83370 * evenly distributed light across a sphere
83371 * evenly distributed light across a rotating sphere
83372 */
83373 /**
83374 * @method ambientLight
83375 * @param {Number} gray a gray value
83376 * @param {Number} [alpha]
83377 * @chainable
83378 */
83379
83380 /**
83381 * @method ambientLight
83382 * @param {Number[]} values an array containing the red,green,blue &
83383 * and alpha components of the color
83384 * @chainable
83385 */
83386
83387 /**
83388 * @method ambientLight
83389 * @param {p5.Color} color the ambient light color
83390 * @chainable
83391 */
83392 _main.default.prototype.ambientLight = function(v1, v2, v3, a) {
83393 this._assert3d('ambientLight');
83394 _main.default._validateParameters('ambientLight', arguments);
83395 var color = this.color.apply(this, arguments);
83396
83397 this._renderer.ambientLightColors.push(
83398 color._array[0],
83399 color._array[1],
83400 color._array[2]
83401 );
83402
83403 this._renderer._enableLighting = true;
83404
83405 return this;
83406 };
83407
83408 /**
83409 * Set's the color of the specular highlight when using a specular material and
83410 * specular light.
83411 *
83412 * This method can be combined with specularMaterial() and shininess()
83413 * functions to set specular highlights. The default color is white, ie
83414 * (255, 255, 255), which is used if this method is not called before
83415 * specularMaterial(). If this method is called without specularMaterial(),
83416 * There will be no effect.
83417 *
83418 * Note: specularColor is equivalent to the processing function
83419 * <a href="https://processing.org/reference/lightSpecular_.html">lightSpecular</a>.
83420 *
83421 * @method specularColor
83422 * @param {Number} v1 red or hue value relative to
83423 * the current color range
83424 * @param {Number} v2 green or saturation value
83425 * relative to the current color range
83426 * @param {Number} v3 blue or brightness value
83427 * relative to the current color range
83428 * @chainable
83429 * @example
83430 * <div>
83431 * <code>
83432 * function setup() {
83433 * createCanvas(100, 100, WEBGL);
83434 * noStroke();
83435 * }
83436 *
83437 * function draw() {
83438 * background(0);
83439 * shininess(20);
83440 * ambientLight(50);
83441 * specularColor(255, 0, 0);
83442 * pointLight(255, 0, 0, 0, -50, 50);
83443 * specularColor(0, 255, 0);
83444 * pointLight(0, 255, 0, 0, 50, 50);
83445 * specularMaterial(255);
83446 * sphere(40);
83447 * }
83448 * </code>
83449 * </div>
83450 *
83451 * @alt
83452 * different specular light sources from top and bottom of canvas
83453 */
83454
83455 /**
83456 * @method specularColor
83457 * @param {String} value a color string
83458 * @chainable
83459 */
83460
83461 /**
83462 * @method specularColor
83463 * @param {Number} gray a gray value
83464 * @chainable
83465 */
83466
83467 /**
83468 * @method specularColor
83469 * @param {Number[]} values an array containing the red,green,blue &
83470 * and alpha components of the color
83471 * @chainable
83472 */
83473
83474 /**
83475 * @method specularColor
83476 * @param {p5.Color} color the ambient light color
83477 * @chainable
83478 */
83479 _main.default.prototype.specularColor = function(v1, v2, v3) {
83480 this._assert3d('specularColor');
83481 _main.default._validateParameters('specularColor', arguments);
83482 var color = this.color.apply(this, arguments);
83483
83484 this._renderer.specularColors = [
83485 color._array[0],
83486 color._array[1],
83487 color._array[2]
83488 ];
83489
83490 return this;
83491 };
83492
83493 /**
83494 * Creates a directional light with a color and a direction
83495 *
83496 * A maximum of 5 directionalLight can be active at one time
83497 * @method directionalLight
83498 * @param {Number} v1 red or hue value (depending on the current
83499 * color mode),
83500 * @param {Number} v2 green or saturation value
83501 * @param {Number} v3 blue or brightness value
83502 * @param {p5.Vector} position the direction of the light
83503 * @chainable
83504 * @example
83505 * <div>
83506 * <code>
83507 * function setup() {
83508 * createCanvas(100, 100, WEBGL);
83509 * }
83510 * function draw() {
83511 * background(0);
83512 * //move your mouse to change light direction
83513 * let dirX = (mouseX / width - 0.5) * 2;
83514 * let dirY = (mouseY / height - 0.5) * 2;
83515 * directionalLight(250, 250, 250, -dirX, -dirY, -1);
83516 * noStroke();
83517 * sphere(40);
83518 * }
83519 * </code>
83520 * </div>
83521 *
83522 * @alt
83523 * light source on canvas changeable with mouse position
83524 */
83525
83526 /**
83527 * @method directionalLight
83528 * @param {Number[]|String|p5.Color} color color Array, CSS color string,
83529 * or <a href="#/p5.Color">p5.Color</a> value
83530 * @param {Number} x x axis direction
83531 * @param {Number} y y axis direction
83532 * @param {Number} z z axis direction
83533 * @chainable
83534 */
83535
83536 /**
83537 * @method directionalLight
83538 * @param {Number[]|String|p5.Color} color
83539 * @param {p5.Vector} position
83540 * @chainable
83541 */
83542
83543 /**
83544 * @method directionalLight
83545 * @param {Number} v1
83546 * @param {Number} v2
83547 * @param {Number} v3
83548 * @param {Number} x
83549 * @param {Number} y
83550 * @param {Number} z
83551 * @chainable
83552 */
83553 _main.default.prototype.directionalLight = function(v1, v2, v3, x, y, z) {
83554 this._assert3d('directionalLight');
83555 _main.default._validateParameters('directionalLight', arguments);
83556
83557 //@TODO: check parameters number
83558 var color;
83559 if (v1 instanceof _main.default.Color) {
83560 color = v1;
83561 } else {
83562 color = this.color(v1, v2, v3);
83563 }
83564
83565 var _x, _y, _z;
83566 var v = arguments[arguments.length - 1];
83567 if (typeof v === 'number') {
83568 _x = arguments[arguments.length - 3];
83569 _y = arguments[arguments.length - 2];
83570 _z = arguments[arguments.length - 1];
83571 } else {
83572 _x = v.x;
83573 _y = v.y;
83574 _z = v.z;
83575 }
83576
83577 // normalize direction
83578 var l = Math.sqrt(_x * _x + _y * _y + _z * _z);
83579 this._renderer.directionalLightDirections.push(_x / l, _y / l, _z / l);
83580
83581 this._renderer.directionalLightDiffuseColors.push(
83582 color._array[0],
83583 color._array[1],
83584 color._array[2]
83585 );
83586
83587 Array.prototype.push.apply(
83588 this._renderer.directionalLightSpecularColors,
83589 this._renderer.specularColors
83590 );
83591
83592 this._renderer._enableLighting = true;
83593
83594 return this;
83595 };
83596
83597 /**
83598 * Creates a point light with a color and a light position
83599 *
83600 * A maximum of 5 pointLight can be active at one time
83601 * @method pointLight
83602 * @param {Number} v1 red or hue value (depending on the current
83603 * color mode),
83604 * @param {Number} v2 green or saturation value
83605 * @param {Number} v3 blue or brightness value
83606 * @param {Number} x x axis position
83607 * @param {Number} y y axis position
83608 * @param {Number} z z axis position
83609 * @chainable
83610 * @example
83611 * <div>
83612 * <code>
83613 * function setup() {
83614 * createCanvas(100, 100, WEBGL);
83615 * }
83616 * function draw() {
83617 * background(0);
83618 * //move your mouse to change light position
83619 * let locX = mouseX - width / 2;
83620 * let locY = mouseY - height / 2;
83621 * // to set the light position,
83622 * // think of the world's coordinate as:
83623 * // -width/2,-height/2 -------- width/2,-height/2
83624 * // | |
83625 * // | 0,0 |
83626 * // | |
83627 * // -width/2,height/2--------width/2,height/2
83628 * pointLight(250, 250, 250, locX, locY, 50);
83629 * noStroke();
83630 * sphere(40);
83631 * }
83632 * </code>
83633 * </div>
83634 *
83635 * @alt
83636 * spot light on canvas changes position with mouse
83637 */
83638
83639 /**
83640 * @method pointLight
83641 * @param {Number} v1
83642 * @param {Number} v2
83643 * @param {Number} v3
83644 * @param {p5.Vector} position the position of the light
83645 * @chainable
83646 */
83647
83648 /**
83649 * @method pointLight
83650 * @param {Number[]|String|p5.Color} color color Array, CSS color string,
83651 * or <a href="#/p5.Color">p5.Color</a> value
83652 * @param {Number} x
83653 * @param {Number} y
83654 * @param {Number} z
83655 * @chainable
83656 */
83657
83658 /**
83659 * @method pointLight
83660 * @param {Number[]|String|p5.Color} color
83661 * @param {p5.Vector} position
83662 * @chainable
83663 */
83664 _main.default.prototype.pointLight = function(v1, v2, v3, x, y, z) {
83665 this._assert3d('pointLight');
83666 _main.default._validateParameters('pointLight', arguments);
83667
83668 //@TODO: check parameters number
83669 var color;
83670 if (v1 instanceof _main.default.Color) {
83671 color = v1;
83672 } else {
83673 color = this.color(v1, v2, v3);
83674 }
83675
83676 var _x, _y, _z;
83677 var v = arguments[arguments.length - 1];
83678 if (typeof v === 'number') {
83679 _x = arguments[arguments.length - 3];
83680 _y = arguments[arguments.length - 2];
83681 _z = arguments[arguments.length - 1];
83682 } else {
83683 _x = v.x;
83684 _y = v.y;
83685 _z = v.z;
83686 }
83687
83688 this._renderer.pointLightPositions.push(_x, _y, _z);
83689 this._renderer.pointLightDiffuseColors.push(
83690 color._array[0],
83691 color._array[1],
83692 color._array[2]
83693 );
83694
83695 Array.prototype.push.apply(
83696 this._renderer.pointLightSpecularColors,
83697 this._renderer.specularColors
83698 );
83699
83700 this._renderer._enableLighting = true;
83701
83702 return this;
83703 };
83704
83705 /**
83706 * Sets the default ambient and directional light. The defaults are <a href="#/p5/ambientLight">ambientLight(128, 128, 128)</a> and <a href="#/p5/directionalLight">directionalLight(128, 128, 128, 0, 0, -1)</a>. Lights need to be included in the <a href="#/p5/draw">draw()</a> to remain persistent in a looping program. Placing them in the <a href="#/p5/setup">setup()</a> of a looping program will cause them to only have an effect the first time through the loop.
83707 * @method lights
83708 * @chainable
83709 * @example
83710 * <div>
83711 * <code>
83712 * function setup() {
83713 * createCanvas(100, 100, WEBGL);
83714 * }
83715 * function draw() {
83716 * background(0);
83717 * lights();
83718 * rotateX(millis() / 1000);
83719 * rotateY(millis() / 1000);
83720 * rotateZ(millis() / 1000);
83721 * box();
83722 * }
83723 * </code>
83724 * </div>
83725 *
83726 * @alt
83727 * the light is partially ambient and partially directional
83728 */
83729 _main.default.prototype.lights = function() {
83730 this._assert3d('lights');
83731 this.ambientLight(128, 128, 128);
83732 this.directionalLight(128, 128, 128, 0, 0, -1);
83733 return this;
83734 };
83735
83736 /**
83737 * Sets the falloff rates for point lights. It affects only the elements which are created after it in the code.
83738 * The default value is lightFalloff(1.0, 0.0, 0.0), and the parameters are used to calculate the falloff with the following equation:
83739 *
83740 * d = distance from light position to vertex position
83741 *
83742 * falloff = 1 / (CONSTANT + d \* LINEAR + ( d \* d ) \* QUADRATIC)
83743 *
83744 * @method lightFalloff
83745 * @param {Number} constant constant value for determining falloff
83746 * @param {Number} linear linear value for determining falloff
83747 * @param {Number} quadratic quadratic value for determining falloff
83748 * @chainable
83749 * @example
83750 * <div>
83751 * <code>
83752 * function setup() {
83753 * createCanvas(100, 100, WEBGL);
83754 * noStroke();
83755 * }
83756 * function draw() {
83757 * background(0);
83758 * let locX = mouseX - width / 2;
83759 * let locY = mouseY - height / 2;
83760 * translate(-25, 0, 0);
83761 * lightFalloff(1, 0, 0);
83762 * pointLight(250, 250, 250, locX, locY, 50);
83763 * sphere(20);
83764 * translate(50, 0, 0);
83765 * lightFalloff(0.9, 0.01, 0);
83766 * pointLight(250, 250, 250, locX, locY, 50);
83767 * sphere(20);
83768 * }
83769 * </code>
83770 * </div>
83771 *
83772 * @alt
83773 * Two spheres with different falloff values show different intensity of light
83774 */
83775 _main.default.prototype.lightFalloff = function(
83776 constantAttenuation,
83777 linearAttenuation,
83778 quadraticAttenuation
83779 ) {
83780 this._assert3d('lightFalloff');
83781 _main.default._validateParameters('lightFalloff', arguments);
83782
83783 if (constantAttenuation < 0) {
83784 constantAttenuation = 0;
83785 console.warn(
83786 'Value of constant argument in lightFalloff() should be never be negative. Set to 0.'
83787 );
83788 }
83789
83790 if (linearAttenuation < 0) {
83791 linearAttenuation = 0;
83792 console.warn(
83793 'Value of linear argument in lightFalloff() should be never be negative. Set to 0.'
83794 );
83795 }
83796
83797 if (quadraticAttenuation < 0) {
83798 quadraticAttenuation = 0;
83799 console.warn(
83800 'Value of quadratic argument in lightFalloff() should be never be negative. Set to 0.'
83801 );
83802 }
83803
83804 if (
83805 constantAttenuation === 0 &&
83806 linearAttenuation === 0 &&
83807 quadraticAttenuation === 0
83808 ) {
83809 constantAttenuation = 1;
83810 console.warn(
83811 'Either one of the three arguments in lightFalloff() should be greater than zero. Set constant argument to 1.'
83812 );
83813 }
83814
83815 this._renderer.constantAttenuation = constantAttenuation;
83816 this._renderer.linearAttenuation = linearAttenuation;
83817 this._renderer.quadraticAttenuation = quadraticAttenuation;
83818
83819 return this;
83820 };
83821
83822 /**
83823 * Creates a spotlight with a given color, position, direction of light,
83824 * angle and concentration. Here, angle refers to the opening or aperture
83825 * of the cone of the spotlight, and concentration is used to focus the
83826 * light towards the center. Both angle and concentration are optional, but if
83827 * you want to provide concentration, you will also have to specify the angle.
83828 *
83829 * A maximum of 5 spotLight can be active at one time
83830 * @method spotLight
83831 * @param {Number} v1 red or hue value (depending on the current
83832 * color mode),
83833 * @param {Number} v2 green or saturation value
83834 * @param {Number} v3 blue or brightness value
83835 * @param {Number} x x axis position
83836 * @param {Number} y y axis position
83837 * @param {Number} z z axis position
83838 * @param {Number} rx x axis direction of light
83839 * @param {Number} ry y axis direction of light
83840 * @param {Number} rz z axis direction of light
83841 * @param {Number} [angle] optional parameter for angle. Defaults to PI/3
83842 * @param {Number} [conc] optional parameter for concentration. Defaults to 100
83843 * @chainable
83844 *
83845 * @example
83846 * <div>
83847 * <code>
83848 * function setup() {
83849 * createCanvas(100, 100, WEBGL);
83850 * }
83851 * function draw() {
83852 * background(0);
83853 * //move your mouse to change light position
83854 * let locX = mouseX - width / 2;
83855 * let locY = mouseY - height / 2;
83856 * // to set the light position,
83857 * // think of the world's coordinate as:
83858 * // -width/2,-height/2 -------- width/2,-height/2
83859 * // | |
83860 * // | 0,0 |
83861 * // | |
83862 * // -width/2,height/2--------width/2,height/2
83863 * ambientLight(50);
83864 * spotLight(0, 250, 0, locX, locY, 100, 0, 0, -1, Math.PI / 16);
83865 * noStroke();
83866 * sphere(40);
83867 * }
83868 * </code>
83869 * </div>
83870 *
83871 * @alt
83872 * Spot light on a sphere which changes position with mouse
83873 */
83874 /**
83875 * @method spotLight
83876 * @param {Number[]|String|p5.Color} color color Array, CSS color string,
83877 * or <a href="#/p5.Color">p5.Color</a> value
83878 * @param {p5.Vector} position the position of the light
83879 * @param {p5.Vector} direction the direction of the light
83880 * @param {Number} [angle]
83881 * @param {Number} [conc]
83882 */
83883 /**
83884 * @method spotLight
83885 * @param {Number} v1
83886 * @param {Number} v2
83887 * @param {Number} v3
83888 * @param {p5.Vector} position
83889 * @param {p5.Vector} direction
83890 * @param {Number} [angle]
83891 * @param {Number} [conc]
83892 */
83893 /**
83894 * @method spotLight
83895 * @param {Number[]|String|p5.Color} color
83896 * @param {Number} x
83897 * @param {Number} y
83898 * @param {Number} z
83899 * @param {p5.Vector} direction
83900 * @param {Number} [angle]
83901 * @param {Number} [conc]
83902 */
83903 /**
83904 * @method spotLight
83905 * @param {Number[]|String|p5.Color} color
83906 * @param {p5.Vector} position
83907 * @param {Number} rx
83908 * @param {Number} ry
83909 * @param {Number} rz
83910 * @param {Number} [angle]
83911 * @param {Number} [conc]
83912 */
83913 /**
83914 * @method spotLight
83915 * @param {Number} v1
83916 * @param {Number} v2
83917 * @param {Number} v3
83918 * @param {Number} x
83919 * @param {Number} y
83920 * @param {Number} z
83921 * @param {p5.Vector} direction
83922 * @param {Number} [angle]
83923 * @param {Number} [conc]
83924 */
83925 /**
83926 * @method spotLight
83927 * @param {Number} v1
83928 * @param {Number} v2
83929 * @param {Number} v3
83930 * @param {p5.Vector} position
83931 * @param {Number} rx
83932 * @param {Number} ry
83933 * @param {Number} rz
83934 * @param {Number} [angle]
83935 * @param {Number} [conc]
83936 */
83937 /**
83938 * @method spotLight
83939 * @param {Number[]|String|p5.Color} color
83940 * @param {Number} x
83941 * @param {Number} y
83942 * @param {Number} z
83943 * @param {Number} rx
83944 * @param {Number} ry
83945 * @param {Number} rz
83946 * @param {Number} [angle]
83947 * @param {Number} [conc]
83948 */
83949 _main.default.prototype.spotLight = function(
83950 v1,
83951 v2,
83952 v3,
83953 x,
83954 y,
83955 z,
83956 nx,
83957 ny,
83958 nz,
83959 angle,
83960 concentration
83961 ) {
83962 this._assert3d('spotLight');
83963 _main.default._validateParameters('spotLight', arguments);
83964
83965 var color, position, direction;
83966 var length = arguments.length;
83967
83968 switch (length) {
83969 case 11:
83970 case 10:
83971 color = this.color(v1, v2, v3);
83972 position = new _main.default.Vector(x, y, z);
83973 direction = new _main.default.Vector(nx, ny, nz);
83974 break;
83975
83976 case 9:
83977 if (v1 instanceof _main.default.Color) {
83978 color = v1;
83979 position = new _main.default.Vector(v2, v3, x);
83980 direction = new _main.default.Vector(y, z, nx);
83981 angle = ny;
83982 concentration = nz;
83983 } else if (x instanceof _main.default.Vector) {
83984 color = this.color(v1, v2, v3);
83985 position = x;
83986 direction = new _main.default.Vector(y, z, nx);
83987 angle = ny;
83988 concentration = nz;
83989 } else if (nx instanceof _main.default.Vector) {
83990 color = this.color(v1, v2, v3);
83991 position = new _main.default.Vector(x, y, z);
83992 direction = nx;
83993 angle = ny;
83994 concentration = nz;
83995 } else {
83996 color = this.color(v1, v2, v3);
83997 position = new _main.default.Vector(x, y, z);
83998 direction = new _main.default.Vector(nx, ny, nz);
83999 }
84000 break;
84001
84002 case 8:
84003 if (v1 instanceof _main.default.Color) {
84004 color = v1;
84005 position = new _main.default.Vector(v2, v3, x);
84006 direction = new _main.default.Vector(y, z, nx);
84007 angle = ny;
84008 } else if (x instanceof _main.default.Vector) {
84009 color = this.color(v1, v2, v3);
84010 position = x;
84011 direction = new _main.default.Vector(y, z, nx);
84012 angle = ny;
84013 } else {
84014 color = this.color(v1, v2, v3);
84015 position = new _main.default.Vector(x, y, z);
84016 direction = nx;
84017 angle = ny;
84018 }
84019 break;
84020
84021 case 7:
84022 if (
84023 v1 instanceof _main.default.Color &&
84024 v2 instanceof _main.default.Vector
84025 ) {
84026 color = v1;
84027 position = v2;
84028 direction = new _main.default.Vector(v3, x, y);
84029 angle = z;
84030 concentration = nx;
84031 } else if (
84032 v1 instanceof _main.default.Color &&
84033 y instanceof _main.default.Vector
84034 ) {
84035 color = v1;
84036 position = new _main.default.Vector(v2, v3, x);
84037 direction = y;
84038 angle = z;
84039 concentration = nx;
84040 } else if (
84041 x instanceof _main.default.Vector &&
84042 y instanceof _main.default.Vector
84043 ) {
84044 color = this.color(v1, v2, v3);
84045 position = x;
84046 direction = y;
84047 angle = z;
84048 concentration = nx;
84049 } else if (v1 instanceof _main.default.Color) {
84050 color = v1;
84051 position = new _main.default.Vector(v2, v3, x);
84052 direction = new _main.default.Vector(y, z, nx);
84053 } else if (x instanceof _main.default.Vector) {
84054 color = this.color(v1, v2, v3);
84055 position = x;
84056 direction = new _main.default.Vector(y, z, nx);
84057 } else {
84058 color = this.color(v1, v2, v3);
84059 position = new _main.default.Vector(x, y, z);
84060 direction = nx;
84061 }
84062 break;
84063
84064 case 6:
84065 if (
84066 x instanceof _main.default.Vector &&
84067 y instanceof _main.default.Vector
84068 ) {
84069 color = this.color(v1, v2, v3);
84070 position = x;
84071 direction = y;
84072 angle = z;
84073 } else if (
84074 v1 instanceof _main.default.Color &&
84075 y instanceof _main.default.Vector
84076 ) {
84077 color = v1;
84078 position = new _main.default.Vector(v2, v3, x);
84079 direction = y;
84080 angle = z;
84081 } else if (
84082 v1 instanceof _main.default.Color &&
84083 v2 instanceof _main.default.Vector
84084 ) {
84085 color = v1;
84086 position = v2;
84087 direction = new _main.default.Vector(v3, x, y);
84088 angle = z;
84089 }
84090 break;
84091
84092 case 5:
84093 if (
84094 v1 instanceof _main.default.Color &&
84095 v2 instanceof _main.default.Vector &&
84096 v3 instanceof _main.default.Vector
84097 ) {
84098 color = v1;
84099 position = v2;
84100 direction = v3;
84101 angle = x;
84102 concentration = y;
84103 } else if (
84104 x instanceof _main.default.Vector &&
84105 y instanceof _main.default.Vector
84106 ) {
84107 color = this.color(v1, v2, v3);
84108 position = x;
84109 direction = y;
84110 } else if (
84111 v1 instanceof _main.default.Color &&
84112 y instanceof _main.default.Vector
84113 ) {
84114 color = v1;
84115 position = new _main.default.Vector(v2, v3, x);
84116 direction = y;
84117 } else if (
84118 v1 instanceof _main.default.Color &&
84119 v2 instanceof _main.default.Vector
84120 ) {
84121 color = v1;
84122 position = v2;
84123 direction = new _main.default.Vector(v3, x, y);
84124 }
84125 break;
84126
84127 case 4:
84128 color = v1;
84129 position = v2;
84130 direction = v3;
84131 angle = x;
84132 break;
84133
84134 case 3:
84135 color = v1;
84136 position = v2;
84137 direction = v3;
84138 break;
84139
84140 default:
84141 console.warn(
84142 'Sorry, input for spotlight() is not in prescribed format. Too '.concat(
84143 length < 3 ? 'few' : 'many',
84144 ' arguments were provided'
84145 )
84146 );
84147
84148 return this;
84149 }
84150
84151 this._renderer.spotLightDiffuseColors.push(
84152 color._array[0],
84153 color._array[1],
84154 color._array[2]
84155 );
84156
84157 Array.prototype.push.apply(
84158 this._renderer.spotLightSpecularColors,
84159 this._renderer.specularColors
84160 );
84161
84162 this._renderer.spotLightPositions.push(position.x, position.y, position.z);
84163 direction.normalize();
84164 this._renderer.spotLightDirections.push(direction.x, direction.y, direction.z);
84165
84166 if (angle === undefined) {
84167 angle = Math.PI / 3;
84168 }
84169
84170 if (concentration !== undefined && concentration < 1) {
84171 concentration = 1;
84172 console.warn(
84173 'Value of concentration needs to be greater than 1. Setting it to 1'
84174 );
84175 } else if (concentration === undefined) {
84176 concentration = 100;
84177 }
84178
84179 angle = this._renderer._pInst._toRadians(angle);
84180 this._renderer.spotLightAngle.push(Math.cos(angle));
84181 this._renderer.spotLightConc.push(concentration);
84182
84183 this._renderer._enableLighting = true;
84184
84185 return this;
84186 };
84187
84188 /**
84189 * This function will remove all the lights from the sketch for the
84190 * subsequent materials rendered. It affects all the subsequent methods.
84191 * Calls to lighting methods made after noLights() will re-enable lights
84192 * in the sketch.
84193 * @method noLights
84194 * @chainable
84195 * @example
84196 * <div>
84197 * <code>
84198 * function setup() {
84199 * createCanvas(100, 100, WEBGL);
84200 * }
84201 * function draw() {
84202 * background(0);
84203 * noStroke();
84204 *
84205 * ambientLight(150, 0, 0);
84206 * translate(-25, 0, 0);
84207 * ambientMaterial(250);
84208 * sphere(20);
84209 *
84210 * noLights();
84211 * ambientLight(0, 150, 0);
84212 * translate(50, 0, 0);
84213 * ambientMaterial(250);
84214 * sphere(20);
84215 * }
84216 * </code>
84217 * </div>
84218 *
84219 * @alt
84220 * Two spheres showing different colors
84221 */
84222 _main.default.prototype.noLights = function() {
84223 this._assert3d('noLights');
84224 _main.default._validateParameters('noLights', arguments);
84225
84226 this._renderer._enableLighting = false;
84227
84228 this._renderer.ambientLightColors.length = 0;
84229 this._renderer.specularColors = [1, 1, 1];
84230
84231 this._renderer.directionalLightDirections.length = 0;
84232 this._renderer.directionalLightDiffuseColors.length = 0;
84233 this._renderer.directionalLightSpecularColors.length = 0;
84234
84235 this._renderer.pointLightPositions.length = 0;
84236 this._renderer.pointLightDiffuseColors.length = 0;
84237 this._renderer.pointLightSpecularColors.length = 0;
84238
84239 this._renderer.spotLightPositions.length = 0;
84240 this._renderer.spotLightDirections.length = 0;
84241 this._renderer.spotLightDiffuseColors.length = 0;
84242 this._renderer.spotLightSpecularColors.length = 0;
84243 this._renderer.spotLightAngle.length = 0;
84244 this._renderer.spotLightConc.length = 0;
84245
84246 this._renderer.constantAttenuation = 1;
84247 this._renderer.linearAttenuation = 0;
84248 this._renderer.quadraticAttenuation = 0;
84249 this._renderer._useShininess = 1;
84250
84251 return this;
84252 };
84253 var _default = _main.default;
84254 exports.default = _default;
84255 },
84256 { '../core/main': 54 }
84257 ],
84258 100: [
84259 function(_dereq_, module, exports) {
84260 'use strict';
84261 Object.defineProperty(exports, '__esModule', { value: true });
84262 exports.default = void 0;
84263
84264 var _main = _interopRequireDefault(_dereq_('../core/main'));
84265 _dereq_('./p5.Geometry');
84266 function _interopRequireDefault(obj) {
84267 return obj && obj.__esModule ? obj : { default: obj };
84268 }
84269 /**
84270 * @module Shape
84271 * @submodule 3D Models
84272 * @for p5
84273 * @requires core
84274 * @requires p5.Geometry
84275 */ /**
84276 * Load a 3d model from an OBJ or STL file.
84277 *
84278 * <a href="#/p5/loadModel">loadModel()</a> should be placed inside of <a href="#/p5/preload">preload()</a>.
84279 * This allows the model to load fully before the rest of your code is run.
84280 *
84281 * One of the limitations of the OBJ and STL format is that it doesn't have a built-in
84282 * sense of scale. This means that models exported from different programs might
84283 * be very different sizes. If your model isn't displaying, try calling
84284 * <a href="#/p5/loadModel">loadModel()</a> with the normalized parameter set to true. This will resize the
84285 * model to a scale appropriate for p5. You can also make additional changes to
84286 * the final size of your model with the <a href="#/p5/scale">scale()</a> function.
84287 *
84288 * Also, the support for colored STL files is not present. STL files with color will be
84289 * rendered without color properties.
84290 *
84291 * @method loadModel
84292 * @param {String} path Path of the model to be loaded
84293 * @param {Boolean} normalize If true, scale the model to a
84294 * standardized size when loading
84295 * @param {function(p5.Geometry)} [successCallback] Function to be called
84296 * once the model is loaded. Will be passed
84297 * the 3D model object.
84298 * @param {function(Event)} [failureCallback] called with event error if
84299 * the model fails to load.
84300 * @param {String} [fileType] The file extension of the model
84301 * (<code>.stl</code>, <code>.obj</code>).
84302 * @return {p5.Geometry} the <a href="#/p5.Geometry">p5.Geometry</a> object
84303 *
84304 * @example
84305 * <div>
84306 * <code>
84307 * //draw a spinning octahedron
84308 * let octahedron;
84309 *
84310 * function preload() {
84311 * octahedron = loadModel('assets/octahedron.obj');
84312 * }
84313 *
84314 * function setup() {
84315 * createCanvas(100, 100, WEBGL);
84316 * }
84317 *
84318 * function draw() {
84319 * background(200);
84320 * rotateX(frameCount * 0.01);
84321 * rotateY(frameCount * 0.01);
84322 * model(octahedron);
84323 * }
84324 * </code>
84325 * </div>
84326 *
84327 * @alt
84328 * Vertically rotating 3-d octahedron.
84329 *
84330 * @example
84331 * <div>
84332 * <code>
84333 * //draw a spinning teapot
84334 * let teapot;
84335 *
84336 * function preload() {
84337 * // Load model with normalise parameter set to true
84338 * teapot = loadModel('assets/teapot.obj', true);
84339 * }
84340 *
84341 * function setup() {
84342 * createCanvas(100, 100, WEBGL);
84343 * }
84344 *
84345 * function draw() {
84346 * background(200);
84347 * scale(0.4); // Scaled to make model fit into canvas
84348 * rotateX(frameCount * 0.01);
84349 * rotateY(frameCount * 0.01);
84350 * normalMaterial(); // For effect
84351 * model(teapot);
84352 * }
84353 * </code>
84354 * </div>
84355 *
84356 * @alt
84357 * Vertically rotating 3-d teapot with red, green and blue gradient.
84358 */ /**
84359 * @method loadModel
84360 * @param {String} path
84361 * @param {function(p5.Geometry)} [successCallback]
84362 * @param {function(Event)} [failureCallback]
84363 * @param {String} [fileType]
84364 * @return {p5.Geometry} the <a href="#/p5.Geometry">p5.Geometry</a> object
84365 */ _main.default.prototype.loadModel = function(path) {
84366 _main.default._validateParameters('loadModel', arguments);
84367 var normalize;
84368 var successCallback;
84369 var failureCallback;
84370 var fileType = path.slice(-4);
84371 if (typeof arguments[1] === 'boolean') {
84372 normalize = arguments[1];
84373 successCallback = arguments[2];
84374 failureCallback = arguments[3];
84375 if (typeof arguments[4] !== 'undefined') {
84376 fileType = arguments[4];
84377 }
84378 } else {
84379 normalize = false;
84380 successCallback = arguments[1];
84381 failureCallback = arguments[2];
84382 if (typeof arguments[3] !== 'undefined') {
84383 fileType = arguments[3];
84384 }
84385 }
84386
84387 var model = new _main.default.Geometry();
84388 model.gid = ''.concat(path, '|').concat(normalize);
84389 var self = this;
84390
84391 if (fileType.match(/\.stl$/i)) {
84392 this.httpDo(
84393 path,
84394 'GET',
84395 'arrayBuffer',
84396 function(arrayBuffer) {
84397 parseSTL(model, arrayBuffer);
84398
84399 if (normalize) {
84400 model.normalize();
84401 }
84402 self._decrementPreload();
84403 if (typeof successCallback === 'function') {
84404 successCallback(model);
84405 }
84406 },
84407 failureCallback
84408 );
84409 } else if (fileType.match(/\.obj$/i)) {
84410 this.loadStrings(
84411 path,
84412 function(strings) {
84413 parseObj(model, strings);
84414
84415 if (normalize) {
84416 model.normalize();
84417 }
84418
84419 self._decrementPreload();
84420 if (typeof successCallback === 'function') {
84421 successCallback(model);
84422 }
84423 },
84424 failureCallback
84425 );
84426 } else {
84427 _main.default._friendlyFileLoadError(3, path);
84428
84429 if (failureCallback) {
84430 failureCallback();
84431 } else {
84432 console.error(
84433 'Sorry, the file type is invalid. Only OBJ and STL files are supported.'
84434 );
84435 }
84436 }
84437 return model;
84438 };
84439
84440 /**
84441 * Parse OBJ lines into model. For reference, this is what a simple model of a
84442 * square might look like:
84443 *
84444 * v -0.5 -0.5 0.5
84445 * v -0.5 -0.5 -0.5
84446 * v -0.5 0.5 -0.5
84447 * v -0.5 0.5 0.5
84448 *
84449 * f 4 3 2 1
84450 */
84451 function parseObj(model, lines) {
84452 // OBJ allows a face to specify an index for a vertex (in the above example),
84453 // but it also allows you to specify a custom combination of vertex, UV
84454 // coordinate, and vertex normal. So, "3/4/3" would mean, "use vertex 3 with
84455 // UV coordinate 4 and vertex normal 3". In WebGL, every vertex with different
84456 // parameters must be a different vertex, so loadedVerts is used to
84457 // temporarily store the parsed vertices, normals, etc., and indexedVerts is
84458 // used to map a specific combination (keyed on, for example, the string
84459 // "3/4/3"), to the actual index of the newly created vertex in the final
84460 // object.
84461 var loadedVerts = {
84462 v: [],
84463 vt: [],
84464 vn: []
84465 };
84466
84467 var indexedVerts = {};
84468
84469 for (var line = 0; line < lines.length; ++line) {
84470 // Each line is a separate object (vertex, face, vertex normal, etc)
84471 // For each line, split it into tokens on whitespace. The first token
84472 // describes the type.
84473 var tokens = lines[line].trim().split(/\b\s+/);
84474
84475 if (tokens.length > 0) {
84476 if (tokens[0] === 'v' || tokens[0] === 'vn') {
84477 // Check if this line describes a vertex or vertex normal.
84478 // It will have three numeric parameters.
84479 var vertex = new _main.default.Vector(
84480 parseFloat(tokens[1]),
84481 parseFloat(tokens[2]),
84482 parseFloat(tokens[3])
84483 );
84484
84485 loadedVerts[tokens[0]].push(vertex);
84486 } else if (tokens[0] === 'vt') {
84487 // Check if this line describes a texture coordinate.
84488 // It will have two numeric parameters.
84489 var texVertex = [parseFloat(tokens[1]), parseFloat(tokens[2])];
84490 loadedVerts[tokens[0]].push(texVertex);
84491 } else if (tokens[0] === 'f') {
84492 // Check if this line describes a face.
84493 // OBJ faces can have more than three points. Triangulate points.
84494 for (var tri = 3; tri < tokens.length; ++tri) {
84495 var face = [];
84496
84497 var vertexTokens = [1, tri - 1, tri];
84498
84499 for (var tokenInd = 0; tokenInd < vertexTokens.length; ++tokenInd) {
84500 // Now, convert the given token into an index
84501 var vertString = tokens[vertexTokens[tokenInd]];
84502 var vertIndex = 0;
84503
84504 // TODO: Faces can technically use negative numbers to refer to the
84505 // previous nth vertex. I haven't seen this used in practice, but
84506 // it might be good to implement this in the future.
84507
84508 if (indexedVerts[vertString] !== undefined) {
84509 vertIndex = indexedVerts[vertString];
84510 } else {
84511 var vertParts = vertString.split('/');
84512 for (var i = 0; i < vertParts.length; i++) {
84513 vertParts[i] = parseInt(vertParts[i]) - 1;
84514 }
84515
84516 vertIndex = indexedVerts[vertString] = model.vertices.length;
84517 model.vertices.push(loadedVerts.v[vertParts[0]].copy());
84518 if (loadedVerts.vt[vertParts[1]]) {
84519 model.uvs.push(loadedVerts.vt[vertParts[1]].slice());
84520 } else {
84521 model.uvs.push([0, 0]);
84522 }
84523
84524 if (loadedVerts.vn[vertParts[2]]) {
84525 model.vertexNormals.push(loadedVerts.vn[vertParts[2]].copy());
84526 }
84527 }
84528
84529 face.push(vertIndex);
84530 }
84531
84532 if (face[0] !== face[1] && face[0] !== face[2] && face[1] !== face[2]) {
84533 model.faces.push(face);
84534 }
84535 }
84536 }
84537 }
84538 }
84539 // If the model doesn't have normals, compute the normals
84540 if (model.vertexNormals.length === 0) {
84541 model.computeNormals();
84542 }
84543
84544 return model;
84545 }
84546
84547 /**
84548 * STL files can be of two types, ASCII and Binary,
84549 *
84550 * We need to convert the arrayBuffer to an array of strings,
84551 * to parse it as an ASCII file.
84552 */
84553 function parseSTL(model, buffer) {
84554 if (isBinary(buffer)) {
84555 parseBinarySTL(model, buffer);
84556 } else {
84557 var reader = new DataView(buffer);
84558
84559 if (!('TextDecoder' in window)) {
84560 console.warn(
84561 'Sorry, ASCII STL loading only works in browsers that support TextDecoder (https://caniuse.com/#feat=textencoder)'
84562 );
84563
84564 return model;
84565 }
84566
84567 var decoder = new TextDecoder('utf-8');
84568 var lines = decoder.decode(reader);
84569 var lineArray = lines.split('\n');
84570 parseASCIISTL(model, lineArray);
84571 }
84572 return model;
84573 }
84574
84575 /**
84576 * This function checks if the file is in ASCII format or in Binary format
84577 *
84578 * It is done by searching keyword `solid` at the start of the file.
84579 *
84580 * An ASCII STL data must begin with `solid` as the first six bytes.
84581 * However, ASCII STLs lacking the SPACE after the `d` are known to be
84582 * plentiful. So, check the first 5 bytes for `solid`.
84583 *
84584 * Several encodings, such as UTF-8, precede the text with up to 5 bytes:
84585 * https://en.wikipedia.org/wiki/Byte_order_mark#Byte_order_marks_by_encoding
84586 * Search for `solid` to start anywhere after those prefixes.
84587 */
84588 function isBinary(data) {
84589 var reader = new DataView(data);
84590
84591 // US-ASCII ordinal values for `s`, `o`, `l`, `i`, `d`
84592 var solid = [115, 111, 108, 105, 100];
84593 for (var off = 0; off < 5; off++) {
84594 // If "solid" text is matched to the current offset, declare it to be an ASCII STL.
84595 if (matchDataViewAt(solid, reader, off)) return false;
84596 }
84597
84598 // Couldn't find "solid" text at the beginning; it is binary STL.
84599 return true;
84600 }
84601
84602 /**
84603 * This function matches the `query` at the provided `offset`
84604 */
84605 function matchDataViewAt(query, reader, offset) {
84606 // Check if each byte in query matches the corresponding byte from the current offset
84607 for (var i = 0, il = query.length; i < il; i++) {
84608 if (query[i] !== reader.getUint8(offset + i, false)) return false;
84609 }
84610
84611 return true;
84612 }
84613
84614 /**
84615 * This function parses the Binary STL files.
84616 * https://en.wikipedia.org/wiki/STL_%28file_format%29#Binary_STL
84617 *
84618 * Currently there is no support for the colors provided in STL files.
84619 */
84620 function parseBinarySTL(model, buffer) {
84621 var reader = new DataView(buffer);
84622
84623 // Number of faces is present following the header
84624 var faces = reader.getUint32(80, true);
84625 var r,
84626 g,
84627 b,
84628 hasColors = false,
84629 colors;
84630 var defaultR, defaultG, defaultB;
84631
84632 // Binary files contain 80-byte header, which is generally ignored.
84633 for (var index = 0; index < 80 - 10; index++) {
84634 // Check for `COLOR=`
84635 if (
84636 reader.getUint32(index, false) === 0x434f4c4f /*COLO*/ &&
84637 reader.getUint8(index + 4) === 0x52 /*'R'*/ &&
84638 reader.getUint8(index + 5) === 0x3d /*'='*/
84639 ) {
84640 hasColors = true;
84641 colors = [];
84642
84643 defaultR = reader.getUint8(index + 6) / 255;
84644 defaultG = reader.getUint8(index + 7) / 255;
84645 defaultB = reader.getUint8(index + 8) / 255;
84646 // To be used when color support is added
84647 // alpha = reader.getUint8(index + 9) / 255;
84648 }
84649 }
84650 var dataOffset = 84;
84651 var faceLength = 12 * 4 + 2;
84652
84653 // Iterate the faces
84654 for (var face = 0; face < faces; face++) {
84655 var start = dataOffset + face * faceLength;
84656 var normalX = reader.getFloat32(start, true);
84657 var normalY = reader.getFloat32(start + 4, true);
84658 var normalZ = reader.getFloat32(start + 8, true);
84659
84660 if (hasColors) {
84661 var packedColor = reader.getUint16(start + 48, true);
84662
84663 if ((packedColor & 0x8000) === 0) {
84664 // facet has its own unique color
84665 r = (packedColor & 0x1f) / 31;
84666 g = ((packedColor >> 5) & 0x1f) / 31;
84667 b = ((packedColor >> 10) & 0x1f) / 31;
84668 } else {
84669 r = defaultR;
84670 g = defaultG;
84671 b = defaultB;
84672 }
84673 }
84674 var newNormal = new _main.default.Vector(normalX, normalY, normalZ);
84675
84676 for (var i = 1; i <= 3; i++) {
84677 var vertexstart = start + i * 12;
84678
84679 var newVertex = new _main.default.Vector(
84680 reader.getFloat32(vertexstart, true),
84681 reader.getFloat32(vertexstart + 4, true),
84682 reader.getFloat32(vertexstart + 8, true)
84683 );
84684
84685 model.vertices.push(newVertex);
84686 model.vertexNormals.push(newNormal);
84687
84688 if (hasColors) {
84689 colors.push(r, g, b);
84690 }
84691 }
84692
84693 model.faces.push([3 * face, 3 * face + 1, 3 * face + 2]);
84694 model.uvs.push([0, 0], [0, 0], [0, 0]);
84695 }
84696 if (hasColors) {
84697 // add support for colors here.
84698 }
84699 return model;
84700 }
84701
84702 /**
84703 * ASCII STL file starts with `solid 'nameOfFile'`
84704 * Then contain the normal of the face, starting with `facet normal`
84705 * Next contain a keyword indicating the start of face vertex, `outer loop`
84706 * Next comes the three vertex, starting with `vertex x y z`
84707 * Vertices ends with `endloop`
84708 * Face ends with `endfacet`
84709 * Next face starts with `facet normal`
84710 * The end of the file is indicated by `endsolid`
84711 */
84712 function parseASCIISTL(model, lines) {
84713 var state = '';
84714 var curVertexIndex = [];
84715 var newNormal, newVertex;
84716
84717 for (var iterator = 0; iterator < lines.length; ++iterator) {
84718 var line = lines[iterator].trim();
84719 var parts = line.split(' ');
84720
84721 for (var partsiterator = 0; partsiterator < parts.length; ++partsiterator) {
84722 if (parts[partsiterator] === '') {
84723 // Ignoring multiple whitespaces
84724 parts.splice(partsiterator, 1);
84725 }
84726 }
84727
84728 if (parts.length === 0) {
84729 // Remove newline
84730 continue;
84731 }
84732
84733 switch (state) {
84734 case '': // First run
84735 if (parts[0] !== 'solid') {
84736 // Invalid state
84737 console.error(line);
84738 console.error(
84739 'Invalid state "'.concat(parts[0], '", should be "solid"')
84740 );
84741 return;
84742 } else {
84743 state = 'solid';
84744 }
84745 break;
84746
84747 case 'solid': // First face
84748 if (parts[0] !== 'facet' || parts[1] !== 'normal') {
84749 // Invalid state
84750 console.error(line);
84751 console.error(
84752 'Invalid state "'.concat(parts[0], '", should be "facet normal"')
84753 );
84754
84755 return;
84756 } else {
84757 // Push normal for first face
84758 newNormal = new _main.default.Vector(
84759 parseFloat(parts[2]),
84760 parseFloat(parts[3]),
84761 parseFloat(parts[4])
84762 );
84763
84764 model.vertexNormals.push(newNormal, newNormal, newNormal);
84765 state = 'facet normal';
84766 }
84767 break;
84768
84769 case 'facet normal': // After normal is defined
84770 if (parts[0] !== 'outer' || parts[1] !== 'loop') {
84771 // Invalid State
84772 console.error(line);
84773 console.error(
84774 'Invalid state "'.concat(parts[0], '", should be "outer loop"')
84775 );
84776 return;
84777 } else {
84778 // Next should be vertices
84779 state = 'vertex';
84780 }
84781 break;
84782
84783 case 'vertex':
84784 if (parts[0] === 'vertex') {
84785 //Vertex of triangle
84786 newVertex = new _main.default.Vector(
84787 parseFloat(parts[1]),
84788 parseFloat(parts[2]),
84789 parseFloat(parts[3])
84790 );
84791
84792 model.vertices.push(newVertex);
84793 model.uvs.push([0, 0]);
84794 curVertexIndex.push(model.vertices.indexOf(newVertex));
84795 } else if (parts[0] === 'endloop') {
84796 // End of vertices
84797 model.faces.push(curVertexIndex);
84798 curVertexIndex = [];
84799 state = 'endloop';
84800 } else {
84801 // Invalid State
84802 console.error(line);
84803 console.error(
84804 'Invalid state "'.concat(
84805 parts[0],
84806 '", should be "vertex" or "endloop"'
84807 )
84808 );
84809
84810 return;
84811 }
84812 break;
84813
84814 case 'endloop':
84815 if (parts[0] !== 'endfacet') {
84816 // End of face
84817 console.error(line);
84818 console.error(
84819 'Invalid state "'.concat(parts[0], '", should be "endfacet"')
84820 );
84821 return;
84822 } else {
84823 state = 'endfacet';
84824 }
84825 break;
84826
84827 case 'endfacet':
84828 if (parts[0] === 'endsolid') {
84829 // End of solid
84830 } else if (parts[0] === 'facet' && parts[1] === 'normal') {
84831 // Next face
84832 newNormal = new _main.default.Vector(
84833 parseFloat(parts[2]),
84834 parseFloat(parts[3]),
84835 parseFloat(parts[4])
84836 );
84837
84838 model.vertexNormals.push(newNormal, newNormal, newNormal);
84839 state = 'facet normal';
84840 } else {
84841 // Invalid State
84842 console.error(line);
84843 console.error(
84844 'Invalid state "'.concat(
84845 parts[0],
84846 '", should be "endsolid" or "facet normal"'
84847 )
84848 );
84849
84850 return;
84851 }
84852 break;
84853
84854 default:
84855 console.error('Invalid state "'.concat(state, '"'));
84856 break;
84857 }
84858 }
84859 return model;
84860 }
84861
84862 /**
84863 * Render a 3d model to the screen.
84864 *
84865 * @method model
84866 * @param {p5.Geometry} model Loaded 3d model to be rendered
84867 * @example
84868 * <div>
84869 * <code>
84870 * //draw a spinning octahedron
84871 * let octahedron;
84872 *
84873 * function preload() {
84874 * octahedron = loadModel('assets/octahedron.obj');
84875 * }
84876 *
84877 * function setup() {
84878 * createCanvas(100, 100, WEBGL);
84879 * }
84880 *
84881 * function draw() {
84882 * background(200);
84883 * rotateX(frameCount * 0.01);
84884 * rotateY(frameCount * 0.01);
84885 * model(octahedron);
84886 * }
84887 * </code>
84888 * </div>
84889 *
84890 * @alt
84891 * Vertically rotating 3-d octahedron.
84892 */
84893 _main.default.prototype.model = function(model) {
84894 this._assert3d('model');
84895 _main.default._validateParameters('model', arguments);
84896 if (model.vertices.length > 0) {
84897 if (!this._renderer.geometryInHash(model.gid)) {
84898 model._makeTriangleEdges()._edgesToVertices();
84899 this._renderer.createBuffers(model.gid, model);
84900 }
84901
84902 this._renderer.drawBuffers(model.gid);
84903 }
84904 };
84905 var _default = _main.default;
84906 exports.default = _default;
84907 },
84908 { '../core/main': 54, './p5.Geometry': 103 }
84909 ],
84910 101: [
84911 function(_dereq_, module, exports) {
84912 'use strict';
84913 function _typeof(obj) {
84914 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
84915 _typeof = function _typeof(obj) {
84916 return typeof obj;
84917 };
84918 } else {
84919 _typeof = function _typeof(obj) {
84920 return obj &&
84921 typeof Symbol === 'function' &&
84922 obj.constructor === Symbol &&
84923 obj !== Symbol.prototype
84924 ? 'symbol'
84925 : typeof obj;
84926 };
84927 }
84928 return _typeof(obj);
84929 }
84930 Object.defineProperty(exports, '__esModule', { value: true });
84931 exports.default = void 0;
84932
84933 var _main = _interopRequireDefault(_dereq_('../core/main'));
84934 var constants = _interopRequireWildcard(_dereq_('../core/constants'));
84935 _dereq_('./p5.Texture');
84936 function _getRequireWildcardCache() {
84937 if (typeof WeakMap !== 'function') return null;
84938 var cache = new WeakMap();
84939 _getRequireWildcardCache = function _getRequireWildcardCache() {
84940 return cache;
84941 };
84942 return cache;
84943 }
84944 function _interopRequireWildcard(obj) {
84945 if (obj && obj.__esModule) {
84946 return obj;
84947 }
84948 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) {
84949 return { default: obj };
84950 }
84951 var cache = _getRequireWildcardCache();
84952 if (cache && cache.has(obj)) {
84953 return cache.get(obj);
84954 }
84955 var newObj = {};
84956 var hasPropertyDescriptor =
84957 Object.defineProperty && Object.getOwnPropertyDescriptor;
84958 for (var key in obj) {
84959 if (Object.prototype.hasOwnProperty.call(obj, key)) {
84960 var desc = hasPropertyDescriptor
84961 ? Object.getOwnPropertyDescriptor(obj, key)
84962 : null;
84963 if (desc && (desc.get || desc.set)) {
84964 Object.defineProperty(newObj, key, desc);
84965 } else {
84966 newObj[key] = obj[key];
84967 }
84968 }
84969 }
84970 newObj.default = obj;
84971 if (cache) {
84972 cache.set(obj, newObj);
84973 }
84974 return newObj;
84975 }
84976 function _interopRequireDefault(obj) {
84977 return obj && obj.__esModule ? obj : { default: obj };
84978 }
84979 /**
84980 * @module Lights, Camera
84981 * @submodule Material
84982 * @for p5
84983 * @requires core
84984 */ /**
84985 * Loads a custom shader from the provided vertex and fragment
84986 * shader paths. The shader files are loaded asynchronously in the
84987 * background, so this method should be used in <a href="#/p5/preload">preload()</a>.
84988 *
84989 * For now, there are three main types of shaders. p5 will automatically
84990 * supply appropriate vertices, normals, colors, and lighting attributes
84991 * if the parameters defined in the shader match the names.
84992 *
84993 * @method loadShader
84994 * @param {String} vertFilename path to file containing vertex shader
84995 * source code
84996 * @param {String} fragFilename path to file containing fragment shader
84997 * source code
84998 * @param {function} [callback] callback to be executed after loadShader
84999 * completes. On success, the Shader object is passed as the first argument.
85000 * @param {function} [errorCallback] callback to be executed when an error
85001 * occurs inside loadShader. On error, the error is passed as the first
85002 * argument.
85003 * @return {p5.Shader} a shader object created from the provided
85004 * vertex and fragment shader files.
85005 *
85006 * @example
85007 * <div modernizr='webgl'>
85008 * <code>
85009 * let mandel;
85010 * function preload() {
85011 * // load the shader definitions from files
85012 * mandel = loadShader('assets/shader.vert', 'assets/shader.frag');
85013 * }
85014 * function setup() {
85015 * createCanvas(100, 100, WEBGL);
85016 * // use the shader
85017 * shader(mandel);
85018 * noStroke();
85019 * mandel.setUniform('p', [-0.74364388703, 0.13182590421]);
85020 * }
85021 *
85022 * function draw() {
85023 * mandel.setUniform('r', 1.5 * exp(-6.5 * (1 + sin(millis() / 2000))));
85024 * quad(-1, -1, 1, -1, 1, 1, -1, 1);
85025 * }
85026 * </code>
85027 * </div>
85028 *
85029 * @alt
85030 * zooming Mandelbrot set. a colorful, infinitely detailed fractal.
85031 */ _main.default.prototype.loadShader = function(
85032 vertFilename,
85033 fragFilename,
85034 callback,
85035 errorCallback
85036 ) {
85037 _main.default._validateParameters('loadShader', arguments);
85038 if (!errorCallback) {
85039 errorCallback = console.error;
85040 }
85041
85042 var loadedShader = new _main.default.Shader();
85043
85044 var self = this;
85045 var loadedFrag = false;
85046 var loadedVert = false;
85047
85048 var onLoad = function onLoad() {
85049 self._decrementPreload();
85050 if (callback) {
85051 callback(loadedShader);
85052 }
85053 };
85054
85055 this.loadStrings(
85056 vertFilename,
85057 function(result) {
85058 loadedShader._vertSrc = result.join('\n');
85059 loadedVert = true;
85060 if (loadedFrag) {
85061 onLoad();
85062 }
85063 },
85064 errorCallback
85065 );
85066
85067 this.loadStrings(
85068 fragFilename,
85069 function(result) {
85070 loadedShader._fragSrc = result.join('\n');
85071 loadedFrag = true;
85072 if (loadedVert) {
85073 onLoad();
85074 }
85075 },
85076 errorCallback
85077 );
85078
85079 return loadedShader;
85080 };
85081
85082 /**
85083 * @method createShader
85084 * @param {String} vertSrc source code for the vertex shader
85085 * @param {String} fragSrc source code for the fragment shader
85086 * @returns {p5.Shader} a shader object created from the provided
85087 * vertex and fragment shaders.
85088 *
85089 * @example
85090 * <div modernizr='webgl'>
85091 * <code>
85092 * // the 'varying's are shared between both vertex & fragment shaders
85093 * let varying = 'precision highp float; varying vec2 vPos;';
85094 *
85095 * // the vertex shader is called for each vertex
85096 * let vs =
85097 * varying +
85098 * 'attribute vec3 aPosition;' +
85099 * 'void main() { vPos = (gl_Position = vec4(aPosition,1.0)).xy; }';
85100 *
85101 * // the fragment shader is called for each pixel
85102 * let fs =
85103 * varying +
85104 * 'uniform vec2 p;' +
85105 * 'uniform float r;' +
85106 * 'const int I = 500;' +
85107 * 'void main() {' +
85108 * ' vec2 c = p + vPos * r, z = c;' +
85109 * ' float n = 0.0;' +
85110 * ' for (int i = I; i > 0; i --) {' +
85111 * ' if(z.x*z.x+z.y*z.y > 4.0) {' +
85112 * ' n = float(i)/float(I);' +
85113 * ' break;' +
85114 * ' }' +
85115 * ' z = vec2(z.x*z.x-z.y*z.y, 2.0*z.x*z.y) + c;' +
85116 * ' }' +
85117 * ' 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);' +
85118 * '}';
85119 *
85120 * let mandel;
85121 * function setup() {
85122 * createCanvas(100, 100, WEBGL);
85123 *
85124 * // create and initialize the shader
85125 * mandel = createShader(vs, fs);
85126 * shader(mandel);
85127 * noStroke();
85128 *
85129 * // 'p' is the center point of the Mandelbrot image
85130 * mandel.setUniform('p', [-0.74364388703, 0.13182590421]);
85131 * }
85132 *
85133 * function draw() {
85134 * // 'r' is the size of the image in Mandelbrot-space
85135 * mandel.setUniform('r', 1.5 * exp(-6.5 * (1 + sin(millis() / 2000))));
85136 * quad(-1, -1, 1, -1, 1, 1, -1, 1);
85137 * }
85138 * </code>
85139 * </div>
85140 *
85141 * @alt
85142 * zooming Mandelbrot set. a colorful, infinitely detailed fractal.
85143 */
85144 _main.default.prototype.createShader = function(vertSrc, fragSrc) {
85145 this._assert3d('createShader');
85146 _main.default._validateParameters('createShader', arguments);
85147 return new _main.default.Shader(this._renderer, vertSrc, fragSrc);
85148 };
85149
85150 /**
85151 * The <a href="#/p5/shader">shader()</a> function lets the user provide a custom shader
85152 * to fill in shapes in WEBGL mode. Users can create their
85153 * own shaders by loading vertex and fragment shaders with
85154 * <a href="#/p5/loadShader">loadShader()</a>.
85155 *
85156 * @method shader
85157 * @chainable
85158 * @param {p5.Shader} [s] the desired <a href="#/p5.Shader">p5.Shader</a> to use for rendering
85159 * shapes.
85160 *
85161 * @example
85162 * <div modernizr='webgl'>
85163 * <code>
85164 * // Click within the image to toggle
85165 * // the shader used by the quad shape
85166 * // Note: for an alternative approach to the same example,
85167 * // involving changing uniforms please refer to:
85168 * // https://p5js.org/reference/#/p5.Shader/setUniform
85169 *
85170 * let redGreen;
85171 * let orangeBlue;
85172 * let showRedGreen = false;
85173 *
85174 * function preload() {
85175 * // note that we are using two instances
85176 * // of the same vertex and fragment shaders
85177 * redGreen = loadShader('assets/shader.vert', 'assets/shader-gradient.frag');
85178 * orangeBlue = loadShader('assets/shader.vert', 'assets/shader-gradient.frag');
85179 * }
85180 *
85181 * function setup() {
85182 * createCanvas(100, 100, WEBGL);
85183 *
85184 * // initialize the colors for redGreen shader
85185 * shader(redGreen);
85186 * redGreen.setUniform('colorCenter', [1.0, 0.0, 0.0]);
85187 * redGreen.setUniform('colorBackground', [0.0, 1.0, 0.0]);
85188 *
85189 * // initialize the colors for orangeBlue shader
85190 * shader(orangeBlue);
85191 * orangeBlue.setUniform('colorCenter', [1.0, 0.5, 0.0]);
85192 * orangeBlue.setUniform('colorBackground', [0.226, 0.0, 0.615]);
85193 *
85194 * noStroke();
85195 * }
85196 *
85197 * function draw() {
85198 * // update the offset values for each shader,
85199 * // moving orangeBlue in vertical and redGreen
85200 * // in horizontal direction
85201 * orangeBlue.setUniform('offset', [0, sin(millis() / 2000) + 1]);
85202 * redGreen.setUniform('offset', [sin(millis() / 2000), 1]);
85203 *
85204 * if (showRedGreen === true) {
85205 * shader(redGreen);
85206 * } else {
85207 * shader(orangeBlue);
85208 * }
85209 * quad(-1, -1, 1, -1, 1, 1, -1, 1);
85210 * }
85211 *
85212 * function mouseClicked() {
85213 * showRedGreen = !showRedGreen;
85214 * }
85215 * </code>
85216 * </div>
85217 *
85218 * @alt
85219 * canvas toggles between a circular gradient of orange and blue vertically. and a circular gradient of red and green moving horizontally when mouse is clicked/pressed.
85220 */
85221 _main.default.prototype.shader = function(s) {
85222 this._assert3d('shader');
85223 _main.default._validateParameters('shader', arguments);
85224
85225 if (s._renderer === undefined) {
85226 s._renderer = this._renderer;
85227 }
85228
85229 if (s.isStrokeShader()) {
85230 this._renderer.userStrokeShader = s;
85231 } else {
85232 this._renderer.userFillShader = s;
85233 this._renderer._useNormalMaterial = false;
85234 }
85235
85236 s.init();
85237
85238 return this;
85239 };
85240
85241 /**
85242 * This function restores the default shaders in WEBGL mode. Code that runs
85243 * after resetShader() will not be affected by previously defined
85244 * shaders. Should be run after <a href="#/p5/shader">shader()</a>.
85245 *
85246 * @method resetShader
85247 * @chainable
85248 */
85249 _main.default.prototype.resetShader = function() {
85250 this._renderer.userFillShader = this._renderer.userStrokeShader = null;
85251 return this;
85252 };
85253
85254 /**
85255 * Normal material for geometry is a material that is not affected by light.
85256 * It is not reflective and is a placeholder material often used for debugging.
85257 * Surfaces facing the X-axis, become red, those facing the Y-axis, become green and those facing the Z-axis, become blue.
85258 * You can view all possible materials in this
85259 * <a href="https://p5js.org/examples/3d-materials.html">example</a>.
85260 * @method normalMaterial
85261 * @chainable
85262 * @example
85263 * <div>
85264 * <code>
85265 * function setup() {
85266 * createCanvas(100, 100, WEBGL);
85267 * }
85268 *
85269 * function draw() {
85270 * background(200);
85271 * normalMaterial();
85272 * sphere(40);
85273 * }
85274 * </code>
85275 * </div>
85276 * @alt
85277 * Red, green and blue gradient.
85278 */
85279 _main.default.prototype.normalMaterial = function() {
85280 this._assert3d('normalMaterial');
85281 for (
85282 var _len = arguments.length, args = new Array(_len), _key = 0;
85283 _key < _len;
85284 _key++
85285 ) {
85286 args[_key] = arguments[_key];
85287 }
85288 _main.default._validateParameters('normalMaterial', args);
85289 this._renderer.drawMode = constants.FILL;
85290 this._renderer._useSpecularMaterial = false;
85291 this._renderer._useEmissiveMaterial = false;
85292 this._renderer._useNormalMaterial = true;
85293 this._renderer.curFillColor = [1, 1, 1, 1];
85294 this._renderer._setProperty('_doFill', true);
85295 this.noStroke();
85296 return this;
85297 };
85298
85299 /**
85300 * Texture for geometry. You can view other possible materials in this
85301 * <a href="https://p5js.org/examples/3d-materials.html">example</a>.
85302 * @method texture
85303 * @param {p5.Image|p5.MediaElement|p5.Graphics} tex 2-dimensional graphics
85304 * to render as texture
85305 * @chainable
85306 * @example
85307 * <div>
85308 * <code>
85309 * let img;
85310 * function preload() {
85311 * img = loadImage('assets/laDefense.jpg');
85312 * }
85313 *
85314 * function setup() {
85315 * createCanvas(100, 100, WEBGL);
85316 * }
85317 *
85318 * function draw() {
85319 * background(0);
85320 * rotateZ(frameCount * 0.01);
85321 * rotateX(frameCount * 0.01);
85322 * rotateY(frameCount * 0.01);
85323 * //pass image as texture
85324 * texture(img);
85325 * box(200, 200, 200);
85326 * }
85327 * </code>
85328 * </div>
85329 *
85330 * <div>
85331 * <code>
85332 * let pg;
85333 *
85334 * function setup() {
85335 * createCanvas(100, 100, WEBGL);
85336 * pg = createGraphics(200, 200);
85337 * pg.textSize(75);
85338 * }
85339 *
85340 * function draw() {
85341 * background(0);
85342 * pg.background(255);
85343 * pg.text('hello!', 0, 100);
85344 * //pass image as texture
85345 * texture(pg);
85346 * rotateX(0.5);
85347 * noStroke();
85348 * plane(50);
85349 * }
85350 * </code>
85351 * </div>
85352 *
85353 * <div>
85354 * <code>
85355 * let vid;
85356 * function preload() {
85357 * vid = createVideo('assets/fingers.mov');
85358 * vid.hide();
85359 * }
85360 * function setup() {
85361 * createCanvas(100, 100, WEBGL);
85362 * }
85363 *
85364 * function draw() {
85365 * background(0);
85366 * //pass video frame as texture
85367 * texture(vid);
85368 * rect(-40, -40, 80, 80);
85369 * }
85370 *
85371 * function mousePressed() {
85372 * vid.loop();
85373 * }
85374 * </code>
85375 * </div>
85376 *
85377 * @alt
85378 * Rotating view of many images umbrella and grid roof on a 3d plane
85379 * black canvas
85380 * black canvas
85381 */
85382 _main.default.prototype.texture = function(tex) {
85383 this._assert3d('texture');
85384 _main.default._validateParameters('texture', arguments);
85385 if (tex.gifProperties) {
85386 tex._animateGif(this);
85387 }
85388
85389 this._renderer.drawMode = constants.TEXTURE;
85390 this._renderer._useSpecularMaterial = false;
85391 this._renderer._useEmissiveMaterial = false;
85392 this._renderer._useNormalMaterial = false;
85393 this._renderer._tex = tex;
85394 this._renderer._setProperty('_doFill', true);
85395
85396 return this;
85397 };
85398
85399 /**
85400 * Sets the coordinate space for texture mapping. The default mode is IMAGE
85401 * which refers to the actual coordinates of the image.
85402 * NORMAL refers to a normalized space of values ranging from 0 to 1.
85403 * This function only works in WEBGL mode.
85404 *
85405 * With IMAGE, if an image is 100 x 200 pixels, mapping the image onto the entire
85406 * size of a quad would require the points (0,0) (100, 0) (100,200) (0,200).
85407 * The same mapping in NORMAL is (0,0) (1,0) (1,1) (0,1).
85408 * @method textureMode
85409 * @param {Constant} mode either IMAGE or NORMAL
85410 * @example
85411 * <div>
85412 * <code>
85413 * let img;
85414 *
85415 * function preload() {
85416 * img = loadImage('assets/laDefense.jpg');
85417 * }
85418 *
85419 * function setup() {
85420 * createCanvas(100, 100, WEBGL);
85421 * }
85422 *
85423 * function draw() {
85424 * texture(img);
85425 * textureMode(NORMAL);
85426 * beginShape();
85427 * vertex(-50, -50, 0, 0);
85428 * vertex(50, -50, 1, 0);
85429 * vertex(50, 50, 1, 1);
85430 * vertex(-50, 50, 0, 1);
85431 * endShape();
85432 * }
85433 * </code>
85434 * </div>
85435 *
85436 * @alt
85437 * the underside of a white umbrella and gridded ceiling above
85438 *
85439 * <div>
85440 * <code>
85441 * let img;
85442 *
85443 * function preload() {
85444 * img = loadImage('assets/laDefense.jpg');
85445 * }
85446 *
85447 * function setup() {
85448 * createCanvas(100, 100, WEBGL);
85449 * }
85450 *
85451 * function draw() {
85452 * texture(img);
85453 * textureMode(NORMAL);
85454 * beginShape();
85455 * vertex(-50, -50, 0, 0);
85456 * vertex(50, -50, img.width, 0);
85457 * vertex(50, 50, img.width, img.height);
85458 * vertex(-50, 50, 0, img.height);
85459 * endShape();
85460 * }
85461 * </code>
85462 * </div>
85463 *
85464 * @alt
85465 * the underside of a white umbrella and gridded ceiling above
85466 */
85467 _main.default.prototype.textureMode = function(mode) {
85468 if (mode !== constants.IMAGE && mode !== constants.NORMAL) {
85469 console.warn(
85470 'You tried to set '.concat(
85471 mode,
85472 ' textureMode only supports IMAGE & NORMAL '
85473 )
85474 );
85475 } else {
85476 this._renderer.textureMode = mode;
85477 }
85478 };
85479
85480 /**
85481 * Sets the global texture wrapping mode. This controls how textures behave
85482 * when their uv's go outside of the 0 - 1 range. There are three options:
85483 * CLAMP, REPEAT, and MIRROR.
85484 *
85485 * CLAMP causes the pixels at the edge of the texture to extend to the bounds
85486 * REPEAT causes the texture to tile repeatedly until reaching the bounds
85487 * MIRROR works similarly to REPEAT but it flips the texture with every new tile
85488 *
85489 * REPEAT & MIRROR are only available if the texture
85490 * is a power of two size (128, 256, 512, 1024, etc.).
85491 *
85492 * This method will affect all textures in your sketch until a subsequent
85493 * textureWrap call is made.
85494 *
85495 * If only one argument is provided, it will be applied to both the
85496 * horizontal and vertical axes.
85497 * @method textureWrap
85498 * @param {Constant} wrapX either CLAMP, REPEAT, or MIRROR
85499 * @param {Constant} [wrapY] either CLAMP, REPEAT, or MIRROR
85500 * @example
85501 * <div>
85502 * <code>
85503 * let img;
85504 * function preload() {
85505 * img = loadImage('assets/rockies128.jpg');
85506 * }
85507 *
85508 * function setup() {
85509 * createCanvas(100, 100, WEBGL);
85510 * textureWrap(MIRROR);
85511 * }
85512 *
85513 * function draw() {
85514 * background(0);
85515 *
85516 * let dX = mouseX;
85517 * let dY = mouseY;
85518 *
85519 * let u = lerp(1.0, 2.0, dX);
85520 * let v = lerp(1.0, 2.0, dY);
85521 *
85522 * scale(width / 2);
85523 *
85524 * texture(img);
85525 *
85526 * beginShape(TRIANGLES);
85527 * vertex(-1, -1, 0, 0, 0);
85528 * vertex(1, -1, 0, u, 0);
85529 * vertex(1, 1, 0, u, v);
85530 *
85531 * vertex(1, 1, 0, u, v);
85532 * vertex(-1, 1, 0, 0, v);
85533 * vertex(-1, -1, 0, 0, 0);
85534 * endShape();
85535 * }
85536 * </code>
85537 * </div>
85538 *
85539 * @alt
85540 * an image of the rocky mountains repeated in mirrored tiles
85541 */
85542 _main.default.prototype.textureWrap = function(wrapX) {
85543 var wrapY =
85544 arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : wrapX;
85545 this._renderer.textureWrapX = wrapX;
85546 this._renderer.textureWrapY = wrapY;
85547
85548 var textures = this._renderer.textures;
85549 for (var i = 0; i < textures.length; i++) {
85550 textures[i].setWrapMode(wrapX, wrapY);
85551 }
85552 };
85553
85554 /**
85555 * Ambient material for geometry with a given color. Ambient material defines the color the object reflects under any lighting.
85556 * For example, if the ambient material of an object is pure red, but the ambient lighting only contains green, the object will not reflect any light.
85557 * Here's an <a href="https://p5js.org/examples/3d-materials.html">example containing all possible materials</a>.
85558 * @method ambientMaterial
85559 * @param {Number} v1 gray value, red or hue value
85560 * (depending on the current color mode),
85561 * @param {Number} [v2] green or saturation value
85562 * @param {Number} [v3] blue or brightness value
85563 * @chainable
85564 * @example
85565 * <div>
85566 * <code>
85567 * function setup() {
85568 * createCanvas(100, 100, WEBGL);
85569 * }
85570 * function draw() {
85571 * background(0);
85572 * noStroke();
85573 * ambientLight(200);
85574 * ambientMaterial(70, 130, 230);
85575 * sphere(40);
85576 * }
85577 * </code>
85578 * </div>
85579 * <div>
85580 * <code>
85581 * // ambientLight is both red and blue (magenta),
85582 * // so object only reflects it's red and blue components
85583 * function setup() {
85584 * createCanvas(100, 100, WEBGL);
85585 * }
85586 * function draw() {
85587 * background(70);
85588 * ambientLight(100); // white light
85589 * ambientMaterial(255, 0, 255); // pink material
85590 * box(30);
85591 * }
85592 * </code>
85593 * </div>
85594 * <div>
85595 * <code>
85596 * // ambientLight is green. Since object does not contain
85597 * // green, it does not reflect any light
85598 * function setup() {
85599 * createCanvas(100, 100, WEBGL);
85600 * }
85601 * function draw() {
85602 * background(70);
85603 * ambientLight(0, 255, 0); // green light
85604 * ambientMaterial(255, 0, 255); // pink material
85605 * box(30);
85606 * }
85607 * </code>
85608 * </div>
85609 * @alt
85610 * radiating light source from top right of canvas
85611 * box reflecting only red and blue light
85612 * box reflecting no light
85613 */
85614 /**
85615 * @method ambientMaterial
85616 * @param {Number[]|String|p5.Color} color color, color Array, or CSS color string
85617 * @chainable
85618 */
85619 _main.default.prototype.ambientMaterial = function(v1, v2, v3) {
85620 this._assert3d('ambientMaterial');
85621 _main.default._validateParameters('ambientMaterial', arguments);
85622
85623 var color = _main.default.prototype.color.apply(this, arguments);
85624 this._renderer.curFillColor = color._array;
85625 this._renderer._useSpecularMaterial = false;
85626 this._renderer._useEmissiveMaterial = false;
85627 this._renderer._useNormalMaterial = false;
85628 this._renderer._enableLighting = true;
85629 this._renderer._tex = null;
85630
85631 return this;
85632 };
85633
85634 /**
85635 * Sets the emissive color of the material used for geometry drawn to
85636 * the screen. This is a misnomer in the sense that the material does not
85637 * actually emit light that effects surrounding polygons. Instead,
85638 * it gives the appearance that the object is glowing. An emissive material
85639 * will display at full strength even if there is no light for it to reflect.
85640 * @method emissiveMaterial
85641 * @param {Number} v1 gray value, red or hue value
85642 * (depending on the current color mode),
85643 * @param {Number} [v2] green or saturation value
85644 * @param {Number} [v3] blue or brightness value
85645 * @param {Number} [a] opacity
85646 * @chainable
85647 * @example
85648 * <div>
85649 * <code>
85650 * function setup() {
85651 * createCanvas(100, 100, WEBGL);
85652 * }
85653 * function draw() {
85654 * background(0);
85655 * noStroke();
85656 * ambientLight(0);
85657 * emissiveMaterial(130, 230, 0);
85658 * sphere(40);
85659 * }
85660 * </code>
85661 * </div>
85662 *
85663 * @alt
85664 * radiating light source from top right of canvas
85665 */
85666 /**
85667 * @method emissiveMaterial
85668 * @param {Number[]|String|p5.Color} color color, color Array, or CSS color string
85669 * @chainable
85670 */
85671 _main.default.prototype.emissiveMaterial = function(v1, v2, v3, a) {
85672 this._assert3d('emissiveMaterial');
85673 _main.default._validateParameters('emissiveMaterial', arguments);
85674
85675 var color = _main.default.prototype.color.apply(this, arguments);
85676 this._renderer.curFillColor = color._array;
85677 this._renderer._useSpecularMaterial = false;
85678 this._renderer._useEmissiveMaterial = true;
85679 this._renderer._useNormalMaterial = false;
85680 this._renderer._enableLighting = true;
85681 this._renderer._tex = null;
85682
85683 return this;
85684 };
85685
85686 /**
85687 * Specular material for geometry with a given color. Specular material is a shiny reflective material.
85688 * Like ambient material it also defines the color the object reflects under ambient lighting.
85689 * For example, if the specular material of an object is pure red, but the ambient lighting only contains green, the object will not reflect any light.
85690 * For all other types of light like point and directional light, a specular material will reflect the color of the light source to the viewer.
85691 * Here's an <a href="https://p5js.org/examples/3d-materials.html">example containing all possible materials</a>.
85692 *
85693 * @method specularMaterial
85694 * @param {Number} gray number specifying value between white and black.
85695 * @param {Number} [alpha] alpha value relative to current color range
85696 * (default is 0-255)
85697 * @chainable
85698 */
85699
85700 /**
85701 * @method specularMaterial
85702 * @param {Number} v1 red or hue value relative to
85703 * the current color range
85704 * @param {Number} v2 green or saturation value
85705 * relative to the current color range
85706 * @param {Number} v3 blue or brightness value
85707 * relative to the current color range
85708 * @param {Number} [alpha]
85709 * @chainable
85710 *
85711 * @example
85712 * <div>
85713 * <code>
85714 * function setup() {
85715 * createCanvas(100, 100, WEBGL);
85716 * }
85717 * function draw() {
85718 * background(0);
85719 * ambientLight(50);
85720 * pointLight(250, 250, 250, 100, 100, 30);
85721 * specularMaterial(250);
85722 * sphere(40);
85723 * }
85724 * </code>
85725 * </div>
85726 * @alt
85727 * diffused radiating light source from top right of canvas
85728 */
85729
85730 /**
85731 * @method specularMaterial
85732 * @param {Number[]|String|p5.Color} color color Array, or CSS color string
85733 * @chainable
85734 */
85735 _main.default.prototype.specularMaterial = function(v1, v2, v3, alpha) {
85736 this._assert3d('specularMaterial');
85737 _main.default._validateParameters('specularMaterial', arguments);
85738
85739 var color = _main.default.prototype.color.apply(this, arguments);
85740 this._renderer.curFillColor = color._array;
85741 this._renderer._useSpecularMaterial = true;
85742 this._renderer._useEmissiveMaterial = false;
85743 this._renderer._useNormalMaterial = false;
85744 this._renderer._enableLighting = true;
85745 this._renderer._tex = null;
85746
85747 return this;
85748 };
85749
85750 /**
85751 * Sets the amount of gloss in the surface of shapes.
85752 * Used in combination with specularMaterial() in setting
85753 * the material properties of shapes. The default and minimum value is 1.
85754 * @method shininess
85755 * @param {Number} shine Degree of Shininess.
85756 * Defaults to 1.
85757 * @chainable
85758 * @example
85759 * <div>
85760 * <code>
85761 * function setup() {
85762 * createCanvas(100, 100, WEBGL);
85763 * }
85764 * function draw() {
85765 * background(0);
85766 * noStroke();
85767 * let locX = mouseX - width / 2;
85768 * let locY = mouseY - height / 2;
85769 * ambientLight(60, 60, 60);
85770 * pointLight(255, 255, 255, locX, locY, 50);
85771 * specularMaterial(250);
85772 * translate(-25, 0, 0);
85773 * shininess(1);
85774 * sphere(20);
85775 * translate(50, 0, 0);
85776 * shininess(20);
85777 * sphere(20);
85778 * }
85779 * </code>
85780 * </div>
85781 * @alt
85782 * Shininess on Camera changes position with mouse
85783 */
85784 _main.default.prototype.shininess = function(shine) {
85785 this._assert3d('shininess');
85786 _main.default._validateParameters('shininess', arguments);
85787
85788 if (shine < 1) {
85789 shine = 1;
85790 }
85791 this._renderer._useShininess = shine;
85792 return this;
85793 };
85794
85795 /**
85796 * @private blends colors according to color components.
85797 * If alpha value is less than 1, or non-standard blendMode
85798 * we need to enable blending on our gl context.
85799 * @param {Number[]} color [description]
85800 * @return {Number[]]} Normalized numbers array
85801 */
85802 _main.default.RendererGL.prototype._applyColorBlend = function(colors) {
85803 var gl = this.GL;
85804
85805 var isTexture = this.drawMode === constants.TEXTURE;
85806 var doBlend = isTexture || colors[colors.length - 1] < 1.0 || this._isErasing;
85807
85808 if (doBlend !== this._isBlending) {
85809 if (
85810 doBlend ||
85811 (this.curBlendMode !== constants.BLEND &&
85812 this.curBlendMode !== constants.ADD)
85813 ) {
85814 gl.enable(gl.BLEND);
85815 } else {
85816 gl.disable(gl.BLEND);
85817 }
85818 gl.depthMask(true);
85819 this._isBlending = doBlend;
85820 }
85821 this._applyBlendMode();
85822 return colors;
85823 };
85824
85825 /**
85826 * @private sets blending in gl context to curBlendMode
85827 * @param {Number[]} color [description]
85828 * @return {Number[]]} Normalized numbers array
85829 */
85830 _main.default.RendererGL.prototype._applyBlendMode = function() {
85831 if (this._cachedBlendMode === this.curBlendMode) {
85832 return;
85833 }
85834 var gl = this.GL;
85835 switch (this.curBlendMode) {
85836 case constants.BLEND:
85837 case constants.ADD:
85838 gl.blendEquation(gl.FUNC_ADD);
85839 gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
85840 break;
85841 case constants.REMOVE:
85842 gl.blendEquation(gl.FUNC_REVERSE_SUBTRACT);
85843 gl.blendFunc(gl.SRC_ALPHA, gl.DST_ALPHA);
85844 break;
85845 case constants.MULTIPLY:
85846 gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);
85847 gl.blendFuncSeparate(gl.ZERO, gl.SRC_COLOR, gl.ONE, gl.ONE);
85848 break;
85849 case constants.SCREEN:
85850 gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);
85851 gl.blendFuncSeparate(gl.ONE_MINUS_DST_COLOR, gl.ONE, gl.ONE, gl.ONE);
85852 break;
85853 case constants.EXCLUSION:
85854 gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);
85855 gl.blendFuncSeparate(
85856 gl.ONE_MINUS_DST_COLOR,
85857 gl.ONE_MINUS_SRC_COLOR,
85858 gl.ONE,
85859 gl.ONE
85860 );
85861
85862 break;
85863 case constants.REPLACE:
85864 gl.blendEquation(gl.FUNC_ADD);
85865 gl.blendFunc(gl.ONE, gl.ZERO);
85866 break;
85867 case constants.SUBTRACT:
85868 gl.blendEquationSeparate(gl.FUNC_REVERSE_SUBTRACT, gl.FUNC_ADD);
85869 gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE, gl.ONE, gl.ONE);
85870 break;
85871 case constants.DARKEST:
85872 if (this.blendExt) {
85873 gl.blendEquationSeparate(this.blendExt.MIN_EXT, gl.FUNC_ADD);
85874 gl.blendFuncSeparate(gl.ONE, gl.ONE, gl.ONE, gl.ONE);
85875 } else {
85876 console.warn(
85877 'blendMode(DARKEST) does not work in your browser in WEBGL mode.'
85878 );
85879 }
85880 break;
85881 case constants.LIGHTEST:
85882 if (this.blendExt) {
85883 gl.blendEquationSeparate(this.blendExt.MAX_EXT, gl.FUNC_ADD);
85884 gl.blendFuncSeparate(gl.ONE, gl.ONE, gl.ONE, gl.ONE);
85885 } else {
85886 console.warn(
85887 'blendMode(LIGHTEST) does not work in your browser in WEBGL mode.'
85888 );
85889 }
85890 break;
85891 default:
85892 console.error(
85893 'Oops! Somehow RendererGL set curBlendMode to an unsupported mode.'
85894 );
85895
85896 break;
85897 }
85898
85899 if (!this._isErasing) {
85900 this._cachedBlendMode = this.curBlendMode;
85901 }
85902 };
85903 var _default = _main.default;
85904 exports.default = _default;
85905 },
85906 { '../core/constants': 43, '../core/main': 54, './p5.Texture': 110 }
85907 ],
85908 102: [
85909 function(_dereq_, module, exports) {
85910 'use strict';
85911 Object.defineProperty(exports, '__esModule', { value: true });
85912 exports.default = void 0;
85913
85914 var _main = _interopRequireDefault(_dereq_('../core/main'));
85915 function _interopRequireDefault(obj) {
85916 return obj && obj.__esModule ? obj : { default: obj };
85917 } /** ////////////////////////////////////////////////////////////////////////////////
85918 * @module Lights, Camera
85919 * @submodule Camera
85920 * @requires core
85921 */
85922 // p5.Prototype Methods
85923 ////////////////////////////////////////////////////////////////////////////////
85924 /**
85925 * Sets the camera position for a 3D sketch. Parameters for this function define
85926 * the position for the camera, the center of the sketch (where the camera is
85927 * pointing), and an up direction (the orientation of the camera).
85928 *
85929 * This function simulates the movements of the camera, allowing objects to be
85930 * viewed from various angles. Remember, it does not move the objects themselves
85931 * but the camera instead. For example when centerX value is positive, the camera
85932 * is rotating to the right side of the sketch, so the object would seem like
85933 * moving to the left.
85934 *
85935 * See this <a href = "https://www.openprocessing.org/sketch/740258">example</a>
85936 * to view the position of your camera.
85937 *
85938 * When called with no arguments, this function creates a default camera
85939 * equivalent to
85940 * camera(0, 0, (height/2.0) / tan(PI*30.0 / 180.0), 0, 0, 0, 0, 1, 0);
85941 * @method camera
85942 * @constructor
85943 * @for p5
85944 * @param {Number} [x] camera position value on x axis
85945 * @param {Number} [y] camera position value on y axis
85946 * @param {Number} [z] camera position value on z axis
85947 * @param {Number} [centerX] x coordinate representing center of the sketch
85948 * @param {Number} [centerY] y coordinate representing center of the sketch
85949 * @param {Number} [centerZ] z coordinate representing center of the sketch
85950 * @param {Number} [upX] x component of direction 'up' from camera
85951 * @param {Number} [upY] y component of direction 'up' from camera
85952 * @param {Number} [upZ] z component of direction 'up' from camera
85953 * @chainable
85954 * @example
85955 * <div>
85956 * <code>
85957 * function setup() {
85958 * createCanvas(100, 100, WEBGL);
85959 * }
85960 * function draw() {
85961 * background(204);
85962 * //move the camera away from the plane by a sin wave
85963 * camera(0, 0, 20 + sin(frameCount * 0.01) * 10, 0, 0, 0, 0, 1, 0);
85964 * plane(10, 10);
85965 * }
85966 * </code>
85967 * </div>
85968 *
85969 * @example
85970 * <div>
85971 * <code>
85972 * //move slider to see changes!
85973 * //sliders control the first 6 parameters of camera()
85974 * let sliderGroup = [];
85975 * let X;
85976 * let Y;
85977 * let Z;
85978 * let centerX;
85979 * let centerY;
85980 * let centerZ;
85981 * let h = 20;
85982 *
85983 * function setup() {
85984 * createCanvas(100, 100, WEBGL);
85985 * //create sliders
85986 * for (var i = 0; i < 6; i++) {
85987 * if (i === 2) {
85988 * sliderGroup[i] = createSlider(10, 400, 200);
85989 * } else {
85990 * sliderGroup[i] = createSlider(-400, 400, 0);
85991 * }
85992 * h = map(i, 0, 6, 5, 85);
85993 * sliderGroup[i].position(10, height + h);
85994 * sliderGroup[i].style('width', '80px');
85995 * }
85996 * }
85997 *
85998 * function draw() {
85999 * background(60);
86000 * // assigning sliders' value to each parameters
86001 * X = sliderGroup[0].value();
86002 * Y = sliderGroup[1].value();
86003 * Z = sliderGroup[2].value();
86004 * centerX = sliderGroup[3].value();
86005 * centerY = sliderGroup[4].value();
86006 * centerZ = sliderGroup[5].value();
86007 * camera(X, Y, Z, centerX, centerY, centerZ, 0, 1, 0);
86008 * stroke(255);
86009 * fill(255, 102, 94);
86010 * box(85);
86011 * }
86012 * </code>
86013 * </div>
86014 * @alt
86015 * White square repeatedly grows to fill canvas and then shrinks.
86016 * An interactive example of a red cube with 3 sliders for moving it across x, y,
86017 * z axis and 3 sliders for shifting it's center.
86018 */ _main.default.prototype.camera = function() {
86019 var _this$_renderer$_curC;
86020 this._assert3d('camera');
86021 for (
86022 var _len = arguments.length, args = new Array(_len), _key = 0;
86023 _key < _len;
86024 _key++
86025 ) {
86026 args[_key] = arguments[_key];
86027 }
86028 _main.default._validateParameters('camera', args);
86029 (_this$_renderer$_curC = this._renderer._curCamera).camera.apply(
86030 _this$_renderer$_curC,
86031 args
86032 );
86033 return this;
86034 };
86035
86036 /**
86037 * Sets a perspective projection for the camera in a 3D sketch. This projection
86038 * represents depth through foreshortening: objects that are close to the camera
86039 * appear their actual size while those that are further away from the camera
86040 * appear smaller. The parameters to this function define the viewing frustum
86041 * (the truncated pyramid within which objects are seen by the camera) through
86042 * vertical field of view, aspect ratio (usually width/height), and near and far
86043 * clipping planes.
86044 *
86045 * When called with no arguments, the defaults
86046 * provided are equivalent to
86047 * perspective(PI/3.0, width/height, eyeZ/10.0, eyeZ*10.0), where eyeZ
86048 * is equal to ((height/2.0) / tan(PI*60.0/360.0));
86049 * @method perspective
86050 * @for p5
86051 * @param {Number} [fovy] camera frustum vertical field of view,
86052 * from bottom to top of view, in <a href="#/p5/angleMode">angleMode</a> units
86053 * @param {Number} [aspect] camera frustum aspect ratio
86054 * @param {Number} [near] frustum near plane length
86055 * @param {Number} [far] frustum far plane length
86056 * @chainable
86057 * @example
86058 * <div>
86059 * <code>
86060 * //drag the mouse to look around!
86061 * function setup() {
86062 * createCanvas(100, 100, WEBGL);
86063 * perspective(PI / 3.0, width / height, 0.1, 500);
86064 * }
86065 * function draw() {
86066 * background(200);
86067 * orbitControl();
86068 * normalMaterial();
86069 *
86070 * rotateX(-0.3);
86071 * rotateY(-0.2);
86072 * translate(0, 0, -50);
86073 *
86074 * push();
86075 * translate(-15, 0, sin(frameCount / 30) * 95);
86076 * box(30);
86077 * pop();
86078 * push();
86079 * translate(15, 0, sin(frameCount / 30 + PI) * 95);
86080 * box(30);
86081 * pop();
86082 * }
86083 * </code>
86084 * </div>
86085 *
86086 * @alt
86087 * two colored 3D boxes move back and forth, rotating as mouse is dragged.
86088 */
86089 _main.default.prototype.perspective = function() {
86090 var _this$_renderer$_curC2;
86091 this._assert3d('perspective');
86092 for (
86093 var _len2 = arguments.length, args = new Array(_len2), _key2 = 0;
86094 _key2 < _len2;
86095 _key2++
86096 ) {
86097 args[_key2] = arguments[_key2];
86098 }
86099 _main.default._validateParameters('perspective', args);
86100 (_this$_renderer$_curC2 = this._renderer._curCamera).perspective.apply(
86101 _this$_renderer$_curC2,
86102 args
86103 );
86104 return this;
86105 };
86106
86107 /**
86108 * Sets an orthographic projection for the camera in a 3D sketch and defines a
86109 * box-shaped viewing frustum within which objects are seen. In this projection,
86110 * all objects with the same dimension appear the same size, regardless of
86111 * whether they are near or far from the camera. The parameters to this
86112 * function specify the viewing frustum where left and right are the minimum and
86113 * maximum x values, top and bottom are the minimum and maximum y values, and near
86114 * and far are the minimum and maximum z values. If no parameters are given, the
86115 * default is used: ortho(-width/2, width/2, -height/2, height/2).
86116 * @method ortho
86117 * @for p5
86118 * @param {Number} [left] camera frustum left plane
86119 * @param {Number} [right] camera frustum right plane
86120 * @param {Number} [bottom] camera frustum bottom plane
86121 * @param {Number} [top] camera frustum top plane
86122 * @param {Number} [near] camera frustum near plane
86123 * @param {Number} [far] camera frustum far plane
86124 * @chainable
86125 * @example
86126 * <div>
86127 * <code>
86128 * //drag the mouse to look around!
86129 * //there's no vanishing point
86130 * function setup() {
86131 * createCanvas(100, 100, WEBGL);
86132 * ortho(-width / 2, width / 2, height / 2, -height / 2, 0, 500);
86133 * }
86134 * function draw() {
86135 * background(200);
86136 * orbitControl();
86137 * normalMaterial();
86138 *
86139 * rotateX(0.2);
86140 * rotateY(-0.2);
86141 * push();
86142 * translate(-15, 0, sin(frameCount / 30) * 65);
86143 * box(30);
86144 * pop();
86145 * push();
86146 * translate(15, 0, sin(frameCount / 30 + PI) * 65);
86147 * box(30);
86148 * pop();
86149 * }
86150 * </code>
86151 * </div>
86152 *
86153 * @alt
86154 * two 3D boxes move back and forth along same plane, rotating as mouse is dragged.
86155 */
86156 _main.default.prototype.ortho = function() {
86157 var _this$_renderer$_curC3;
86158 this._assert3d('ortho');
86159 for (
86160 var _len3 = arguments.length, args = new Array(_len3), _key3 = 0;
86161 _key3 < _len3;
86162 _key3++
86163 ) {
86164 args[_key3] = arguments[_key3];
86165 }
86166 _main.default._validateParameters('ortho', args);
86167 (_this$_renderer$_curC3 = this._renderer._curCamera).ortho.apply(
86168 _this$_renderer$_curC3,
86169 args
86170 );
86171 return this;
86172 };
86173
86174 /**
86175 * Sets a perspective matrix as defined by the parameters.
86176 *
86177 * A frustum is a geometric form: a pyramid with its top
86178 * cut off. With the viewer's eye at the imaginary top of
86179 * the pyramid, the six planes of the frustum act as clipping
86180 * planes when rendering a 3D view. Thus, any form inside the
86181 * clipping planes is visible; anything outside
86182 * those planes is not visible.
86183 *
86184 * Setting the frustum changes the perspective of the scene being rendered.
86185 * This can be achieved more simply in many cases by using
86186 * <a href="https://p5js.org/reference/#/p5/perspective">perspective()</a>.
86187 *
86188 * @method frustum
86189 * @for p5
86190 * @param {Number} [left] camera frustum left plane
86191 * @param {Number} [right] camera frustum right plane
86192 * @param {Number} [bottom] camera frustum bottom plane
86193 * @param {Number} [top] camera frustum top plane
86194 * @param {Number} [near] camera frustum near plane
86195 * @param {Number} [far] camera frustum far plane
86196 * @chainable
86197 * @example
86198 * <div>
86199 * <code>
86200 * function setup() {
86201 * createCanvas(100, 100, WEBGL);
86202 * setAttributes('antialias', true);
86203 * frustum(-0.1, 0.1, -0.1, 0.1, 0.1, 200);
86204 * }
86205 * function draw() {
86206 * background(200);
86207 * orbitControl();
86208 * strokeWeight(10);
86209 * stroke(0, 0, 255);
86210 * noFill();
86211 *
86212 * rotateY(-0.2);
86213 * rotateX(-0.3);
86214 * push();
86215 * translate(-15, 0, sin(frameCount / 30) * 25);
86216 * box(30);
86217 * pop();
86218 * push();
86219 * translate(15, 0, sin(frameCount / 30 + PI) * 25);
86220 * box(30);
86221 * pop();
86222 * }
86223 * </code>
86224 * </div>
86225 *
86226 * @alt
86227 * two 3D boxes move back and forth along same plane, rotating as mouse is dragged.
86228 */
86229 _main.default.prototype.frustum = function() {
86230 var _this$_renderer$_curC4;
86231 this._assert3d('frustum');
86232 for (
86233 var _len4 = arguments.length, args = new Array(_len4), _key4 = 0;
86234 _key4 < _len4;
86235 _key4++
86236 ) {
86237 args[_key4] = arguments[_key4];
86238 }
86239 _main.default._validateParameters('frustum', args);
86240 (_this$_renderer$_curC4 = this._renderer._curCamera).frustum.apply(
86241 _this$_renderer$_curC4,
86242 args
86243 );
86244 return this;
86245 };
86246
86247 ////////////////////////////////////////////////////////////////////////////////
86248 // p5.Camera
86249 ////////////////////////////////////////////////////////////////////////////////
86250
86251 /**
86252 * Creates a new <a href="#/p5.Camera">p5.Camera</a> object and tells the
86253 * renderer to use that camera.
86254 * Returns the p5.Camera object.
86255 * @method createCamera
86256 * @return {p5.Camera} The newly created camera object.
86257 * @for p5
86258 * @example
86259 * <div><code>
86260 * // Creates a camera object and animates it around a box.
86261 * let camera;
86262 * function setup() {
86263 * createCanvas(100, 100, WEBGL);
86264 * background(0);
86265 * camera = createCamera();
86266 * setCamera(camera);
86267 * }
86268 *
86269 * function draw() {
86270 * camera.lookAt(0, 0, 0);
86271 * camera.setPosition(sin(frameCount / 60) * 200, 0, 100);
86272 * box(20);
86273 * }
86274 * </code></div>
86275 *
86276 * @alt
86277 * An example that creates a camera and moves it around the box.
86278 */
86279 _main.default.prototype.createCamera = function() {
86280 this._assert3d('createCamera');
86281 var _cam = new _main.default.Camera(this._renderer);
86282
86283 // compute default camera settings, then set a default camera
86284 _cam._computeCameraDefaultSettings();
86285 _cam._setDefaultCamera();
86286
86287 // set renderer current camera to the new camera
86288 this._renderer._curCamera = _cam;
86289
86290 return _cam;
86291 };
86292
86293 /**
86294 * This class describes a camera for use in p5's
86295 * <a href="https://github.com/processing/p5.js/wiki/Getting-started-with-WebGL-in-p5">
86296 * WebGL mode</a>. It contains camera position, orientation, and projection
86297 * information necessary for rendering a 3D scene.
86298 *
86299 * New p5.Camera objects can be made through the
86300 * <a href="#/p5/createCamera">createCamera()</a> function and controlled through
86301 * the methods described below. A camera created in this way will use a default
86302 * position in the scene and a default perspective projection until these
86303 * properties are changed through the various methods available. It is possible
86304 * to create multiple cameras, in which case the current camera
86305 * can be set through the <a href="#/p5/setCamera">setCamera()</a> method.
86306 *
86307 * Note:
86308 * The methods below operate in two coordinate systems: the 'world' coordinate
86309 * system describe positions in terms of their relationship to the origin along
86310 * the X, Y and Z axes whereas the camera's 'local' coordinate system
86311 * describes positions from the camera's point of view: left-right, up-down,
86312 * and forward-backward. The <a href="#/p5.Camera/move">move()</a> method,
86313 * for instance, moves the camera along its own axes, whereas the
86314 * <a href="#/p5.Camera/setPosition">setPosition()</a>
86315 * method sets the camera's position in world-space.
86316 *
86317 * @class p5.Camera
86318 * @param {rendererGL} rendererGL instance of WebGL renderer
86319 * @example
86320 * <div>
86321 * <code>
86322 * let cam;
86323 * let delta = 0.01;
86324 *
86325 * function setup() {
86326 * createCanvas(100, 100, WEBGL);
86327 * normalMaterial();
86328 * cam = createCamera();
86329 * // set initial pan angle
86330 * cam.pan(-0.8);
86331 * }
86332 *
86333 * function draw() {
86334 * background(200);
86335 *
86336 * // pan camera according to angle 'delta'
86337 * cam.pan(delta);
86338 *
86339 * // every 160 frames, switch direction
86340 * if (frameCount % 160 === 0) {
86341 * delta *= -1;
86342 * }
86343 *
86344 * rotateX(frameCount * 0.01);
86345 * translate(-100, 0, 0);
86346 * box(20);
86347 * translate(35, 0, 0);
86348 * box(20);
86349 * translate(35, 0, 0);
86350 * box(20);
86351 * translate(35, 0, 0);
86352 * box(20);
86353 * translate(35, 0, 0);
86354 * box(20);
86355 * translate(35, 0, 0);
86356 * box(20);
86357 * translate(35, 0, 0);
86358 * box(20);
86359 * }
86360 * </code>
86361 * </div>
86362 *
86363 * @alt
86364 * camera view pans left and right across a series of rotating 3D boxes.
86365 */
86366 _main.default.Camera = function(renderer) {
86367 this._renderer = renderer;
86368
86369 this.cameraType = 'default';
86370
86371 this.cameraMatrix = new _main.default.Matrix();
86372 this.projMatrix = new _main.default.Matrix();
86373 };
86374
86375 ////////////////////////////////////////////////////////////////////////////////
86376 // Camera Projection Methods
86377 ////////////////////////////////////////////////////////////////////////////////
86378
86379 /**
86380 * Sets a perspective projection for a p5.Camera object and sets parameters
86381 * for that projection according to <a href="#/p5/perspective">perspective()</a>
86382 * syntax.
86383 * @method perspective
86384 * @for p5.Camera
86385 */
86386 _main.default.Camera.prototype.perspective = function(fovy, aspect, near, far) {
86387 this.cameraType = arguments.length > 0 ? 'custom' : 'default';
86388 if (typeof fovy === 'undefined') {
86389 fovy = this.defaultCameraFOV;
86390 // this avoids issue where setting angleMode(DEGREES) before calling
86391 // perspective leads to a smaller than expected FOV (because
86392 // _computeCameraDefaultSettings computes in radians)
86393 this.cameraFOV = fovy;
86394 } else {
86395 this.cameraFOV = this._renderer._pInst._toRadians(fovy);
86396 }
86397 if (typeof aspect === 'undefined') {
86398 aspect = this.defaultAspectRatio;
86399 }
86400 if (typeof near === 'undefined') {
86401 near = this.defaultCameraNear;
86402 }
86403 if (typeof far === 'undefined') {
86404 far = this.defaultCameraFar;
86405 }
86406
86407 if (near <= 0.0001) {
86408 near = 0.01;
86409 console.log(
86410 'Avoid perspective near plane values close to or below 0. ' +
86411 'Setting value to 0.01.'
86412 );
86413 }
86414
86415 if (far < near) {
86416 console.log(
86417 'Perspective far plane value is less than near plane value. ' +
86418 'Nothing will be shown.'
86419 );
86420 }
86421
86422 this.aspectRatio = aspect;
86423 this.cameraNear = near;
86424 this.cameraFar = far;
86425
86426 this.projMatrix = _main.default.Matrix.identity();
86427
86428 var f = 1.0 / Math.tan(this.cameraFOV / 2);
86429 var nf = 1.0 / (this.cameraNear - this.cameraFar);
86430
86431 // prettier-ignore
86432 this.projMatrix.set(f / aspect, 0, 0, 0,
86433 0, -f, 0, 0,
86434 0, 0, (far + near) * nf, -1,
86435 0, 0, 2 * far * near * nf, 0);
86436
86437 if (this._isActive()) {
86438 this._renderer.uPMatrix.set(
86439 this.projMatrix.mat4[0],
86440 this.projMatrix.mat4[1],
86441 this.projMatrix.mat4[2],
86442 this.projMatrix.mat4[3],
86443 this.projMatrix.mat4[4],
86444 this.projMatrix.mat4[5],
86445 this.projMatrix.mat4[6],
86446 this.projMatrix.mat4[7],
86447 this.projMatrix.mat4[8],
86448 this.projMatrix.mat4[9],
86449 this.projMatrix.mat4[10],
86450 this.projMatrix.mat4[11],
86451 this.projMatrix.mat4[12],
86452 this.projMatrix.mat4[13],
86453 this.projMatrix.mat4[14],
86454 this.projMatrix.mat4[15]
86455 );
86456 }
86457 };
86458
86459 /**
86460 * Sets an orthographic projection for a p5.Camera object and sets parameters
86461 * for that projection according to <a href="#/p5/ortho">ortho()</a> syntax.
86462 * @method ortho
86463 * @for p5.Camera
86464 */
86465 _main.default.Camera.prototype.ortho = function(
86466 left,
86467 right,
86468 bottom,
86469 top,
86470 near,
86471 far
86472 ) {
86473 if (left === undefined) left = -this._renderer.width / 2;
86474 if (right === undefined) right = +this._renderer.width / 2;
86475 if (bottom === undefined) bottom = -this._renderer.height / 2;
86476 if (top === undefined) top = +this._renderer.height / 2;
86477 if (near === undefined) near = 0;
86478 if (far === undefined)
86479 far = Math.max(this._renderer.width, this._renderer.height);
86480
86481 var w = right - left;
86482 var h = top - bottom;
86483 var d = far - near;
86484
86485 var x = +2.0 / w;
86486 var y = +2.0 / h;
86487 var z = -2.0 / d;
86488
86489 var tx = -(right + left) / w;
86490 var ty = -(top + bottom) / h;
86491 var tz = -(far + near) / d;
86492
86493 this.projMatrix = _main.default.Matrix.identity();
86494
86495 // prettier-ignore
86496 this.projMatrix.set(x, 0, 0, 0,
86497 0, -y, 0, 0,
86498 0, 0, z, 0,
86499 tx, ty, tz, 1);
86500
86501 if (this._isActive()) {
86502 this._renderer.uPMatrix.set(
86503 this.projMatrix.mat4[0],
86504 this.projMatrix.mat4[1],
86505 this.projMatrix.mat4[2],
86506 this.projMatrix.mat4[3],
86507 this.projMatrix.mat4[4],
86508 this.projMatrix.mat4[5],
86509 this.projMatrix.mat4[6],
86510 this.projMatrix.mat4[7],
86511 this.projMatrix.mat4[8],
86512 this.projMatrix.mat4[9],
86513 this.projMatrix.mat4[10],
86514 this.projMatrix.mat4[11],
86515 this.projMatrix.mat4[12],
86516 this.projMatrix.mat4[13],
86517 this.projMatrix.mat4[14],
86518 this.projMatrix.mat4[15]
86519 );
86520 }
86521
86522 this.cameraType = 'custom';
86523 };
86524
86525 /**
86526 * @method frustum
86527 * @for p5.Camera
86528 */
86529 _main.default.Camera.prototype.frustum = function(
86530 left,
86531 right,
86532 bottom,
86533 top,
86534 near,
86535 far
86536 ) {
86537 if (left === undefined) left = -this._renderer.width / 2;
86538 if (right === undefined) right = +this._renderer.width / 2;
86539 if (bottom === undefined) bottom = -this._renderer.height / 2;
86540 if (top === undefined) top = +this._renderer.height / 2;
86541 if (near === undefined) near = 0;
86542 if (far === undefined)
86543 far = Math.max(this._renderer.width, this._renderer.height);
86544
86545 var w = right - left;
86546 var h = top - bottom;
86547 var d = far - near;
86548
86549 var x = +(2.0 * near) / w;
86550 var y = +(2.0 * near) / h;
86551 var z = -(2.0 * far * near) / d;
86552
86553 var tx = (right + left) / w;
86554 var ty = (top + bottom) / h;
86555 var tz = -(far + near) / d;
86556
86557 this.projMatrix = _main.default.Matrix.identity();
86558
86559 // prettier-ignore
86560 this.projMatrix.set(x, 0, 0, 0,
86561 0, y, 0, 0,
86562 tx, ty, tz, -1,
86563 0, 0, z, 0);
86564
86565 if (this._isActive()) {
86566 this._renderer.uPMatrix.set(
86567 this.projMatrix.mat4[0],
86568 this.projMatrix.mat4[1],
86569 this.projMatrix.mat4[2],
86570 this.projMatrix.mat4[3],
86571 this.projMatrix.mat4[4],
86572 this.projMatrix.mat4[5],
86573 this.projMatrix.mat4[6],
86574 this.projMatrix.mat4[7],
86575 this.projMatrix.mat4[8],
86576 this.projMatrix.mat4[9],
86577 this.projMatrix.mat4[10],
86578 this.projMatrix.mat4[11],
86579 this.projMatrix.mat4[12],
86580 this.projMatrix.mat4[13],
86581 this.projMatrix.mat4[14],
86582 this.projMatrix.mat4[15]
86583 );
86584 }
86585
86586 this.cameraType = 'custom';
86587 };
86588
86589 ////////////////////////////////////////////////////////////////////////////////
86590 // Camera Orientation Methods
86591 ////////////////////////////////////////////////////////////////////////////////
86592
86593 /**
86594 * Rotate camera view about arbitrary axis defined by x,y,z
86595 * based on http://learnwebgl.brown37.net/07_cameras/camera_rotating_motion.html
86596 * @method _rotateView
86597 * @private
86598 */
86599 _main.default.Camera.prototype._rotateView = function(a, x, y, z) {
86600 var centerX = this.centerX;
86601 var centerY = this.centerY;
86602 var centerZ = this.centerZ;
86603
86604 // move center by eye position such that rotation happens around eye position
86605 centerX -= this.eyeX;
86606 centerY -= this.eyeY;
86607 centerZ -= this.eyeZ;
86608
86609 var rotation = _main.default.Matrix.identity(this._renderer._pInst);
86610 rotation.rotate(this._renderer._pInst._toRadians(a), x, y, z);
86611
86612 // prettier-ignore
86613 var rotatedCenter = [
86614 centerX * rotation.mat4[0] + centerY * rotation.mat4[4] + centerZ * rotation.mat4[8],
86615 centerX * rotation.mat4[1] + centerY * rotation.mat4[5] + centerZ * rotation.mat4[9],
86616 centerX * rotation.mat4[2] + centerY * rotation.mat4[6] + centerZ * rotation.mat4[10]];
86617
86618 // add eye position back into center
86619 rotatedCenter[0] += this.eyeX;
86620 rotatedCenter[1] += this.eyeY;
86621 rotatedCenter[2] += this.eyeZ;
86622
86623 this.camera(
86624 this.eyeX,
86625 this.eyeY,
86626 this.eyeZ,
86627 rotatedCenter[0],
86628 rotatedCenter[1],
86629 rotatedCenter[2],
86630 this.upX,
86631 this.upY,
86632 this.upZ
86633 );
86634 };
86635
86636 /**
86637 * Panning rotates the camera view to the left and right.
86638 * @method pan
86639 * @param {Number} angle amount to rotate camera in current
86640 * <a href="#/p5/angleMode">angleMode</a> units.
86641 * Greater than 0 values rotate counterclockwise (to the left).
86642 * @example
86643 * <div>
86644 * <code>
86645 * let cam;
86646 * let delta = 0.01;
86647 *
86648 * function setup() {
86649 * createCanvas(100, 100, WEBGL);
86650 * normalMaterial();
86651 * cam = createCamera();
86652 * // set initial pan angle
86653 * cam.pan(-0.8);
86654 * }
86655 *
86656 * function draw() {
86657 * background(200);
86658 *
86659 * // pan camera according to angle 'delta'
86660 * cam.pan(delta);
86661 *
86662 * // every 160 frames, switch direction
86663 * if (frameCount % 160 === 0) {
86664 * delta *= -1;
86665 * }
86666 *
86667 * rotateX(frameCount * 0.01);
86668 * translate(-100, 0, 0);
86669 * box(20);
86670 * translate(35, 0, 0);
86671 * box(20);
86672 * translate(35, 0, 0);
86673 * box(20);
86674 * translate(35, 0, 0);
86675 * box(20);
86676 * translate(35, 0, 0);
86677 * box(20);
86678 * translate(35, 0, 0);
86679 * box(20);
86680 * translate(35, 0, 0);
86681 * box(20);
86682 * }
86683 * </code>
86684 * </div>
86685 *
86686 * @alt
86687 * camera view pans left and right across a series of rotating 3D boxes.
86688 */
86689 _main.default.Camera.prototype.pan = function(amount) {
86690 var local = this._getLocalAxes();
86691 this._rotateView(amount, local.y[0], local.y[1], local.y[2]);
86692 };
86693
86694 /**
86695 * Tilting rotates the camera view up and down.
86696 * @method tilt
86697 * @param {Number} angle amount to rotate camera in current
86698 * <a href="#/p5/angleMode">angleMode</a> units.
86699 * Greater than 0 values rotate counterclockwise (to the left).
86700 * @example
86701 * <div>
86702 * <code>
86703 * let cam;
86704 * let delta = 0.01;
86705 *
86706 * function setup() {
86707 * createCanvas(100, 100, WEBGL);
86708 * normalMaterial();
86709 * cam = createCamera();
86710 * // set initial tilt
86711 * cam.tilt(-0.8);
86712 * }
86713 *
86714 * function draw() {
86715 * background(200);
86716 *
86717 * // pan camera according to angle 'delta'
86718 * cam.tilt(delta);
86719 *
86720 * // every 160 frames, switch direction
86721 * if (frameCount % 160 === 0) {
86722 * delta *= -1;
86723 * }
86724 *
86725 * rotateY(frameCount * 0.01);
86726 * translate(0, -100, 0);
86727 * box(20);
86728 * translate(0, 35, 0);
86729 * box(20);
86730 * translate(0, 35, 0);
86731 * box(20);
86732 * translate(0, 35, 0);
86733 * box(20);
86734 * translate(0, 35, 0);
86735 * box(20);
86736 * translate(0, 35, 0);
86737 * box(20);
86738 * translate(0, 35, 0);
86739 * box(20);
86740 * }
86741 * </code>
86742 * </div>
86743 *
86744 * @alt
86745 * camera view tilts up and down across a series of rotating 3D boxes.
86746 */
86747 _main.default.Camera.prototype.tilt = function(amount) {
86748 var local = this._getLocalAxes();
86749 this._rotateView(amount, local.x[0], local.x[1], local.x[2]);
86750 };
86751
86752 /**
86753 * Reorients the camera to look at a position in world space.
86754 * @method lookAt
86755 * @for p5.Camera
86756 * @param {Number} x x position of a point in world space
86757 * @param {Number} y y position of a point in world space
86758 * @param {Number} z z position of a point in world space
86759 * @example
86760 * <div>
86761 * <code>
86762 * let cam;
86763 *
86764 * function setup() {
86765 * createCanvas(100, 100, WEBGL);
86766 * normalMaterial();
86767 * cam = createCamera();
86768 * }
86769 *
86770 * function draw() {
86771 * background(200);
86772 *
86773 * // look at a new random point every 60 frames
86774 * if (frameCount % 60 === 0) {
86775 * cam.lookAt(random(-100, 100), random(-50, 50), 0);
86776 * }
86777 *
86778 * rotateX(frameCount * 0.01);
86779 * translate(-100, 0, 0);
86780 * box(20);
86781 * translate(35, 0, 0);
86782 * box(20);
86783 * translate(35, 0, 0);
86784 * box(20);
86785 * translate(35, 0, 0);
86786 * box(20);
86787 * translate(35, 0, 0);
86788 * box(20);
86789 * translate(35, 0, 0);
86790 * box(20);
86791 * translate(35, 0, 0);
86792 * box(20);
86793 * }
86794 * </code>
86795 * </div>
86796 *
86797 * @alt
86798 * camera view of rotating 3D cubes changes to look at a new random
86799 * point every second .
86800 */
86801 _main.default.Camera.prototype.lookAt = function(x, y, z) {
86802 this.camera(
86803 this.eyeX,
86804 this.eyeY,
86805 this.eyeZ,
86806 x,
86807 y,
86808 z,
86809 this.upX,
86810 this.upY,
86811 this.upZ
86812 );
86813 };
86814
86815 ////////////////////////////////////////////////////////////////////////////////
86816 // Camera Position Methods
86817 ////////////////////////////////////////////////////////////////////////////////
86818
86819 /**
86820 * Sets a camera's position and orientation. This is equivalent to calling
86821 * <a href="#/p5/camera">camera()</a> on a p5.Camera object.
86822 * @method camera
86823 * @for p5.Camera
86824 */
86825 _main.default.Camera.prototype.camera = function(
86826 eyeX,
86827 eyeY,
86828 eyeZ,
86829 centerX,
86830 centerY,
86831 centerZ,
86832 upX,
86833 upY,
86834 upZ
86835 ) {
86836 if (typeof eyeX === 'undefined') {
86837 eyeX = this.defaultEyeX;
86838 eyeY = this.defaultEyeY;
86839 eyeZ = this.defaultEyeZ;
86840 centerX = eyeX;
86841 centerY = eyeY;
86842 centerZ = 0;
86843 upX = 0;
86844 upY = 1;
86845 upZ = 0;
86846 }
86847
86848 this.eyeX = eyeX;
86849 this.eyeY = eyeY;
86850 this.eyeZ = eyeZ;
86851
86852 this.centerX = centerX;
86853 this.centerY = centerY;
86854 this.centerZ = centerZ;
86855
86856 this.upX = upX;
86857 this.upY = upY;
86858 this.upZ = upZ;
86859
86860 var local = this._getLocalAxes();
86861
86862 // the camera affects the model view matrix, insofar as it
86863 // inverse translates the world to the eye position of the camera
86864 // and rotates it.
86865 // prettier-ignore
86866 this.cameraMatrix.set(local.x[0], local.y[0], local.z[0], 0,
86867 local.x[1], local.y[1], local.z[1], 0,
86868 local.x[2], local.y[2], local.z[2], 0,
86869 0, 0, 0, 1);
86870
86871 var tx = -eyeX;
86872 var ty = -eyeY;
86873 var tz = -eyeZ;
86874
86875 this.cameraMatrix.translate([tx, ty, tz]);
86876
86877 if (this._isActive()) {
86878 this._renderer.uMVMatrix.set(
86879 this.cameraMatrix.mat4[0],
86880 this.cameraMatrix.mat4[1],
86881 this.cameraMatrix.mat4[2],
86882 this.cameraMatrix.mat4[3],
86883 this.cameraMatrix.mat4[4],
86884 this.cameraMatrix.mat4[5],
86885 this.cameraMatrix.mat4[6],
86886 this.cameraMatrix.mat4[7],
86887 this.cameraMatrix.mat4[8],
86888 this.cameraMatrix.mat4[9],
86889 this.cameraMatrix.mat4[10],
86890 this.cameraMatrix.mat4[11],
86891 this.cameraMatrix.mat4[12],
86892 this.cameraMatrix.mat4[13],
86893 this.cameraMatrix.mat4[14],
86894 this.cameraMatrix.mat4[15]
86895 );
86896 }
86897 return this;
86898 };
86899
86900 /**
86901 * Move camera along its local axes while maintaining current camera orientation.
86902 * @method move
86903 * @param {Number} x amount to move along camera's left-right axis
86904 * @param {Number} y amount to move along camera's up-down axis
86905 * @param {Number} z amount to move along camera's forward-backward axis
86906 * @example
86907 * <div>
86908 * <code>
86909 * // see the camera move along its own axes while maintaining its orientation
86910 * let cam;
86911 * let delta = 0.5;
86912 *
86913 * function setup() {
86914 * createCanvas(100, 100, WEBGL);
86915 * normalMaterial();
86916 * cam = createCamera();
86917 * }
86918 *
86919 * function draw() {
86920 * background(200);
86921 *
86922 * // move the camera along its local axes
86923 * cam.move(delta, delta, 0);
86924 *
86925 * // every 100 frames, switch direction
86926 * if (frameCount % 150 === 0) {
86927 * delta *= -1;
86928 * }
86929 *
86930 * translate(-10, -10, 0);
86931 * box(50, 8, 50);
86932 * translate(15, 15, 0);
86933 * box(50, 8, 50);
86934 * translate(15, 15, 0);
86935 * box(50, 8, 50);
86936 * translate(15, 15, 0);
86937 * box(50, 8, 50);
86938 * translate(15, 15, 0);
86939 * box(50, 8, 50);
86940 * translate(15, 15, 0);
86941 * box(50, 8, 50);
86942 * }
86943 * </code>
86944 * </div>
86945 *
86946 * @alt
86947 * camera view moves along a series of 3D boxes, maintaining the same
86948 * orientation throughout the move
86949 */
86950 _main.default.Camera.prototype.move = function(x, y, z) {
86951 var local = this._getLocalAxes();
86952
86953 // scale local axes by movement amounts
86954 // based on http://learnwebgl.brown37.net/07_cameras/camera_linear_motion.html
86955 var dx = [local.x[0] * x, local.x[1] * x, local.x[2] * x];
86956 var dy = [local.y[0] * y, local.y[1] * y, local.y[2] * y];
86957 var dz = [local.z[0] * z, local.z[1] * z, local.z[2] * z];
86958
86959 this.camera(
86960 this.eyeX + dx[0] + dy[0] + dz[0],
86961 this.eyeY + dx[1] + dy[1] + dz[1],
86962 this.eyeZ + dx[2] + dy[2] + dz[2],
86963 this.centerX + dx[0] + dy[0] + dz[0],
86964 this.centerY + dx[1] + dy[1] + dz[1],
86965 this.centerZ + dx[2] + dy[2] + dz[2],
86966 0,
86967 1,
86968 0
86969 );
86970 };
86971
86972 /**
86973 * Set camera position in world-space while maintaining current camera
86974 * orientation.
86975 * @method setPosition
86976 * @param {Number} x x position of a point in world space
86977 * @param {Number} y y position of a point in world space
86978 * @param {Number} z z position of a point in world space
86979 * @example
86980 * <div>
86981 * <code>
86982 * // press '1' '2' or '3' keys to set camera position
86983 *
86984 * let cam;
86985 *
86986 * function setup() {
86987 * createCanvas(100, 100, WEBGL);
86988 * normalMaterial();
86989 * cam = createCamera();
86990 * }
86991 *
86992 * function draw() {
86993 * background(200);
86994 *
86995 * // '1' key
86996 * if (keyIsDown(49)) {
86997 * cam.setPosition(30, 0, 80);
86998 * }
86999 * // '2' key
87000 * if (keyIsDown(50)) {
87001 * cam.setPosition(0, 0, 80);
87002 * }
87003 * // '3' key
87004 * if (keyIsDown(51)) {
87005 * cam.setPosition(-30, 0, 80);
87006 * }
87007 *
87008 * box(20);
87009 * }
87010 * </code>
87011 * </div>
87012 *
87013 * @alt
87014 * camera position changes as the user presses keys, altering view of a 3D box
87015 */
87016 _main.default.Camera.prototype.setPosition = function(x, y, z) {
87017 var diffX = x - this.eyeX;
87018 var diffY = y - this.eyeY;
87019 var diffZ = z - this.eyeZ;
87020
87021 this.camera(
87022 x,
87023 y,
87024 z,
87025 this.centerX + diffX,
87026 this.centerY + diffY,
87027 this.centerZ + diffZ,
87028 0,
87029 1,
87030 0
87031 );
87032 };
87033
87034 ////////////////////////////////////////////////////////////////////////////////
87035 // Camera Helper Methods
87036 ////////////////////////////////////////////////////////////////////////////////
87037
87038 // @TODO: combine this function with _setDefaultCamera to compute these values
87039 // as-needed
87040 _main.default.Camera.prototype._computeCameraDefaultSettings = function() {
87041 this.defaultCameraFOV = 60 / 180 * Math.PI;
87042 this.defaultAspectRatio = this._renderer.width / this._renderer.height;
87043 this.defaultEyeX = 0;
87044 this.defaultEyeY = 0;
87045 this.defaultEyeZ =
87046 this._renderer.height / 2.0 / Math.tan(this.defaultCameraFOV / 2.0);
87047 this.defaultCenterX = 0;
87048 this.defaultCenterY = 0;
87049 this.defaultCenterZ = 0;
87050 this.defaultCameraNear = this.defaultEyeZ * 0.1;
87051 this.defaultCameraFar = this.defaultEyeZ * 10;
87052 };
87053
87054 //detect if user didn't set the camera
87055 //then call this function below
87056 _main.default.Camera.prototype._setDefaultCamera = function() {
87057 this.cameraFOV = this.defaultCameraFOV;
87058 this.aspectRatio = this.defaultAspectRatio;
87059 this.eyeX = this.defaultEyeX;
87060 this.eyeY = this.defaultEyeY;
87061 this.eyeZ = this.defaultEyeZ;
87062 this.centerX = this.defaultCenterX;
87063 this.centerY = this.defaultCenterY;
87064 this.centerZ = this.defaultCenterZ;
87065 this.upX = 0;
87066 this.upY = 1;
87067 this.upZ = 0;
87068 this.cameraNear = this.defaultCameraNear;
87069 this.cameraFar = this.defaultCameraFar;
87070
87071 this.perspective();
87072 this.camera();
87073
87074 this.cameraType = 'default';
87075 };
87076
87077 _main.default.Camera.prototype._resize = function() {
87078 // If we're using the default camera, update the aspect ratio
87079 if (this.cameraType === 'default') {
87080 this._computeCameraDefaultSettings();
87081 this._setDefaultCamera();
87082 } else {
87083 this.perspective(
87084 this.cameraFOV,
87085 this._renderer.width / this._renderer.height
87086 );
87087 }
87088 };
87089
87090 /**
87091 * Returns a copy of a camera.
87092 * @method copy
87093 * @private
87094 */
87095 _main.default.Camera.prototype.copy = function() {
87096 var _cam = new _main.default.Camera(this._renderer);
87097 _cam.cameraFOV = this.cameraFOV;
87098 _cam.aspectRatio = this.aspectRatio;
87099 _cam.eyeX = this.eyeX;
87100 _cam.eyeY = this.eyeY;
87101 _cam.eyeZ = this.eyeZ;
87102 _cam.centerX = this.centerX;
87103 _cam.centerY = this.centerY;
87104 _cam.centerZ = this.centerZ;
87105 _cam.cameraNear = this.cameraNear;
87106 _cam.cameraFar = this.cameraFar;
87107
87108 _cam.cameraType = this.cameraType;
87109
87110 _cam.cameraMatrix = this.cameraMatrix.copy();
87111 _cam.projMatrix = this.projMatrix.copy();
87112
87113 return _cam;
87114 };
87115
87116 /**
87117 * Returns a camera's local axes: left-right, up-down, and forward-backward,
87118 * as defined by vectors in world-space.
87119 * @method _getLocalAxes
87120 * @private
87121 */
87122 _main.default.Camera.prototype._getLocalAxes = function() {
87123 // calculate camera local Z vector
87124 var z0 = this.eyeX - this.centerX;
87125 var z1 = this.eyeY - this.centerY;
87126 var z2 = this.eyeZ - this.centerZ;
87127
87128 // normalize camera local Z vector
87129 var eyeDist = Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2);
87130 if (eyeDist !== 0) {
87131 z0 /= eyeDist;
87132 z1 /= eyeDist;
87133 z2 /= eyeDist;
87134 }
87135
87136 // calculate camera Y vector
87137 var y0 = this.upX;
87138 var y1 = this.upY;
87139 var y2 = this.upZ;
87140
87141 // compute camera local X vector as up vector (local Y) cross local Z
87142 var x0 = y1 * z2 - y2 * z1;
87143 var x1 = -y0 * z2 + y2 * z0;
87144 var x2 = y0 * z1 - y1 * z0;
87145
87146 // recompute y = z cross x
87147 y0 = z1 * x2 - z2 * x1;
87148 y1 = -z0 * x2 + z2 * x0;
87149 y2 = z0 * x1 - z1 * x0;
87150
87151 // cross product gives area of parallelogram, which is < 1.0 for
87152 // non-perpendicular unit-length vectors; so normalize x, y here:
87153 var xmag = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2);
87154 if (xmag !== 0) {
87155 x0 /= xmag;
87156 x1 /= xmag;
87157 x2 /= xmag;
87158 }
87159
87160 var ymag = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2);
87161 if (ymag !== 0) {
87162 y0 /= ymag;
87163 y1 /= ymag;
87164 y2 /= ymag;
87165 }
87166
87167 return {
87168 x: [x0, x1, x2],
87169 y: [y0, y1, y2],
87170 z: [z0, z1, z2]
87171 };
87172 };
87173
87174 /**
87175 * Orbits the camera about center point. For use with orbitControl().
87176 * @method _orbit
87177 * @private
87178 * @param {Number} dTheta change in spherical coordinate theta
87179 * @param {Number} dPhi change in spherical coordinate phi
87180 * @param {Number} dRadius change in radius
87181 */
87182 _main.default.Camera.prototype._orbit = function(dTheta, dPhi, dRadius) {
87183 var diffX = this.eyeX - this.centerX;
87184 var diffY = this.eyeY - this.centerY;
87185 var diffZ = this.eyeZ - this.centerZ;
87186
87187 // get spherical coorinates for current camera position about origin
87188 var camRadius = Math.sqrt(diffX * diffX + diffY * diffY + diffZ * diffZ);
87189 // from https://github.com/mrdoob/three.js/blob/dev/src/math/Spherical.js#L72-L73
87190 var camTheta = Math.atan2(diffX, diffZ); // equatorial angle
87191 var camPhi = Math.acos(Math.max(-1, Math.min(1, diffY / camRadius))); // polar angle
87192
87193 // add change
87194 camTheta += dTheta;
87195 camPhi += dPhi;
87196 camRadius += dRadius;
87197
87198 // prevent zooming through the center:
87199 if (camRadius < 0) {
87200 camRadius = 0.1;
87201 }
87202
87203 // prevent rotation over the zenith / under bottom
87204 if (camPhi > Math.PI) {
87205 camPhi = Math.PI;
87206 } else if (camPhi <= 0) {
87207 camPhi = 0.001;
87208 }
87209
87210 // from https://github.com/mrdoob/three.js/blob/dev/src/math/Vector3.js#L628-L632
87211 var _x = Math.sin(camPhi) * camRadius * Math.sin(camTheta);
87212 var _y = Math.cos(camPhi) * camRadius;
87213 var _z = Math.sin(camPhi) * camRadius * Math.cos(camTheta);
87214
87215 this.camera(
87216 _x + this.centerX,
87217 _y + this.centerY,
87218 _z + this.centerZ,
87219 this.centerX,
87220 this.centerY,
87221 this.centerZ,
87222 0,
87223 1,
87224 0
87225 );
87226 };
87227
87228 /**
87229 * Returns true if camera is currently attached to renderer.
87230 * @method _isActive
87231 * @private
87232 */
87233 _main.default.Camera.prototype._isActive = function() {
87234 return this === this._renderer._curCamera;
87235 };
87236
87237 /**
87238 * Sets rendererGL's current camera to a p5.Camera object. Allows switching
87239 * between multiple cameras.
87240 * @method setCamera
87241 * @param {p5.Camera} cam p5.Camera object
87242 * @for p5
87243 * @example
87244 * <div>
87245 * <code>
87246 * let cam1, cam2;
87247 * let currentCamera;
87248 *
87249 * function setup() {
87250 * createCanvas(100, 100, WEBGL);
87251 * normalMaterial();
87252 *
87253 * cam1 = createCamera();
87254 * cam2 = createCamera();
87255 * cam2.setPosition(30, 0, 50);
87256 * cam2.lookAt(0, 0, 0);
87257 * cam2.ortho();
87258 *
87259 * // set variable for previously active camera:
87260 * currentCamera = 1;
87261 * }
87262 *
87263 * function draw() {
87264 * background(200);
87265 *
87266 * // camera 1:
87267 * cam1.lookAt(0, 0, 0);
87268 * cam1.setPosition(sin(frameCount / 60) * 200, 0, 100);
87269 *
87270 * // every 100 frames, switch between the two cameras
87271 * if (frameCount % 100 === 0) {
87272 * if (currentCamera === 1) {
87273 * setCamera(cam1);
87274 * currentCamera = 0;
87275 * } else {
87276 * setCamera(cam2);
87277 * currentCamera = 1;
87278 * }
87279 * }
87280 *
87281 * drawBoxes();
87282 * }
87283 *
87284 * function drawBoxes() {
87285 * rotateX(frameCount * 0.01);
87286 * translate(-100, 0, 0);
87287 * box(20);
87288 * translate(35, 0, 0);
87289 * box(20);
87290 * translate(35, 0, 0);
87291 * box(20);
87292 * translate(35, 0, 0);
87293 * box(20);
87294 * translate(35, 0, 0);
87295 * box(20);
87296 * translate(35, 0, 0);
87297 * box(20);
87298 * translate(35, 0, 0);
87299 * box(20);
87300 * }
87301 * </code>
87302 * </div>
87303 *
87304 * @alt
87305 * Canvas switches between two camera views, each showing a series of spinning
87306 * 3D boxes.
87307 */
87308 _main.default.prototype.setCamera = function(cam) {
87309 this._renderer._curCamera = cam;
87310
87311 // set the projection matrix (which is not normally updated each frame)
87312 this._renderer.uPMatrix.set(
87313 cam.projMatrix.mat4[0],
87314 cam.projMatrix.mat4[1],
87315 cam.projMatrix.mat4[2],
87316 cam.projMatrix.mat4[3],
87317 cam.projMatrix.mat4[4],
87318 cam.projMatrix.mat4[5],
87319 cam.projMatrix.mat4[6],
87320 cam.projMatrix.mat4[7],
87321 cam.projMatrix.mat4[8],
87322 cam.projMatrix.mat4[9],
87323 cam.projMatrix.mat4[10],
87324 cam.projMatrix.mat4[11],
87325 cam.projMatrix.mat4[12],
87326 cam.projMatrix.mat4[13],
87327 cam.projMatrix.mat4[14],
87328 cam.projMatrix.mat4[15]
87329 );
87330 };
87331 var _default = _main.default.Camera;
87332 exports.default = _default;
87333 },
87334 { '../core/main': 54 }
87335 ],
87336 103: [
87337 function(_dereq_, module, exports) {
87338 'use strict';
87339 Object.defineProperty(exports, '__esModule', { value: true });
87340 exports.default = void 0;
87341
87342 var _main = _interopRequireDefault(_dereq_('../core/main'));
87343 function _interopRequireDefault(obj) {
87344 return obj && obj.__esModule ? obj : { default: obj };
87345 } /** //some of the functions are adjusted from Three.js(http://threejs.org)
87346 * @module Lights, Camera
87347 * @submodule Material
87348 * @for p5
87349 * @requires core
87350 * @requires p5.Geometry
87351 */
87352 /**
87353 * p5 Geometry class
87354 * @class p5.Geometry
87355 * @constructor
87356 * @param {Integer} [detailX] number of vertices on horizontal surface
87357 * @param {Integer} [detailY] number of vertices on horizontal surface
87358 * @param {function} [callback] function to call upon object instantiation.
87359 */ _main.default.Geometry = function(detailX, detailY, callback) {
87360 //an array containing every vertex
87361 //@type [p5.Vector]
87362 this.vertices = []; //an array containing every vertex for stroke drawing
87363 this.lineVertices = []; //an array 1 normal per lineVertex with
87364 //final position representing which direction to
87365 //displace for strokeWeight
87366 //[[0,0,-1,1], [0,1,0,-1] ...];
87367 this.lineNormals = [];
87368
87369 //an array containing 1 normal per vertex
87370 //@type [p5.Vector]
87371 //[p5.Vector, p5.Vector, p5.Vector,p5.Vector, p5.Vector, p5.Vector,...]
87372 this.vertexNormals = [];
87373 //an array containing each three vertex indices that form a face
87374 //[[0, 1, 2], [2, 1, 3], ...]
87375 this.faces = [];
87376 //a 2D array containing uvs for every vertex
87377 //[[0.0,0.0],[1.0,0.0], ...]
87378 this.uvs = [];
87379 // a 2D array containing edge connectivity pattern for create line vertices
87380 //based on faces for most objects;
87381 this.edges = [];
87382 this.vertexColors = [];
87383 this.detailX = detailX !== undefined ? detailX : 1;
87384 this.detailY = detailY !== undefined ? detailY : 1;
87385 this.dirtyFlags = {};
87386
87387 if (callback instanceof Function) {
87388 callback.call(this);
87389 }
87390 return this; // TODO: is this a constructor?
87391 };
87392
87393 _main.default.Geometry.prototype.reset = function() {
87394 this.lineVertices.length = 0;
87395 this.lineNormals.length = 0;
87396
87397 this.vertices.length = 0;
87398 this.edges.length = 0;
87399 this.vertexColors.length = 0;
87400 this.vertexNormals.length = 0;
87401 this.uvs.length = 0;
87402
87403 this.dirtyFlags = {};
87404 };
87405
87406 /**
87407 * computes faces for geometry objects based on the vertices.
87408 * @method computeFaces
87409 * @chainable
87410 */
87411 _main.default.Geometry.prototype.computeFaces = function() {
87412 this.faces.length = 0;
87413 var sliceCount = this.detailX + 1;
87414 var a, b, c, d;
87415 for (var i = 0; i < this.detailY; i++) {
87416 for (var j = 0; j < this.detailX; j++) {
87417 a = i * sliceCount + j; // + offset;
87418 b = i * sliceCount + j + 1; // + offset;
87419 c = (i + 1) * sliceCount + j + 1; // + offset;
87420 d = (i + 1) * sliceCount + j; // + offset;
87421 this.faces.push([a, b, d]);
87422 this.faces.push([d, b, c]);
87423 }
87424 }
87425 return this;
87426 };
87427
87428 _main.default.Geometry.prototype._getFaceNormal = function(faceId) {
87429 //This assumes that vA->vB->vC is a counter-clockwise ordering
87430 var face = this.faces[faceId];
87431 var vA = this.vertices[face[0]];
87432 var vB = this.vertices[face[1]];
87433 var vC = this.vertices[face[2]];
87434 var ab = _main.default.Vector.sub(vB, vA);
87435 var ac = _main.default.Vector.sub(vC, vA);
87436 var n = _main.default.Vector.cross(ab, ac);
87437 var ln = _main.default.Vector.mag(n);
87438 var sinAlpha =
87439 ln / (_main.default.Vector.mag(ab) * _main.default.Vector.mag(ac));
87440 if (sinAlpha === 0 || isNaN(sinAlpha)) {
87441 console.warn(
87442 'p5.Geometry.prototype._getFaceNormal:',
87443 'face has colinear sides or a repeated vertex'
87444 );
87445
87446 return n;
87447 }
87448 if (sinAlpha > 1) sinAlpha = 1; // handle float rounding error
87449 return n.mult(Math.asin(sinAlpha) / ln);
87450 };
87451 /**
87452 * computes smooth normals per vertex as an average of each
87453 * face.
87454 * @method computeNormals
87455 * @chainable
87456 */
87457 _main.default.Geometry.prototype.computeNormals = function() {
87458 var vertexNormals = this.vertexNormals;
87459 var vertices = this.vertices;
87460 var faces = this.faces;
87461 var iv;
87462
87463 // initialize the vertexNormals array with empty vectors
87464 vertexNormals.length = 0;
87465 for (iv = 0; iv < vertices.length; ++iv) {
87466 vertexNormals.push(new _main.default.Vector());
87467 }
87468
87469 // loop through all the faces adding its normal to the normal
87470 // of each of its vertices
87471 for (var f = 0; f < faces.length; ++f) {
87472 var face = faces[f];
87473 var faceNormal = this._getFaceNormal(f);
87474
87475 // all three vertices get the normal added
87476 for (var fv = 0; fv < 3; ++fv) {
87477 var vertexIndex = face[fv];
87478 vertexNormals[vertexIndex].add(faceNormal);
87479 }
87480 }
87481
87482 // normalize the normals
87483 for (iv = 0; iv < vertices.length; ++iv) {
87484 vertexNormals[iv].normalize();
87485 }
87486
87487 return this;
87488 };
87489
87490 /**
87491 * Averages the vertex normals. Used in curved
87492 * surfaces
87493 * @method averageNormals
87494 * @chainable
87495 */
87496 _main.default.Geometry.prototype.averageNormals = function() {
87497 for (var i = 0; i <= this.detailY; i++) {
87498 var offset = this.detailX + 1;
87499 var temp = _main.default.Vector.add(
87500 this.vertexNormals[i * offset],
87501 this.vertexNormals[i * offset + this.detailX]
87502 );
87503
87504 temp = _main.default.Vector.div(temp, 2);
87505 this.vertexNormals[i * offset] = temp;
87506 this.vertexNormals[i * offset + this.detailX] = temp;
87507 }
87508 return this;
87509 };
87510
87511 /**
87512 * Averages pole normals. Used in spherical primitives
87513 * @method averagePoleNormals
87514 * @chainable
87515 */
87516 _main.default.Geometry.prototype.averagePoleNormals = function() {
87517 //average the north pole
87518 var sum = new _main.default.Vector(0, 0, 0);
87519 for (var i = 0; i < this.detailX; i++) {
87520 sum.add(this.vertexNormals[i]);
87521 }
87522 sum = _main.default.Vector.div(sum, this.detailX);
87523
87524 for (var _i = 0; _i < this.detailX; _i++) {
87525 this.vertexNormals[_i] = sum;
87526 }
87527
87528 //average the south pole
87529 sum = new _main.default.Vector(0, 0, 0);
87530 for (
87531 var _i2 = this.vertices.length - 1;
87532 _i2 > this.vertices.length - 1 - this.detailX;
87533 _i2--
87534 ) {
87535 sum.add(this.vertexNormals[_i2]);
87536 }
87537 sum = _main.default.Vector.div(sum, this.detailX);
87538
87539 for (
87540 var _i3 = this.vertices.length - 1;
87541 _i3 > this.vertices.length - 1 - this.detailX;
87542 _i3--
87543 ) {
87544 this.vertexNormals[_i3] = sum;
87545 }
87546 return this;
87547 };
87548
87549 /**
87550 * Create a 2D array for establishing stroke connections
87551 * @private
87552 * @chainable
87553 */
87554 _main.default.Geometry.prototype._makeTriangleEdges = function() {
87555 this.edges.length = 0;
87556 if (Array.isArray(this.strokeIndices)) {
87557 for (var i = 0, max = this.strokeIndices.length; i < max; i++) {
87558 this.edges.push(this.strokeIndices[i]);
87559 }
87560 } else {
87561 for (var j = 0; j < this.faces.length; j++) {
87562 this.edges.push([this.faces[j][0], this.faces[j][1]]);
87563 this.edges.push([this.faces[j][1], this.faces[j][2]]);
87564 this.edges.push([this.faces[j][2], this.faces[j][0]]);
87565 }
87566 }
87567 return this;
87568 };
87569
87570 /**
87571 * Create 4 vertices for each stroke line, two at the beginning position
87572 * and two at the end position. These vertices are displaced relative to
87573 * that line's normal on the GPU
87574 * @private
87575 * @chainable
87576 */
87577 _main.default.Geometry.prototype._edgesToVertices = function() {
87578 this.lineVertices.length = 0;
87579 this.lineNormals.length = 0;
87580
87581 for (var i = 0; i < this.edges.length; i++) {
87582 var begin = this.vertices[this.edges[i][0]];
87583 var end = this.vertices[this.edges[i][1]];
87584 var dir = end
87585 .copy()
87586 .sub(begin)
87587 .normalize();
87588 var a = begin.array();
87589 var b = begin.array();
87590 var c = end.array();
87591 var d = end.array();
87592 var dirAdd = dir.array();
87593 var dirSub = dir.array();
87594 // below is used to displace the pair of vertices at beginning and end
87595 // in opposite directions
87596 dirAdd.push(1);
87597 dirSub.push(-1);
87598 this.lineNormals.push(dirAdd, dirSub, dirAdd, dirAdd, dirSub, dirSub);
87599 this.lineVertices.push(a, b, c, c, b, d);
87600 }
87601 return this;
87602 };
87603
87604 /**
87605 * Modifies all vertices to be centered within the range -100 to 100.
87606 * @method normalize
87607 * @chainable
87608 */
87609 _main.default.Geometry.prototype.normalize = function() {
87610 if (this.vertices.length > 0) {
87611 // Find the corners of our bounding box
87612 var maxPosition = this.vertices[0].copy();
87613 var minPosition = this.vertices[0].copy();
87614
87615 for (var i = 0; i < this.vertices.length; i++) {
87616 maxPosition.x = Math.max(maxPosition.x, this.vertices[i].x);
87617 minPosition.x = Math.min(minPosition.x, this.vertices[i].x);
87618 maxPosition.y = Math.max(maxPosition.y, this.vertices[i].y);
87619 minPosition.y = Math.min(minPosition.y, this.vertices[i].y);
87620 maxPosition.z = Math.max(maxPosition.z, this.vertices[i].z);
87621 minPosition.z = Math.min(minPosition.z, this.vertices[i].z);
87622 }
87623
87624 var center = _main.default.Vector.lerp(maxPosition, minPosition, 0.5);
87625 var dist = _main.default.Vector.sub(maxPosition, minPosition);
87626 var longestDist = Math.max(Math.max(dist.x, dist.y), dist.z);
87627 var scale = 200 / longestDist;
87628
87629 for (var _i4 = 0; _i4 < this.vertices.length; _i4++) {
87630 this.vertices[_i4].sub(center);
87631 this.vertices[_i4].mult(scale);
87632 }
87633 }
87634 return this;
87635 };
87636 var _default = _main.default.Geometry;
87637 exports.default = _default;
87638 },
87639 { '../core/main': 54 }
87640 ],
87641 104: [
87642 function(_dereq_, module, exports) {
87643 'use strict';
87644 Object.defineProperty(exports, '__esModule', { value: true });
87645 exports.default = void 0;
87646
87647 var _main = _interopRequireDefault(_dereq_('../core/main'));
87648 function _interopRequireDefault(obj) {
87649 return obj && obj.__esModule ? obj : { default: obj };
87650 }
87651 /**
87652 * @requires constants
87653 * @todo see methods below needing further implementation.
87654 * future consideration: implement SIMD optimizations
87655 * when browser compatibility becomes available
87656 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/
87657 * Reference/Global_Objects/SIMD
87658 */ var GLMAT_ARRAY_TYPE = Array;
87659 var isMatrixArray = function isMatrixArray(x) {
87660 return x instanceof Array;
87661 };
87662 if (typeof Float32Array !== 'undefined') {
87663 GLMAT_ARRAY_TYPE = Float32Array;
87664 isMatrixArray = function isMatrixArray(x) {
87665 return x instanceof Array || x instanceof Float32Array;
87666 };
87667 }
87668
87669 /**
87670 * A class to describe a 4x4 matrix
87671 * for model and view matrix manipulation in the p5js webgl renderer.
87672 * @class p5.Matrix
87673 * @private
87674 * @constructor
87675 * @param {Array} [mat4] array literal of our 4x4 matrix
87676 */
87677 _main.default.Matrix = function() {
87678 var args = new Array(arguments.length);
87679 for (var i = 0; i < args.length; ++i) {
87680 args[i] = arguments[i];
87681 }
87682
87683 // This is default behavior when object
87684 // instantiated using createMatrix()
87685 // @todo implement createMatrix() in core/math.js
87686 if (args.length && args[args.length - 1] instanceof _main.default) {
87687 this.p5 = args[args.length - 1];
87688 }
87689
87690 if (args[0] === 'mat3') {
87691 this.mat3 = Array.isArray(args[1])
87692 ? args[1]
87693 : new GLMAT_ARRAY_TYPE([1, 0, 0, 0, 1, 0, 0, 0, 1]);
87694 } else {
87695 this.mat4 = Array.isArray(args[0])
87696 ? args[0]
87697 : new GLMAT_ARRAY_TYPE([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
87698 }
87699 return this;
87700 };
87701
87702 /**
87703 * Sets the x, y, and z component of the vector using two or three separate
87704 * variables, the data from a p5.Matrix, or the values from a float array.
87705 *
87706 * @method set
87707 * @param {p5.Matrix|Float32Array|Number[]} [inMatrix] the input p5.Matrix or
87708 * an Array of length 16
87709 * @chainable
87710 */
87711 /**
87712 * @method set
87713 * @param {Number[]} elements 16 numbers passed by value to avoid
87714 * array copying.
87715 * @chainable
87716 */
87717 _main.default.Matrix.prototype.set = function(inMatrix) {
87718 if (inMatrix instanceof _main.default.Matrix) {
87719 this.mat4 = inMatrix.mat4;
87720 return this;
87721 } else if (isMatrixArray(inMatrix)) {
87722 this.mat4 = inMatrix;
87723 return this;
87724 } else if (arguments.length === 16) {
87725 this.mat4[0] = arguments[0];
87726 this.mat4[1] = arguments[1];
87727 this.mat4[2] = arguments[2];
87728 this.mat4[3] = arguments[3];
87729 this.mat4[4] = arguments[4];
87730 this.mat4[5] = arguments[5];
87731 this.mat4[6] = arguments[6];
87732 this.mat4[7] = arguments[7];
87733 this.mat4[8] = arguments[8];
87734 this.mat4[9] = arguments[9];
87735 this.mat4[10] = arguments[10];
87736 this.mat4[11] = arguments[11];
87737 this.mat4[12] = arguments[12];
87738 this.mat4[13] = arguments[13];
87739 this.mat4[14] = arguments[14];
87740 this.mat4[15] = arguments[15];
87741 }
87742 return this;
87743 };
87744
87745 /**
87746 * Gets a copy of the vector, returns a p5.Matrix object.
87747 *
87748 * @method get
87749 * @return {p5.Matrix} the copy of the p5.Matrix object
87750 */
87751 _main.default.Matrix.prototype.get = function() {
87752 return new _main.default.Matrix(this.mat4, this.p5);
87753 };
87754
87755 /**
87756 * return a copy of a matrix
87757 * @method copy
87758 * @return {p5.Matrix} the result matrix
87759 */
87760 _main.default.Matrix.prototype.copy = function() {
87761 var copied = new _main.default.Matrix(this.p5);
87762 copied.mat4[0] = this.mat4[0];
87763 copied.mat4[1] = this.mat4[1];
87764 copied.mat4[2] = this.mat4[2];
87765 copied.mat4[3] = this.mat4[3];
87766 copied.mat4[4] = this.mat4[4];
87767 copied.mat4[5] = this.mat4[5];
87768 copied.mat4[6] = this.mat4[6];
87769 copied.mat4[7] = this.mat4[7];
87770 copied.mat4[8] = this.mat4[8];
87771 copied.mat4[9] = this.mat4[9];
87772 copied.mat4[10] = this.mat4[10];
87773 copied.mat4[11] = this.mat4[11];
87774 copied.mat4[12] = this.mat4[12];
87775 copied.mat4[13] = this.mat4[13];
87776 copied.mat4[14] = this.mat4[14];
87777 copied.mat4[15] = this.mat4[15];
87778 return copied;
87779 };
87780
87781 /**
87782 * return an identity matrix
87783 * @method identity
87784 * @return {p5.Matrix} the result matrix
87785 */
87786 _main.default.Matrix.identity = function(pInst) {
87787 return new _main.default.Matrix(pInst);
87788 };
87789
87790 /**
87791 * transpose according to a given matrix
87792 * @method transpose
87793 * @param {p5.Matrix|Float32Array|Number[]} a the matrix to be
87794 * based on to transpose
87795 * @chainable
87796 */
87797 _main.default.Matrix.prototype.transpose = function(a) {
87798 var a01, a02, a03, a12, a13, a23;
87799 if (a instanceof _main.default.Matrix) {
87800 a01 = a.mat4[1];
87801 a02 = a.mat4[2];
87802 a03 = a.mat4[3];
87803 a12 = a.mat4[6];
87804 a13 = a.mat4[7];
87805 a23 = a.mat4[11];
87806
87807 this.mat4[0] = a.mat4[0];
87808 this.mat4[1] = a.mat4[4];
87809 this.mat4[2] = a.mat4[8];
87810 this.mat4[3] = a.mat4[12];
87811 this.mat4[4] = a01;
87812 this.mat4[5] = a.mat4[5];
87813 this.mat4[6] = a.mat4[9];
87814 this.mat4[7] = a.mat4[13];
87815 this.mat4[8] = a02;
87816 this.mat4[9] = a12;
87817 this.mat4[10] = a.mat4[10];
87818 this.mat4[11] = a.mat4[14];
87819 this.mat4[12] = a03;
87820 this.mat4[13] = a13;
87821 this.mat4[14] = a23;
87822 this.mat4[15] = a.mat4[15];
87823 } else if (isMatrixArray(a)) {
87824 a01 = a[1];
87825 a02 = a[2];
87826 a03 = a[3];
87827 a12 = a[6];
87828 a13 = a[7];
87829 a23 = a[11];
87830
87831 this.mat4[0] = a[0];
87832 this.mat4[1] = a[4];
87833 this.mat4[2] = a[8];
87834 this.mat4[3] = a[12];
87835 this.mat4[4] = a01;
87836 this.mat4[5] = a[5];
87837 this.mat4[6] = a[9];
87838 this.mat4[7] = a[13];
87839 this.mat4[8] = a02;
87840 this.mat4[9] = a12;
87841 this.mat4[10] = a[10];
87842 this.mat4[11] = a[14];
87843 this.mat4[12] = a03;
87844 this.mat4[13] = a13;
87845 this.mat4[14] = a23;
87846 this.mat4[15] = a[15];
87847 }
87848 return this;
87849 };
87850
87851 /**
87852 * invert matrix according to a give matrix
87853 * @method invert
87854 * @param {p5.Matrix|Float32Array|Number[]} a the matrix to be
87855 * based on to invert
87856 * @chainable
87857 */
87858 _main.default.Matrix.prototype.invert = function(a) {
87859 var a00, a01, a02, a03, a10, a11, a12, a13;
87860 var a20, a21, a22, a23, a30, a31, a32, a33;
87861 if (a instanceof _main.default.Matrix) {
87862 a00 = a.mat4[0];
87863 a01 = a.mat4[1];
87864 a02 = a.mat4[2];
87865 a03 = a.mat4[3];
87866 a10 = a.mat4[4];
87867 a11 = a.mat4[5];
87868 a12 = a.mat4[6];
87869 a13 = a.mat4[7];
87870 a20 = a.mat4[8];
87871 a21 = a.mat4[9];
87872 a22 = a.mat4[10];
87873 a23 = a.mat4[11];
87874 a30 = a.mat4[12];
87875 a31 = a.mat4[13];
87876 a32 = a.mat4[14];
87877 a33 = a.mat4[15];
87878 } else if (isMatrixArray(a)) {
87879 a00 = a[0];
87880 a01 = a[1];
87881 a02 = a[2];
87882 a03 = a[3];
87883 a10 = a[4];
87884 a11 = a[5];
87885 a12 = a[6];
87886 a13 = a[7];
87887 a20 = a[8];
87888 a21 = a[9];
87889 a22 = a[10];
87890 a23 = a[11];
87891 a30 = a[12];
87892 a31 = a[13];
87893 a32 = a[14];
87894 a33 = a[15];
87895 }
87896 var b00 = a00 * a11 - a01 * a10;
87897 var b01 = a00 * a12 - a02 * a10;
87898 var b02 = a00 * a13 - a03 * a10;
87899 var b03 = a01 * a12 - a02 * a11;
87900 var b04 = a01 * a13 - a03 * a11;
87901 var b05 = a02 * a13 - a03 * a12;
87902 var b06 = a20 * a31 - a21 * a30;
87903 var b07 = a20 * a32 - a22 * a30;
87904 var b08 = a20 * a33 - a23 * a30;
87905 var b09 = a21 * a32 - a22 * a31;
87906 var b10 = a21 * a33 - a23 * a31;
87907 var b11 = a22 * a33 - a23 * a32;
87908
87909 // Calculate the determinant
87910 var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
87911
87912 if (!det) {
87913 return null;
87914 }
87915 det = 1.0 / det;
87916
87917 this.mat4[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
87918 this.mat4[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
87919 this.mat4[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
87920 this.mat4[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
87921 this.mat4[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
87922 this.mat4[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
87923 this.mat4[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
87924 this.mat4[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
87925 this.mat4[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
87926 this.mat4[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
87927 this.mat4[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
87928 this.mat4[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
87929 this.mat4[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
87930 this.mat4[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
87931 this.mat4[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
87932 this.mat4[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
87933
87934 return this;
87935 };
87936
87937 /**
87938 * Inverts a 3x3 matrix
87939 * @method invert3x3
87940 * @chainable
87941 */
87942 _main.default.Matrix.prototype.invert3x3 = function() {
87943 var a00 = this.mat3[0];
87944 var a01 = this.mat3[1];
87945 var a02 = this.mat3[2];
87946 var a10 = this.mat3[3];
87947 var a11 = this.mat3[4];
87948 var a12 = this.mat3[5];
87949 var a20 = this.mat3[6];
87950 var a21 = this.mat3[7];
87951 var a22 = this.mat3[8];
87952 var b01 = a22 * a11 - a12 * a21;
87953 var b11 = -a22 * a10 + a12 * a20;
87954 var b21 = a21 * a10 - a11 * a20;
87955
87956 // Calculate the determinant
87957 var det = a00 * b01 + a01 * b11 + a02 * b21;
87958 if (!det) {
87959 return null;
87960 }
87961 det = 1.0 / det;
87962 this.mat3[0] = b01 * det;
87963 this.mat3[1] = (-a22 * a01 + a02 * a21) * det;
87964 this.mat3[2] = (a12 * a01 - a02 * a11) * det;
87965 this.mat3[3] = b11 * det;
87966 this.mat3[4] = (a22 * a00 - a02 * a20) * det;
87967 this.mat3[5] = (-a12 * a00 + a02 * a10) * det;
87968 this.mat3[6] = b21 * det;
87969 this.mat3[7] = (-a21 * a00 + a01 * a20) * det;
87970 this.mat3[8] = (a11 * a00 - a01 * a10) * det;
87971 return this;
87972 };
87973
87974 /**
87975 * transposes a 3x3 p5.Matrix by a mat3
87976 * @method transpose3x3
87977 * @param {Number[]} mat3 1-dimensional array
87978 * @chainable
87979 */
87980 _main.default.Matrix.prototype.transpose3x3 = function(mat3) {
87981 var a01 = mat3[1],
87982 a02 = mat3[2],
87983 a12 = mat3[5];
87984 this.mat3[1] = mat3[3];
87985 this.mat3[2] = mat3[6];
87986 this.mat3[3] = a01;
87987 this.mat3[5] = mat3[7];
87988 this.mat3[6] = a02;
87989 this.mat3[7] = a12;
87990 return this;
87991 };
87992
87993 /**
87994 * converts a 4x4 matrix to its 3x3 inverse transform
87995 * commonly used in MVMatrix to NMatrix conversions.
87996 * @method invertTranspose
87997 * @param {p5.Matrix} mat4 the matrix to be based on to invert
87998 * @chainable
87999 * @todo finish implementation
88000 */
88001 _main.default.Matrix.prototype.inverseTranspose = function(matrix) {
88002 if (this.mat3 === undefined) {
88003 console.error('sorry, this function only works with mat3');
88004 } else {
88005 //convert mat4 -> mat3
88006 this.mat3[0] = matrix.mat4[0];
88007 this.mat3[1] = matrix.mat4[1];
88008 this.mat3[2] = matrix.mat4[2];
88009 this.mat3[3] = matrix.mat4[4];
88010 this.mat3[4] = matrix.mat4[5];
88011 this.mat3[5] = matrix.mat4[6];
88012 this.mat3[6] = matrix.mat4[8];
88013 this.mat3[7] = matrix.mat4[9];
88014 this.mat3[8] = matrix.mat4[10];
88015 }
88016
88017 var inverse = this.invert3x3();
88018 // check inverse succeeded
88019 if (inverse) {
88020 inverse.transpose3x3(this.mat3);
88021 } else {
88022 // in case of singularity, just zero the matrix
88023 for (var i = 0; i < 9; i++) {
88024 this.mat3[i] = 0;
88025 }
88026 }
88027 return this;
88028 };
88029
88030 /**
88031 * inspired by Toji's mat4 determinant
88032 * @method determinant
88033 * @return {Number} Determinant of our 4x4 matrix
88034 */
88035 _main.default.Matrix.prototype.determinant = function() {
88036 var d00 = this.mat4[0] * this.mat4[5] - this.mat4[1] * this.mat4[4],
88037 d01 = this.mat4[0] * this.mat4[6] - this.mat4[2] * this.mat4[4],
88038 d02 = this.mat4[0] * this.mat4[7] - this.mat4[3] * this.mat4[4],
88039 d03 = this.mat4[1] * this.mat4[6] - this.mat4[2] * this.mat4[5],
88040 d04 = this.mat4[1] * this.mat4[7] - this.mat4[3] * this.mat4[5],
88041 d05 = this.mat4[2] * this.mat4[7] - this.mat4[3] * this.mat4[6],
88042 d06 = this.mat4[8] * this.mat4[13] - this.mat4[9] * this.mat4[12],
88043 d07 = this.mat4[8] * this.mat4[14] - this.mat4[10] * this.mat4[12],
88044 d08 = this.mat4[8] * this.mat4[15] - this.mat4[11] * this.mat4[12],
88045 d09 = this.mat4[9] * this.mat4[14] - this.mat4[10] * this.mat4[13],
88046 d10 = this.mat4[9] * this.mat4[15] - this.mat4[11] * this.mat4[13],
88047 d11 = this.mat4[10] * this.mat4[15] - this.mat4[11] * this.mat4[14];
88048
88049 // Calculate the determinant
88050 return d00 * d11 - d01 * d10 + d02 * d09 + d03 * d08 - d04 * d07 + d05 * d06;
88051 };
88052
88053 /**
88054 * multiply two mat4s
88055 * @method mult
88056 * @param {p5.Matrix|Float32Array|Number[]} multMatrix The matrix
88057 * we want to multiply by
88058 * @chainable
88059 */
88060 _main.default.Matrix.prototype.mult = function(multMatrix) {
88061 var _src;
88062
88063 if (multMatrix === this || multMatrix === this.mat4) {
88064 _src = this.copy().mat4; // only need to allocate in this rare case
88065 } else if (multMatrix instanceof _main.default.Matrix) {
88066 _src = multMatrix.mat4;
88067 } else if (isMatrixArray(multMatrix)) {
88068 _src = multMatrix;
88069 } else if (arguments.length === 16) {
88070 _src = arguments;
88071 } else {
88072 return; // nothing to do.
88073 }
88074
88075 // each row is used for the multiplier
88076 var b0 = this.mat4[0],
88077 b1 = this.mat4[1],
88078 b2 = this.mat4[2],
88079 b3 = this.mat4[3];
88080 this.mat4[0] = b0 * _src[0] + b1 * _src[4] + b2 * _src[8] + b3 * _src[12];
88081 this.mat4[1] = b0 * _src[1] + b1 * _src[5] + b2 * _src[9] + b3 * _src[13];
88082 this.mat4[2] = b0 * _src[2] + b1 * _src[6] + b2 * _src[10] + b3 * _src[14];
88083 this.mat4[3] = b0 * _src[3] + b1 * _src[7] + b2 * _src[11] + b3 * _src[15];
88084
88085 b0 = this.mat4[4];
88086 b1 = this.mat4[5];
88087 b2 = this.mat4[6];
88088 b3 = this.mat4[7];
88089 this.mat4[4] = b0 * _src[0] + b1 * _src[4] + b2 * _src[8] + b3 * _src[12];
88090 this.mat4[5] = b0 * _src[1] + b1 * _src[5] + b2 * _src[9] + b3 * _src[13];
88091 this.mat4[6] = b0 * _src[2] + b1 * _src[6] + b2 * _src[10] + b3 * _src[14];
88092 this.mat4[7] = b0 * _src[3] + b1 * _src[7] + b2 * _src[11] + b3 * _src[15];
88093
88094 b0 = this.mat4[8];
88095 b1 = this.mat4[9];
88096 b2 = this.mat4[10];
88097 b3 = this.mat4[11];
88098 this.mat4[8] = b0 * _src[0] + b1 * _src[4] + b2 * _src[8] + b3 * _src[12];
88099 this.mat4[9] = b0 * _src[1] + b1 * _src[5] + b2 * _src[9] + b3 * _src[13];
88100 this.mat4[10] = b0 * _src[2] + b1 * _src[6] + b2 * _src[10] + b3 * _src[14];
88101 this.mat4[11] = b0 * _src[3] + b1 * _src[7] + b2 * _src[11] + b3 * _src[15];
88102
88103 b0 = this.mat4[12];
88104 b1 = this.mat4[13];
88105 b2 = this.mat4[14];
88106 b3 = this.mat4[15];
88107 this.mat4[12] = b0 * _src[0] + b1 * _src[4] + b2 * _src[8] + b3 * _src[12];
88108 this.mat4[13] = b0 * _src[1] + b1 * _src[5] + b2 * _src[9] + b3 * _src[13];
88109 this.mat4[14] = b0 * _src[2] + b1 * _src[6] + b2 * _src[10] + b3 * _src[14];
88110 this.mat4[15] = b0 * _src[3] + b1 * _src[7] + b2 * _src[11] + b3 * _src[15];
88111
88112 return this;
88113 };
88114
88115 _main.default.Matrix.prototype.apply = function(multMatrix) {
88116 var _src;
88117
88118 if (multMatrix === this || multMatrix === this.mat4) {
88119 _src = this.copy().mat4; // only need to allocate in this rare case
88120 } else if (multMatrix instanceof _main.default.Matrix) {
88121 _src = multMatrix.mat4;
88122 } else if (isMatrixArray(multMatrix)) {
88123 _src = multMatrix;
88124 } else if (arguments.length === 16) {
88125 _src = arguments;
88126 } else {
88127 return; // nothing to do.
88128 }
88129
88130 var mat4 = this.mat4;
88131
88132 // each row is used for the multiplier
88133 var m0 = mat4[0];
88134 var m4 = mat4[4];
88135 var m8 = mat4[8];
88136 var m12 = mat4[12];
88137 mat4[0] = _src[0] * m0 + _src[1] * m4 + _src[2] * m8 + _src[3] * m12;
88138 mat4[4] = _src[4] * m0 + _src[5] * m4 + _src[6] * m8 + _src[7] * m12;
88139 mat4[8] = _src[8] * m0 + _src[9] * m4 + _src[10] * m8 + _src[11] * m12;
88140 mat4[12] = _src[12] * m0 + _src[13] * m4 + _src[14] * m8 + _src[15] * m12;
88141
88142 var m1 = mat4[1];
88143 var m5 = mat4[5];
88144 var m9 = mat4[9];
88145 var m13 = mat4[13];
88146 mat4[1] = _src[0] * m1 + _src[1] * m5 + _src[2] * m9 + _src[3] * m13;
88147 mat4[5] = _src[4] * m1 + _src[5] * m5 + _src[6] * m9 + _src[7] * m13;
88148 mat4[9] = _src[8] * m1 + _src[9] * m5 + _src[10] * m9 + _src[11] * m13;
88149 mat4[13] = _src[12] * m1 + _src[13] * m5 + _src[14] * m9 + _src[15] * m13;
88150
88151 var m2 = mat4[2];
88152 var m6 = mat4[6];
88153 var m10 = mat4[10];
88154 var m14 = mat4[14];
88155 mat4[2] = _src[0] * m2 + _src[1] * m6 + _src[2] * m10 + _src[3] * m14;
88156 mat4[6] = _src[4] * m2 + _src[5] * m6 + _src[6] * m10 + _src[7] * m14;
88157 mat4[10] = _src[8] * m2 + _src[9] * m6 + _src[10] * m10 + _src[11] * m14;
88158 mat4[14] = _src[12] * m2 + _src[13] * m6 + _src[14] * m10 + _src[15] * m14;
88159
88160 var m3 = mat4[3];
88161 var m7 = mat4[7];
88162 var m11 = mat4[11];
88163 var m15 = mat4[15];
88164 mat4[3] = _src[0] * m3 + _src[1] * m7 + _src[2] * m11 + _src[3] * m15;
88165 mat4[7] = _src[4] * m3 + _src[5] * m7 + _src[6] * m11 + _src[7] * m15;
88166 mat4[11] = _src[8] * m3 + _src[9] * m7 + _src[10] * m11 + _src[11] * m15;
88167 mat4[15] = _src[12] * m3 + _src[13] * m7 + _src[14] * m11 + _src[15] * m15;
88168
88169 return this;
88170 };
88171
88172 /**
88173 * scales a p5.Matrix by scalars or a vector
88174 * @method scale
88175 * @param {p5.Vector|Float32Array|Number[]} s vector to scale by
88176 * @chainable
88177 */
88178 _main.default.Matrix.prototype.scale = function(x, y, z) {
88179 if (x instanceof _main.default.Vector) {
88180 // x is a vector, extract the components from it.
88181 y = x.y;
88182 z = x.z;
88183 x = x.x; // must be last
88184 } else if (x instanceof Array) {
88185 // x is an array, extract the components from it.
88186 y = x[1];
88187 z = x[2];
88188 x = x[0]; // must be last
88189 }
88190
88191 this.mat4[0] *= x;
88192 this.mat4[1] *= x;
88193 this.mat4[2] *= x;
88194 this.mat4[3] *= x;
88195 this.mat4[4] *= y;
88196 this.mat4[5] *= y;
88197 this.mat4[6] *= y;
88198 this.mat4[7] *= y;
88199 this.mat4[8] *= z;
88200 this.mat4[9] *= z;
88201 this.mat4[10] *= z;
88202 this.mat4[11] *= z;
88203
88204 return this;
88205 };
88206
88207 /**
88208 * rotate our Matrix around an axis by the given angle.
88209 * @method rotate
88210 * @param {Number} a The angle of rotation in radians
88211 * @param {p5.Vector|Number[]} axis the axis(es) to rotate around
88212 * @chainable
88213 * inspired by Toji's gl-matrix lib, mat4 rotation
88214 */
88215 _main.default.Matrix.prototype.rotate = function(a, x, y, z) {
88216 if (x instanceof _main.default.Vector) {
88217 // x is a vector, extract the components from it.
88218 y = x.y;
88219 z = x.z;
88220 x = x.x; //must be last
88221 } else if (x instanceof Array) {
88222 // x is an array, extract the components from it.
88223 y = x[1];
88224 z = x[2];
88225 x = x[0]; //must be last
88226 }
88227
88228 var len = Math.sqrt(x * x + y * y + z * z);
88229 x *= 1 / len;
88230 y *= 1 / len;
88231 z *= 1 / len;
88232
88233 var a00 = this.mat4[0];
88234 var a01 = this.mat4[1];
88235 var a02 = this.mat4[2];
88236 var a03 = this.mat4[3];
88237 var a10 = this.mat4[4];
88238 var a11 = this.mat4[5];
88239 var a12 = this.mat4[6];
88240 var a13 = this.mat4[7];
88241 var a20 = this.mat4[8];
88242 var a21 = this.mat4[9];
88243 var a22 = this.mat4[10];
88244 var a23 = this.mat4[11];
88245
88246 //sin,cos, and tan of respective angle
88247 var sA = Math.sin(a);
88248 var cA = Math.cos(a);
88249 var tA = 1 - cA;
88250 // Construct the elements of the rotation matrix
88251 var b00 = x * x * tA + cA;
88252 var b01 = y * x * tA + z * sA;
88253 var b02 = z * x * tA - y * sA;
88254 var b10 = x * y * tA - z * sA;
88255 var b11 = y * y * tA + cA;
88256 var b12 = z * y * tA + x * sA;
88257 var b20 = x * z * tA + y * sA;
88258 var b21 = y * z * tA - x * sA;
88259 var b22 = z * z * tA + cA;
88260
88261 // rotation-specific matrix multiplication
88262 this.mat4[0] = a00 * b00 + a10 * b01 + a20 * b02;
88263 this.mat4[1] = a01 * b00 + a11 * b01 + a21 * b02;
88264 this.mat4[2] = a02 * b00 + a12 * b01 + a22 * b02;
88265 this.mat4[3] = a03 * b00 + a13 * b01 + a23 * b02;
88266 this.mat4[4] = a00 * b10 + a10 * b11 + a20 * b12;
88267 this.mat4[5] = a01 * b10 + a11 * b11 + a21 * b12;
88268 this.mat4[6] = a02 * b10 + a12 * b11 + a22 * b12;
88269 this.mat4[7] = a03 * b10 + a13 * b11 + a23 * b12;
88270 this.mat4[8] = a00 * b20 + a10 * b21 + a20 * b22;
88271 this.mat4[9] = a01 * b20 + a11 * b21 + a21 * b22;
88272 this.mat4[10] = a02 * b20 + a12 * b21 + a22 * b22;
88273 this.mat4[11] = a03 * b20 + a13 * b21 + a23 * b22;
88274
88275 return this;
88276 };
88277
88278 /**
88279 * @todo finish implementing this method!
88280 * translates
88281 * @method translate
88282 * @param {Number[]} v vector to translate by
88283 * @chainable
88284 */
88285 _main.default.Matrix.prototype.translate = function(v) {
88286 var x = v[0],
88287 y = v[1],
88288 z = v[2] || 0;
88289 this.mat4[12] += this.mat4[0] * x + this.mat4[4] * y + this.mat4[8] * z;
88290 this.mat4[13] += this.mat4[1] * x + this.mat4[5] * y + this.mat4[9] * z;
88291 this.mat4[14] += this.mat4[2] * x + this.mat4[6] * y + this.mat4[10] * z;
88292 this.mat4[15] += this.mat4[3] * x + this.mat4[7] * y + this.mat4[11] * z;
88293 };
88294
88295 _main.default.Matrix.prototype.rotateX = function(a) {
88296 this.rotate(a, 1, 0, 0);
88297 };
88298 _main.default.Matrix.prototype.rotateY = function(a) {
88299 this.rotate(a, 0, 1, 0);
88300 };
88301 _main.default.Matrix.prototype.rotateZ = function(a) {
88302 this.rotate(a, 0, 0, 1);
88303 };
88304
88305 /**
88306 * sets the perspective matrix
88307 * @method perspective
88308 * @param {Number} fovy [description]
88309 * @param {Number} aspect [description]
88310 * @param {Number} near near clipping plane
88311 * @param {Number} far far clipping plane
88312 * @chainable
88313 */
88314 _main.default.Matrix.prototype.perspective = function(fovy, aspect, near, far) {
88315 var f = 1.0 / Math.tan(fovy / 2),
88316 nf = 1 / (near - far);
88317
88318 this.mat4[0] = f / aspect;
88319 this.mat4[1] = 0;
88320 this.mat4[2] = 0;
88321 this.mat4[3] = 0;
88322 this.mat4[4] = 0;
88323 this.mat4[5] = f;
88324 this.mat4[6] = 0;
88325 this.mat4[7] = 0;
88326 this.mat4[8] = 0;
88327 this.mat4[9] = 0;
88328 this.mat4[10] = (far + near) * nf;
88329 this.mat4[11] = -1;
88330 this.mat4[12] = 0;
88331 this.mat4[13] = 0;
88332 this.mat4[14] = 2 * far * near * nf;
88333 this.mat4[15] = 0;
88334
88335 return this;
88336 };
88337
88338 /**
88339 * sets the ortho matrix
88340 * @method ortho
88341 * @param {Number} left [description]
88342 * @param {Number} right [description]
88343 * @param {Number} bottom [description]
88344 * @param {Number} top [description]
88345 * @param {Number} near near clipping plane
88346 * @param {Number} far far clipping plane
88347 * @chainable
88348 */
88349 _main.default.Matrix.prototype.ortho = function(
88350 left,
88351 right,
88352 bottom,
88353 top,
88354 near,
88355 far
88356 ) {
88357 var lr = 1 / (left - right),
88358 bt = 1 / (bottom - top),
88359 nf = 1 / (near - far);
88360 this.mat4[0] = -2 * lr;
88361 this.mat4[1] = 0;
88362 this.mat4[2] = 0;
88363 this.mat4[3] = 0;
88364 this.mat4[4] = 0;
88365 this.mat4[5] = -2 * bt;
88366 this.mat4[6] = 0;
88367 this.mat4[7] = 0;
88368 this.mat4[8] = 0;
88369 this.mat4[9] = 0;
88370 this.mat4[10] = 2 * nf;
88371 this.mat4[11] = 0;
88372 this.mat4[12] = (left + right) * lr;
88373 this.mat4[13] = (top + bottom) * bt;
88374 this.mat4[14] = (far + near) * nf;
88375 this.mat4[15] = 1;
88376
88377 return this;
88378 };
88379
88380 /**
88381 * PRIVATE
88382 */
88383 // matrix methods adapted from:
88384 // https://developer.mozilla.org/en-US/docs/Web/WebGL/
88385 // gluPerspective
88386 //
88387 // function _makePerspective(fovy, aspect, znear, zfar){
88388 // const ymax = znear * Math.tan(fovy * Math.PI / 360.0);
88389 // const ymin = -ymax;
88390 // const xmin = ymin * aspect;
88391 // const xmax = ymax * aspect;
88392 // return _makeFrustum(xmin, xmax, ymin, ymax, znear, zfar);
88393 // }
88394
88395 ////
88396 //// glFrustum
88397 ////
88398 //function _makeFrustum(left, right, bottom, top, znear, zfar){
88399 // const X = 2*znear/(right-left);
88400 // const Y = 2*znear/(top-bottom);
88401 // const A = (right+left)/(right-left);
88402 // const B = (top+bottom)/(top-bottom);
88403 // const C = -(zfar+znear)/(zfar-znear);
88404 // const D = -2*zfar*znear/(zfar-znear);
88405 // const frustrumMatrix =[
88406 // X, 0, A, 0,
88407 // 0, Y, B, 0,
88408 // 0, 0, C, D,
88409 // 0, 0, -1, 0
88410 //];
88411 //return frustrumMatrix;
88412 // }
88413
88414 // function _setMVPMatrices(){
88415 ////an identity matrix
88416 ////@TODO use the p5.Matrix class to abstract away our MV matrices and
88417 ///other math
88418 //const _mvMatrix =
88419 //[
88420 // 1.0,0.0,0.0,0.0,
88421 // 0.0,1.0,0.0,0.0,
88422 // 0.0,0.0,1.0,0.0,
88423 // 0.0,0.0,0.0,1.0
88424 //];
88425 var _default = _main.default.Matrix;
88426 exports.default = _default;
88427 },
88428 { '../core/main': 54 }
88429 ],
88430 105: [
88431 function(_dereq_, module, exports) {
88432 'use strict';
88433 Object.defineProperty(exports, '__esModule', { value: true });
88434 exports.default = void 0;
88435 var _main = _interopRequireDefault(_dereq_('../core/main'));
88436 function _interopRequireDefault(obj) {
88437 return obj && obj.__esModule ? obj : { default: obj };
88438 }
88439
88440 _main.default.RenderBuffer = function(size, src, dst, attr, renderer, map) {
88441 this.size = size; // the number of FLOATs in each vertex
88442 this.src = src; // the name of the model's source array
88443 this.dst = dst; // the name of the geometry's buffer
88444 this.attr = attr; // the name of the vertex attribute
88445 this._renderer = renderer;
88446 this.map = map; // optional, a transformation function to apply to src
88447 };
88448
88449 /**
88450 * Enables and binds the buffers used by shader when the appropriate data exists in geometry.
88451 * Must always be done prior to drawing geometry in WebGL.
88452 * @param {p5.Geometry} geometry Geometry that is going to be drawn
88453 * @param {p5.Shader} shader Active shader
88454 * @private
88455 */
88456 _main.default.RenderBuffer.prototype._prepareBuffer = function(geometry, shader) {
88457 var attributes = shader.attributes;
88458 var gl = this._renderer.GL;
88459 var model;
88460 if (geometry.model) {
88461 model = geometry.model;
88462 } else {
88463 model = geometry;
88464 }
88465
88466 // loop through each of the buffer definitions
88467 var attr = attributes[this.attr];
88468 if (!attr) {
88469 return;
88470 }
88471
88472 // check if the model has the appropriate source array
88473 var buffer = geometry[this.dst];
88474 var src = model[this.src];
88475 if (src.length > 0) {
88476 // check if we need to create the GL buffer
88477 var createBuffer = !buffer;
88478 if (createBuffer) {
88479 // create and remember the buffer
88480 geometry[this.dst] = buffer = gl.createBuffer();
88481 }
88482 // bind the buffer
88483 gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
88484
88485 // check if we need to fill the buffer with data
88486 if (createBuffer || model.dirtyFlags[this.src] !== false) {
88487 var map = this.map;
88488 // get the values from the model, possibly transformed
88489 var values = map ? map(src) : src;
88490 // fill the buffer with the values
88491 this._renderer._bindBuffer(buffer, gl.ARRAY_BUFFER, values);
88492
88493 // mark the model's source array as clean
88494 model.dirtyFlags[this.src] = false;
88495 }
88496 // enable the attribute
88497 shader.enableAttrib(attr, this.size);
88498 }
88499 };
88500 var _default = _main.default.RenderBuffer;
88501 exports.default = _default;
88502 },
88503 { '../core/main': 54 }
88504 ],
88505 106: [
88506 function(_dereq_, module, exports) {
88507 'use strict';
88508 function _typeof(obj) {
88509 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
88510 _typeof = function _typeof(obj) {
88511 return typeof obj;
88512 };
88513 } else {
88514 _typeof = function _typeof(obj) {
88515 return obj &&
88516 typeof Symbol === 'function' &&
88517 obj.constructor === Symbol &&
88518 obj !== Symbol.prototype
88519 ? 'symbol'
88520 : typeof obj;
88521 };
88522 }
88523 return _typeof(obj);
88524 }
88525 Object.defineProperty(exports, '__esModule', { value: true });
88526 exports.default = void 0;
88527
88528 var _main = _interopRequireDefault(_dereq_('../core/main'));
88529 var constants = _interopRequireWildcard(_dereq_('../core/constants'));
88530 _dereq_('./p5.RenderBuffer');
88531 function _getRequireWildcardCache() {
88532 if (typeof WeakMap !== 'function') return null;
88533 var cache = new WeakMap();
88534 _getRequireWildcardCache = function _getRequireWildcardCache() {
88535 return cache;
88536 };
88537 return cache;
88538 }
88539 function _interopRequireWildcard(obj) {
88540 if (obj && obj.__esModule) {
88541 return obj;
88542 }
88543 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) {
88544 return { default: obj };
88545 }
88546 var cache = _getRequireWildcardCache();
88547 if (cache && cache.has(obj)) {
88548 return cache.get(obj);
88549 }
88550 var newObj = {};
88551 var hasPropertyDescriptor =
88552 Object.defineProperty && Object.getOwnPropertyDescriptor;
88553 for (var key in obj) {
88554 if (Object.prototype.hasOwnProperty.call(obj, key)) {
88555 var desc = hasPropertyDescriptor
88556 ? Object.getOwnPropertyDescriptor(obj, key)
88557 : null;
88558 if (desc && (desc.get || desc.set)) {
88559 Object.defineProperty(newObj, key, desc);
88560 } else {
88561 newObj[key] = obj[key];
88562 }
88563 }
88564 }
88565 newObj.default = obj;
88566 if (cache) {
88567 cache.set(obj, newObj);
88568 }
88569 return newObj;
88570 }
88571 function _interopRequireDefault(obj) {
88572 return obj && obj.__esModule ? obj : { default: obj };
88573 }
88574 /**
88575 * Welcome to RendererGL Immediate Mode.
88576 * Immediate mode is used for drawing custom shapes
88577 * from a set of vertices. Immediate Mode is activated
88578 * when you call <a href="#/p5/beginShape">beginShape()</a> & de-activated when you call <a href="#/p5/endShape">endShape()</a>.
88579 * Immediate mode is a style of programming borrowed
88580 * from OpenGL's (now-deprecated) immediate mode.
88581 * It differs from p5.js' default, Retained Mode, which caches
88582 * geometries and buffers on the CPU to reduce the number of webgl
88583 * draw calls. Retained mode is more efficient & performative,
88584 * however, Immediate Mode is useful for sketching quick
88585 * geometric ideas.
88586 */ /**
88587 * Begin shape drawing. This is a helpful way of generating
88588 * custom shapes quickly. However in WEBGL mode, application
88589 * performance will likely drop as a result of too many calls to
88590 * <a href="#/p5/beginShape">beginShape()</a> / <a href="#/p5/endShape">endShape()</a>. As a high performance alternative,
88591 * please use p5.js geometry primitives.
88592 * @private
88593 * @method beginShape
88594 * @param {Number} mode webgl primitives mode. beginShape supports the
88595 * following modes:
88596 * POINTS,LINES,LINE_STRIP,LINE_LOOP,TRIANGLES,
88597 * TRIANGLE_STRIP, TRIANGLE_FAN and TESS(WEBGL only)
88598 * @chainable
88599 */ _main.default.RendererGL.prototype.beginShape = function(mode) {
88600 this.immediateMode.shapeMode =
88601 mode !== undefined ? mode : constants.TRIANGLE_FAN;
88602 this.immediateMode.geometry.reset();
88603 return this;
88604 };
88605 /**
88606 * adds a vertex to be drawn in a custom Shape.
88607 * @private
88608 * @method vertex
88609 * @param {Number} x x-coordinate of vertex
88610 * @param {Number} y y-coordinate of vertex
88611 * @param {Number} z z-coordinate of vertex
88612 * @chainable
88613 * @TODO implement handling of <a href="#/p5.Vector">p5.Vector</a> args
88614 */ _main.default.RendererGL.prototype.vertex = function(x, y) {
88615 var z, u, v;
88616
88617 // default to (x, y) mode: all other arugments assumed to be 0.
88618 z = u = v = 0;
88619
88620 if (arguments.length === 3) {
88621 // (x, y, z) mode: (u, v) assumed to be 0.
88622 z = arguments[2];
88623 } else if (arguments.length === 4) {
88624 // (x, y, u, v) mode: z assumed to be 0.
88625 u = arguments[2];
88626 v = arguments[3];
88627 } else if (arguments.length === 5) {
88628 // (x, y, z, u, v) mode
88629 z = arguments[2];
88630 u = arguments[3];
88631 v = arguments[4];
88632 }
88633 var vert = new _main.default.Vector(x, y, z);
88634 this.immediateMode.geometry.vertices.push(vert);
88635 var vertexColor = this.curFillColor || [0.5, 0.5, 0.5, 1.0];
88636 this.immediateMode.geometry.vertexColors.push(
88637 vertexColor[0],
88638 vertexColor[1],
88639 vertexColor[2],
88640 vertexColor[3]
88641 );
88642
88643 if (this.textureMode === constants.IMAGE) {
88644 if (this._tex !== null) {
88645 if (this._tex.width > 0 && this._tex.height > 0) {
88646 u /= this._tex.width;
88647 v /= this._tex.height;
88648 }
88649 } else if (this._tex === null && arguments.length >= 4) {
88650 // Only throw this warning if custom uv's have been provided
88651 console.warn(
88652 'You must first call texture() before using' +
88653 ' vertex() with image based u and v coordinates'
88654 );
88655 }
88656 }
88657
88658 this.immediateMode.geometry.uvs.push(u, v);
88659
88660 this.immediateMode._bezierVertex[0] = x;
88661 this.immediateMode._bezierVertex[1] = y;
88662 this.immediateMode._bezierVertex[2] = z;
88663
88664 this.immediateMode._quadraticVertex[0] = x;
88665 this.immediateMode._quadraticVertex[1] = y;
88666 this.immediateMode._quadraticVertex[2] = z;
88667
88668 return this;
88669 };
88670
88671 /**
88672 * End shape drawing and render vertices to screen.
88673 * @chainable
88674 */
88675 _main.default.RendererGL.prototype.endShape = function(
88676 mode,
88677 isCurve,
88678 isBezier,
88679 isQuadratic,
88680 isContour,
88681 shapeKind
88682 ) {
88683 if (this.immediateMode.shapeMode === constants.POINTS) {
88684 this._drawPoints(
88685 this.immediateMode.geometry.vertices,
88686 this.immediateMode.buffers.point
88687 );
88688
88689 return this;
88690 }
88691 this._processVertices.apply(this, arguments);
88692 if (this._doFill) {
88693 if (this.immediateMode.geometry.vertices.length > 1) {
88694 this._drawImmediateFill();
88695 }
88696 }
88697 if (this._doStroke) {
88698 if (this.immediateMode.geometry.lineVertices.length > 1) {
88699 this._drawImmediateStroke();
88700 }
88701 }
88702
88703 this.isBezier = false;
88704 this.isQuadratic = false;
88705 this.isCurve = false;
88706 this.immediateMode._bezierVertex.length = 0;
88707 this.immediateMode._quadraticVertex.length = 0;
88708 this.immediateMode._curveVertex.length = 0;
88709 return this;
88710 };
88711
88712 /**
88713 * Called from endShape(). This function calculates the stroke vertices for custom shapes and
88714 * tesselates shapes when applicable.
88715 * @private
88716 * @param {Number} mode webgl primitives mode. beginShape supports the
88717 * following modes:
88718 * POINTS,LINES,LINE_STRIP,LINE_LOOP,TRIANGLES,
88719 * TRIANGLE_STRIP, TRIANGLE_FAN and TESS(WEBGL only)
88720 */
88721 _main.default.RendererGL.prototype._processVertices = function(mode) {
88722 if (this.immediateMode.geometry.vertices.length === 0) return;
88723
88724 var calculateStroke = this._doStroke && this.drawMode !== constants.TEXTURE;
88725 var shouldClose = mode === constants.CLOSE;
88726 if (calculateStroke) {
88727 this.immediateMode.geometry.edges = this._calculateEdges(
88728 this.immediateMode.shapeMode,
88729 this.immediateMode.geometry.vertices,
88730 shouldClose
88731 );
88732
88733 this.immediateMode.geometry._edgesToVertices();
88734 }
88735 // For hollow shapes, user must set mode to TESS
88736 var convexShape = this.immediateMode.shapeMode === constants.TESS;
88737 // We tesselate when drawing curves or convex shapes
88738 var shouldTess =
88739 (this.isBezier || this.isQuadratic || this.isCurve || convexShape) &&
88740 this.immediateMode.shapeMode !== constants.LINES;
88741
88742 if (shouldTess) {
88743 this._tesselateShape();
88744 }
88745 };
88746
88747 /**
88748 * Called from _processVertices(). This function calculates the stroke vertices for custom shapes and
88749 * tesselates shapes when applicable.
88750 * @private
88751 * @returns {Array[Number]} indices for custom shape vertices indicating edges.
88752 */
88753 _main.default.RendererGL.prototype._calculateEdges = function(
88754 shapeMode,
88755 verts,
88756 shouldClose
88757 ) {
88758 var res = [];
88759 var i = 0;
88760 switch (shapeMode) {
88761 case constants.TRIANGLE_STRIP:
88762 for (i = 0; i < verts.length - 2; i++) {
88763 res.push([i, i + 1]);
88764 res.push([i, i + 2]);
88765 }
88766 res.push([i, i + 1]);
88767 break;
88768 case constants.TRIANGLES:
88769 for (i = 0; i < verts.length - 2; i = i + 3) {
88770 res.push([i, i + 1]);
88771 res.push([i + 1, i + 2]);
88772 res.push([i + 2, i]);
88773 }
88774 break;
88775 case constants.LINES:
88776 for (i = 0; i < verts.length - 1; i = i + 2) {
88777 res.push([i, i + 1]);
88778 }
88779 break;
88780 default:
88781 for (i = 0; i < verts.length - 1; i++) {
88782 res.push([i, i + 1]);
88783 }
88784 break;
88785 }
88786
88787 if (shouldClose) {
88788 res.push([verts.length - 1, 0]);
88789 }
88790 return res;
88791 };
88792
88793 /**
88794 * Called from _processVertices() when applicable. This function tesselates immediateMode.geometry.
88795 * @private
88796 */
88797 _main.default.RendererGL.prototype._tesselateShape = function() {
88798 this.immediateMode.shapeMode = constants.TRIANGLES;
88799 var contours = [
88800 new Float32Array(this._vToNArray(this.immediateMode.geometry.vertices))
88801 ];
88802
88803 var polyTriangles = this._triangulate(contours);
88804 this.immediateMode.geometry.vertices = [];
88805 for (
88806 var j = 0, polyTriLength = polyTriangles.length;
88807 j < polyTriLength;
88808 j = j + 3
88809 ) {
88810 this.vertex(polyTriangles[j], polyTriangles[j + 1], polyTriangles[j + 2]);
88811 }
88812 };
88813
88814 /**
88815 * Called from endShape(). Responsible for calculating normals, setting shader uniforms,
88816 * enabling all appropriate buffers, applying color blend, and drawing the fill geometry.
88817 * @private
88818 */
88819 _main.default.RendererGL.prototype._drawImmediateFill = function() {
88820 var gl = this.GL;
88821 var shader = this._getImmediateFillShader();
88822
88823 this._calculateNormals(this.immediateMode.geometry);
88824 this._setFillUniforms(shader);
88825 var _iteratorNormalCompletion = true;
88826 var _didIteratorError = false;
88827 var _iteratorError = undefined;
88828 try {
88829 for (
88830 var _iterator = this.immediateMode.buffers.fill[Symbol.iterator](), _step;
88831 !(_iteratorNormalCompletion = (_step = _iterator.next()).done);
88832 _iteratorNormalCompletion = true
88833 ) {
88834 var buff = _step.value;
88835 buff._prepareBuffer(this.immediateMode.geometry, shader);
88836 }
88837
88838 // LINE_STRIP and LINES are not used for rendering, instead
88839 // they only indicate a way to modify vertices during the _processVertices() step
88840 } catch (err) {
88841 _didIteratorError = true;
88842 _iteratorError = err;
88843 } finally {
88844 try {
88845 if (!_iteratorNormalCompletion && _iterator.return != null) {
88846 _iterator.return();
88847 }
88848 } finally {
88849 if (_didIteratorError) {
88850 throw _iteratorError;
88851 }
88852 }
88853 }
88854 if (
88855 this.immediateMode.shapeMode === constants.LINE_STRIP ||
88856 this.immediateMode.shapeMode === constants.LINES
88857 ) {
88858 this.immediateMode.shapeMode = constants.TRIANGLE_FAN;
88859 }
88860
88861 this._applyColorBlend(this.curFillColor);
88862 gl.drawArrays(
88863 this.immediateMode.shapeMode,
88864 0,
88865 this.immediateMode.geometry.vertices.length
88866 );
88867
88868 shader.unbindShader();
88869 };
88870
88871 /**
88872 * Called from endShape(). Responsible for calculating normals, setting shader uniforms,
88873 * enabling all appropriate buffers, applying color blend, and drawing the stroke geometry.
88874 * @private
88875 */
88876 _main.default.RendererGL.prototype._drawImmediateStroke = function() {
88877 var gl = this.GL;
88878 var shader = this._getImmediateStrokeShader();
88879 this._setStrokeUniforms(shader);
88880 var _iteratorNormalCompletion2 = true;
88881 var _didIteratorError2 = false;
88882 var _iteratorError2 = undefined;
88883 try {
88884 for (
88885 var _iterator2 = this.immediateMode.buffers.stroke[Symbol.iterator](),
88886 _step2;
88887 !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done);
88888 _iteratorNormalCompletion2 = true
88889 ) {
88890 var buff = _step2.value;
88891 buff._prepareBuffer(this.immediateMode.geometry, shader);
88892 }
88893 } catch (err) {
88894 _didIteratorError2 = true;
88895 _iteratorError2 = err;
88896 } finally {
88897 try {
88898 if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
88899 _iterator2.return();
88900 }
88901 } finally {
88902 if (_didIteratorError2) {
88903 throw _iteratorError2;
88904 }
88905 }
88906 }
88907 this._applyColorBlend(this.curStrokeColor);
88908 gl.drawArrays(gl.TRIANGLES, 0, this.immediateMode.geometry.lineVertices.length);
88909
88910 shader.unbindShader();
88911 };
88912
88913 /**
88914 * Called from _drawImmediateFill(). Currently adds default normals which
88915 * only work for flat shapes.
88916 * @parem
88917 * @private
88918 */
88919 _main.default.RendererGL.prototype._calculateNormals = function(geometry) {
88920 geometry.vertices.forEach(function() {
88921 geometry.vertexNormals.push(new _main.default.Vector(0, 0, 1));
88922 });
88923 };
88924 var _default = _main.default.RendererGL;
88925 exports.default = _default;
88926 },
88927 { '../core/constants': 43, '../core/main': 54, './p5.RenderBuffer': 105 }
88928 ],
88929 107: [
88930 function(_dereq_, module, exports) {
88931 'use strict';
88932 Object.defineProperty(exports, '__esModule', { value: true });
88933 exports.default = void 0;
88934
88935 var _main = _interopRequireDefault(_dereq_('../core/main'));
88936 _dereq_('./p5.RendererGL');
88937 _dereq_('./p5.RenderBuffer');
88938 function _interopRequireDefault(obj) {
88939 return obj && obj.__esModule ? obj : { default: obj };
88940 } //Retained Mode. The default mode for rendering 3D primitives
88941 //in WEBGL.
88942 var hashCount = 0;
88943 /**
88944 * _initBufferDefaults
88945 * @private
88946 * @description initializes buffer defaults. runs each time a new geometry is
88947 * registered
88948 * @param {String} gId key of the geometry object
88949 * @returns {Object} a new buffer object
88950 */
88951 _main.default.RendererGL.prototype._initBufferDefaults = function(gId) {
88952 this._freeBuffers(gId);
88953
88954 //@TODO remove this limit on hashes in retainedMode.geometry
88955 hashCount++;
88956 if (hashCount > 1000) {
88957 var key = Object.keys(this.retainedMode.geometry)[0];
88958 delete this.retainedMode.geometry[key];
88959 hashCount--;
88960 }
88961
88962 //create a new entry in our retainedMode.geometry
88963 return (this.retainedMode.geometry[gId] = {});
88964 };
88965
88966 _main.default.RendererGL.prototype._freeBuffers = function(gId) {
88967 var buffers = this.retainedMode.geometry[gId];
88968 if (!buffers) {
88969 return;
88970 }
88971
88972 delete this.retainedMode.geometry[gId];
88973 hashCount--;
88974
88975 var gl = this.GL;
88976 if (buffers.indexBuffer) {
88977 gl.deleteBuffer(buffers.indexBuffer);
88978 }
88979
88980 function freeBuffers(defs) {
88981 var _iteratorNormalCompletion = true;
88982 var _didIteratorError = false;
88983 var _iteratorError = undefined;
88984 try {
88985 for (
88986 var _iterator = defs[Symbol.iterator](), _step;
88987 !(_iteratorNormalCompletion = (_step = _iterator.next()).done);
88988 _iteratorNormalCompletion = true
88989 ) {
88990 var def = _step.value;
88991 if (buffers[def.dst]) {
88992 gl.deleteBuffer(buffers[def.dst]);
88993 buffers[def.dst] = null;
88994 }
88995 }
88996 } catch (err) {
88997 _didIteratorError = true;
88998 _iteratorError = err;
88999 } finally {
89000 try {
89001 if (!_iteratorNormalCompletion && _iterator.return != null) {
89002 _iterator.return();
89003 }
89004 } finally {
89005 if (_didIteratorError) {
89006 throw _iteratorError;
89007 }
89008 }
89009 }
89010 }
89011
89012 // free all the buffers
89013 freeBuffers(this.retainedMode.buffers.stroke);
89014 freeBuffers(this.retainedMode.buffers.fill);
89015 };
89016
89017 /**
89018 * creates a buffers object that holds the WebGL render buffers
89019 * for a geometry.
89020 * @private
89021 * @param {String} gId key of the geometry object
89022 * @param {p5.Geometry} model contains geometry data
89023 */
89024 _main.default.RendererGL.prototype.createBuffers = function(gId, model) {
89025 var gl = this.GL;
89026 //initialize the gl buffers for our geom groups
89027 var buffers = this._initBufferDefaults(gId);
89028 buffers.model = model;
89029
89030 var indexBuffer = buffers.indexBuffer;
89031
89032 if (model.faces.length) {
89033 // allocate space for faces
89034 if (!indexBuffer) indexBuffer = buffers.indexBuffer = gl.createBuffer();
89035 var vals = _main.default.RendererGL.prototype._flatten(model.faces);
89036 this._bindBuffer(indexBuffer, gl.ELEMENT_ARRAY_BUFFER, vals, Uint16Array);
89037
89038 // the vertex count is based on the number of faces
89039 buffers.vertexCount = model.faces.length * 3;
89040 } else {
89041 // the index buffer is unused, remove it
89042 if (indexBuffer) {
89043 gl.deleteBuffer(indexBuffer);
89044 buffers.indexBuffer = null;
89045 }
89046 // the vertex count comes directly from the model
89047 buffers.vertexCount = model.vertices ? model.vertices.length : 0;
89048 }
89049
89050 buffers.lineVertexCount = model.lineVertices ? model.lineVertices.length : 0;
89051
89052 return buffers;
89053 };
89054
89055 /**
89056 * Draws buffers given a geometry key ID
89057 * @private
89058 * @param {String} gId ID in our geom hash
89059 * @chainable
89060 */
89061 _main.default.RendererGL.prototype.drawBuffers = function(gId) {
89062 var gl = this.GL;
89063 var geometry = this.retainedMode.geometry[gId];
89064
89065 if (this._doStroke && geometry.lineVertexCount > 0) {
89066 var strokeShader = this._getRetainedStrokeShader();
89067 this._setStrokeUniforms(strokeShader);
89068 var _iteratorNormalCompletion2 = true;
89069 var _didIteratorError2 = false;
89070 var _iteratorError2 = undefined;
89071 try {
89072 for (
89073 var _iterator2 = this.retainedMode.buffers.stroke[Symbol.iterator](),
89074 _step2;
89075 !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done);
89076 _iteratorNormalCompletion2 = true
89077 ) {
89078 var buff = _step2.value;
89079 buff._prepareBuffer(geometry, strokeShader);
89080 }
89081 } catch (err) {
89082 _didIteratorError2 = true;
89083 _iteratorError2 = err;
89084 } finally {
89085 try {
89086 if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
89087 _iterator2.return();
89088 }
89089 } finally {
89090 if (_didIteratorError2) {
89091 throw _iteratorError2;
89092 }
89093 }
89094 }
89095 this._applyColorBlend(this.curStrokeColor);
89096 this._drawArrays(gl.TRIANGLES, gId);
89097 strokeShader.unbindShader();
89098 }
89099
89100 if (this._doFill) {
89101 var fillShader = this._getRetainedFillShader();
89102 this._setFillUniforms(fillShader);
89103 var _iteratorNormalCompletion3 = true;
89104 var _didIteratorError3 = false;
89105 var _iteratorError3 = undefined;
89106 try {
89107 for (
89108 var _iterator3 = this.retainedMode.buffers.fill[Symbol.iterator](),
89109 _step3;
89110 !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done);
89111 _iteratorNormalCompletion3 = true
89112 ) {
89113 var _buff = _step3.value;
89114 _buff._prepareBuffer(geometry, fillShader);
89115 }
89116 } catch (err) {
89117 _didIteratorError3 = true;
89118 _iteratorError3 = err;
89119 } finally {
89120 try {
89121 if (!_iteratorNormalCompletion3 && _iterator3.return != null) {
89122 _iterator3.return();
89123 }
89124 } finally {
89125 if (_didIteratorError3) {
89126 throw _iteratorError3;
89127 }
89128 }
89129 }
89130 if (geometry.indexBuffer) {
89131 //vertex index buffer
89132 this._bindBuffer(geometry.indexBuffer, gl.ELEMENT_ARRAY_BUFFER);
89133 }
89134 this._applyColorBlend(this.curFillColor);
89135 this._drawElements(gl.TRIANGLES, gId);
89136 fillShader.unbindShader();
89137 }
89138 return this;
89139 };
89140
89141 /**
89142 * Calls drawBuffers() with a scaled model/view matrix.
89143 *
89144 * This is used by various 3d primitive methods (in primitives.js, eg. plane,
89145 * box, torus, etc...) to allow caching of un-scaled geometries. Those
89146 * geometries are generally created with unit-length dimensions, cached as
89147 * such, and then scaled appropriately in this method prior to rendering.
89148 *
89149 * @private
89150 * @method drawBuffersScaled
89151 * @param {String} gId ID in our geom hash
89152 * @param {Number} scaleX the amount to scale in the X direction
89153 * @param {Number} scaleY the amount to scale in the Y direction
89154 * @param {Number} scaleZ the amount to scale in the Z direction
89155 */
89156 _main.default.RendererGL.prototype.drawBuffersScaled = function(
89157 gId,
89158 scaleX,
89159 scaleY,
89160 scaleZ
89161 ) {
89162 var uMVMatrix = this.uMVMatrix.copy();
89163 try {
89164 this.uMVMatrix.scale(scaleX, scaleY, scaleZ);
89165 this.drawBuffers(gId);
89166 } finally {
89167 this.uMVMatrix = uMVMatrix;
89168 }
89169 };
89170
89171 _main.default.RendererGL.prototype._drawArrays = function(drawMode, gId) {
89172 this.GL.drawArrays(
89173 drawMode,
89174 0,
89175 this.retainedMode.geometry[gId].lineVertexCount
89176 );
89177
89178 return this;
89179 };
89180
89181 _main.default.RendererGL.prototype._drawElements = function(drawMode, gId) {
89182 var buffers = this.retainedMode.geometry[gId];
89183 var gl = this.GL;
89184 // render the fill
89185 if (buffers.indexBuffer) {
89186 // we're drawing faces
89187 gl.drawElements(gl.TRIANGLES, buffers.vertexCount, gl.UNSIGNED_SHORT, 0);
89188 } else {
89189 // drawing vertices
89190 gl.drawArrays(drawMode || gl.TRIANGLES, 0, buffers.vertexCount);
89191 }
89192 };
89193
89194 _main.default.RendererGL.prototype._drawPoints = function(
89195 vertices,
89196 vertexBuffer
89197 ) {
89198 var gl = this.GL;
89199 var pointShader = this._getImmediatePointShader();
89200 this._setPointUniforms(pointShader);
89201
89202 this._bindBuffer(
89203 vertexBuffer,
89204 gl.ARRAY_BUFFER,
89205 this._vToNArray(vertices),
89206 Float32Array,
89207 gl.STATIC_DRAW
89208 );
89209
89210 pointShader.enableAttrib(pointShader.attributes.aPosition, 3);
89211
89212 gl.drawArrays(gl.Points, 0, vertices.length);
89213
89214 pointShader.unbindShader();
89215 };
89216 var _default = _main.default.RendererGL;
89217 exports.default = _default;
89218 },
89219 { '../core/main': 54, './p5.RenderBuffer': 105, './p5.RendererGL': 108 }
89220 ],
89221 108: [
89222 function(_dereq_, module, exports) {
89223 'use strict';
89224 function _typeof(obj) {
89225 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
89226 _typeof = function _typeof(obj) {
89227 return typeof obj;
89228 };
89229 } else {
89230 _typeof = function _typeof(obj) {
89231 return obj &&
89232 typeof Symbol === 'function' &&
89233 obj.constructor === Symbol &&
89234 obj !== Symbol.prototype
89235 ? 'symbol'
89236 : typeof obj;
89237 };
89238 }
89239 return _typeof(obj);
89240 }
89241 Object.defineProperty(exports, '__esModule', { value: true });
89242 exports.default = void 0;
89243 var _main = _interopRequireDefault(_dereq_('../core/main'));
89244 var constants = _interopRequireWildcard(_dereq_('../core/constants'));
89245 var _libtess = _interopRequireDefault(_dereq_('libtess'));
89246 _dereq_('./p5.Shader');
89247 _dereq_('./p5.Camera');
89248 _dereq_('../core/p5.Renderer');
89249 _dereq_('./p5.Matrix');
89250
89251 var _path = _dereq_('path');
89252 function _getRequireWildcardCache() {
89253 if (typeof WeakMap !== 'function') return null;
89254 var cache = new WeakMap();
89255 _getRequireWildcardCache = function _getRequireWildcardCache() {
89256 return cache;
89257 };
89258 return cache;
89259 }
89260 function _interopRequireWildcard(obj) {
89261 if (obj && obj.__esModule) {
89262 return obj;
89263 }
89264 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) {
89265 return { default: obj };
89266 }
89267 var cache = _getRequireWildcardCache();
89268 if (cache && cache.has(obj)) {
89269 return cache.get(obj);
89270 }
89271 var newObj = {};
89272 var hasPropertyDescriptor =
89273 Object.defineProperty && Object.getOwnPropertyDescriptor;
89274 for (var key in obj) {
89275 if (Object.prototype.hasOwnProperty.call(obj, key)) {
89276 var desc = hasPropertyDescriptor
89277 ? Object.getOwnPropertyDescriptor(obj, key)
89278 : null;
89279 if (desc && (desc.get || desc.set)) {
89280 Object.defineProperty(newObj, key, desc);
89281 } else {
89282 newObj[key] = obj[key];
89283 }
89284 }
89285 }
89286 newObj.default = obj;
89287 if (cache) {
89288 cache.set(obj, newObj);
89289 }
89290 return newObj;
89291 }
89292 function _interopRequireDefault(obj) {
89293 return obj && obj.__esModule ? obj : { default: obj };
89294 }
89295 function _toConsumableArray(arr) {
89296 return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread();
89297 }
89298 function _nonIterableSpread() {
89299 throw new TypeError('Invalid attempt to spread non-iterable instance');
89300 }
89301 function _iterableToArray(iter) {
89302 if (
89303 Symbol.iterator in Object(iter) ||
89304 Object.prototype.toString.call(iter) === '[object Arguments]'
89305 )
89306 return Array.from(iter);
89307 }
89308 function _arrayWithoutHoles(arr) {
89309 if (Array.isArray(arr)) {
89310 for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) {
89311 arr2[i] = arr[i];
89312 }
89313 return arr2;
89314 }
89315 }
89316
89317 var lightingShader =
89318 'precision highp float;\nprecision highp int;\n\nuniform mat4 uViewMatrix;\n\nuniform bool uUseLighting;\n\nuniform int uAmbientLightCount;\nuniform vec3 uAmbientColor[5];\n\nuniform int uDirectionalLightCount;\nuniform vec3 uLightingDirection[5];\nuniform vec3 uDirectionalDiffuseColors[5];\nuniform vec3 uDirectionalSpecularColors[5];\n\nuniform int uPointLightCount;\nuniform vec3 uPointLightLocation[5];\nuniform vec3 uPointLightDiffuseColors[5];\t\nuniform vec3 uPointLightSpecularColors[5];\n\nuniform int uSpotLightCount;\nuniform float uSpotLightAngle[5];\nuniform float uSpotLightConc[5];\nuniform vec3 uSpotLightDiffuseColors[5];\nuniform vec3 uSpotLightSpecularColors[5];\nuniform vec3 uSpotLightLocation[5];\nuniform vec3 uSpotLightDirection[5];\n\nuniform bool uSpecular;\nuniform float uShininess;\n\nuniform float uConstantAttenuation;\nuniform float uLinearAttenuation;\nuniform float uQuadraticAttenuation;\n\nconst float specularFactor = 2.0;\nconst float diffuseFactor = 0.73;\n\nstruct LightResult {\n float specular;\n float diffuse;\n};\n\nfloat _phongSpecular(\n vec3 lightDirection,\n vec3 viewDirection,\n vec3 surfaceNormal,\n float shininess) {\n\n vec3 R = reflect(lightDirection, surfaceNormal);\n return pow(max(0.0, dot(R, viewDirection)), shininess);\n}\n\nfloat _lambertDiffuse(vec3 lightDirection, vec3 surfaceNormal) {\n return max(0.0, dot(-lightDirection, surfaceNormal));\n}\n\nLightResult _light(vec3 viewDirection, vec3 normal, vec3 lightVector) {\n\n vec3 lightDir = normalize(lightVector);\n\n //compute our diffuse & specular terms\n LightResult lr;\n if (uSpecular)\n lr.specular = _phongSpecular(lightDir, viewDirection, normal, uShininess);\n lr.diffuse = _lambertDiffuse(lightDir, normal);\n return lr;\n}\n\nvoid totalLight(\n vec3 modelPosition,\n vec3 normal,\n out vec3 totalDiffuse,\n out vec3 totalSpecular\n) {\n\n totalSpecular = vec3(0.0);\n\n if (!uUseLighting) {\n totalDiffuse = vec3(1.0);\n return;\n }\n\n totalDiffuse = vec3(0.0);\n\n vec3 viewDirection = normalize(-modelPosition);\n\n for (int j = 0; j < 5; j++) {\n if (j < uDirectionalLightCount) {\n vec3 lightVector = (uViewMatrix * vec4(uLightingDirection[j], 0.0)).xyz;\n vec3 lightColor = uDirectionalDiffuseColors[j];\n vec3 specularColor = uDirectionalSpecularColors[j];\n LightResult result = _light(viewDirection, normal, lightVector);\n totalDiffuse += result.diffuse * lightColor;\n totalSpecular += result.specular * lightColor * specularColor;\n }\n\n if (j < uPointLightCount) {\n vec3 lightPosition = (uViewMatrix * vec4(uPointLightLocation[j], 1.0)).xyz;\n vec3 lightVector = modelPosition - lightPosition;\n \n //calculate attenuation\n float lightDistance = length(lightVector);\n float lightFalloff = 1.0 / (uConstantAttenuation + lightDistance * uLinearAttenuation + (lightDistance * lightDistance) * uQuadraticAttenuation);\n vec3 lightColor = lightFalloff * uPointLightDiffuseColors[j];\n vec3 specularColor = lightFalloff * uPointLightSpecularColors[j];\n\n LightResult result = _light(viewDirection, normal, lightVector);\n totalDiffuse += result.diffuse * lightColor;\n totalSpecular += result.specular * lightColor * specularColor;\n }\n\n if(j < uSpotLightCount) {\n vec3 lightPosition = (uViewMatrix * vec4(uSpotLightLocation[j], 1.0)).xyz;\n vec3 lightVector = modelPosition - lightPosition;\n \n float lightDistance = length(lightVector);\n float lightFalloff = 1.0 / (uConstantAttenuation + lightDistance * uLinearAttenuation + (lightDistance * lightDistance) * uQuadraticAttenuation);\n\n vec3 lightDirection = (uViewMatrix * vec4(uSpotLightDirection[j], 0.0)).xyz;\n float spotDot = dot(normalize(lightVector), normalize(lightDirection));\n float spotFalloff;\n if(spotDot < uSpotLightAngle[j]) {\n spotFalloff = 0.0;\n }\n else {\n spotFalloff = pow(spotDot, uSpotLightConc[j]);\n }\n lightFalloff *= spotFalloff;\n\n vec3 lightColor = uSpotLightDiffuseColors[j];\n vec3 specularColor = uSpotLightSpecularColors[j];\n \n LightResult result = _light(viewDirection, normal, lightVector);\n \n totalDiffuse += result.diffuse * lightColor * lightFalloff;\n totalSpecular += result.specular * lightColor * specularColor * lightFalloff;\n }\n }\n\n totalDiffuse *= diffuseFactor;\n totalSpecular *= specularFactor;\n}\n';
89319
89320 var defaultShaders = {
89321 immediateVert:
89322 'attribute vec3 aPosition;\nattribute vec4 aVertexColor;\n\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\nuniform float uResolution;\nuniform float uPointSize;\n\nvarying vec4 vColor;\nvoid main(void) {\n vec4 positionVec4 = vec4(aPosition, 1.0);\n gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;\n vColor = aVertexColor;\n gl_PointSize = uPointSize;\n}\n',
89323
89324 vertexColorVert:
89325 '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',
89326
89327 vertexColorFrag:
89328 'precision mediump float;\nvarying vec4 vColor;\nvoid main(void) {\n gl_FragColor = vColor;\n}',
89329
89330 normalVert:
89331 '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',
89332 normalFrag:
89333 'precision mediump float;\nvarying vec3 vVertexNormal;\nvoid main(void) {\n gl_FragColor = vec4(vVertexNormal, 1.0);\n}',
89334 basicFrag:
89335 'precision mediump float;\nuniform vec4 uMaterialColor;\nvoid main(void) {\n gl_FragColor = uMaterialColor;\n}',
89336 lightVert:
89337 lightingShader +
89338 '// include lighting.glgl\n\nattribute vec3 aPosition;\nattribute vec3 aNormal;\nattribute vec2 aTexCoord;\n\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\nuniform mat3 uNormalMatrix;\n\nvarying highp vec2 vVertTexCoord;\nvarying vec3 vDiffuseColor;\nvarying vec3 vSpecularColor;\n\nvoid main(void) {\n\n vec4 viewModelPosition = uModelViewMatrix * vec4(aPosition, 1.0);\n gl_Position = uProjectionMatrix * viewModelPosition;\n\n vec3 vertexNormal = normalize(uNormalMatrix * aNormal);\n vVertTexCoord = aTexCoord;\n\n totalLight(viewModelPosition.xyz, vertexNormal, vDiffuseColor, vSpecularColor);\n\n for (int i = 0; i < 8; i++) {\n if (i < uAmbientLightCount) {\n vDiffuseColor += uAmbientColor[i];\n }\n }\n}\n',
89339
89340 lightTextureFrag:
89341 'precision highp float;\n\nuniform vec4 uMaterialColor;\nuniform vec4 uTint;\nuniform sampler2D uSampler;\nuniform bool isTexture;\nuniform bool uEmissive;\n\nvarying highp vec2 vVertTexCoord;\nvarying vec3 vDiffuseColor;\nvarying vec3 vSpecularColor;\n\nvoid main(void) {\n if(uEmissive && !isTexture) {\n gl_FragColor = uMaterialColor;\n }\n else {\n gl_FragColor = isTexture ? texture2D(uSampler, vVertTexCoord) * (uTint / vec4(255, 255, 255, 255)) : uMaterialColor;\n gl_FragColor.rgb = gl_FragColor.rgb * vDiffuseColor + vSpecularColor;\n }\n}',
89342
89343 phongVert:
89344 'precision highp float;\nprecision highp int;\n\nattribute vec3 aPosition;\nattribute vec3 aNormal;\nattribute vec2 aTexCoord;\n\nuniform vec3 uAmbientColor[5];\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);\n\n // Pass varyings to fragment shader\n vViewPosition = viewModelPosition.xyz;\n gl_Position = uProjectionMatrix * viewModelPosition; \n\n vNormal = uNormalMatrix * aNormal;\n vTexCoord = aTexCoord;\n\n // TODO: this should be a uniform\n vAmbientColor = vec3(0.0);\n for (int i = 0; i < 5; i++) {\n if (i < uAmbientLightCount) {\n vAmbientColor += uAmbientColor[i];\n }\n }\n}\n',
89345 phongFrag:
89346 lightingShader +
89347 '// include lighting.glsl\nprecision highp float;\nprecision highp int;\n\nuniform vec4 uMaterialColor;\nuniform vec4 uTint;\nuniform sampler2D uSampler;\nuniform bool isTexture;\nuniform bool uEmissive;\n\nvarying vec3 vNormal;\nvarying vec2 vTexCoord;\nvarying vec3 vViewPosition;\nvarying vec3 vAmbientColor;\n\nvoid main(void) {\n\n vec3 diffuse;\n vec3 specular;\n totalLight(vViewPosition, normalize(vNormal), diffuse, specular);\n\n if(uEmissive && !isTexture) {\n gl_FragColor = uMaterialColor;\n }\n else {\n gl_FragColor = isTexture ? texture2D(uSampler, vTexCoord) * (uTint / vec4(255, 255, 255, 255)) : uMaterialColor;\n gl_FragColor.rgb = gl_FragColor.rgb * (diffuse + vAmbientColor) + specular;\n }\n}',
89348
89349 fontVert:
89350 "precision mediump float;\n\nattribute vec3 aPosition;\nattribute vec2 aTexCoord;\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\n\nuniform vec4 uGlyphRect;\nuniform float uGlyphOffset;\n\nvarying vec2 vTexCoord;\nvarying float w;\n\nvoid main() {\n vec4 positionVec4 = vec4(aPosition, 1.0);\n\n // scale by the size of the glyph's rectangle\n positionVec4.xy *= uGlyphRect.zw - uGlyphRect.xy;\n\n // move to the corner of the glyph\n positionVec4.xy += uGlyphRect.xy;\n\n // move to the letter's line offset\n positionVec4.x += uGlyphOffset;\n \n gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;\n vTexCoord = aTexCoord;\n w = gl_Position.w;\n}\n",
89351 fontFrag:
89352 "#extension GL_OES_standard_derivatives : enable\nprecision mediump float;\n\n#if 0\n // simulate integer math using floats\n\t#define int float\n\t#define ivec2 vec2\n\t#define INT(x) float(x)\n\n\tint ifloor(float v) { return floor(v); }\n\tivec2 ifloor(vec2 v) { return floor(v); }\n\n#else\n // use native integer math\n\tprecision highp int;\n\t#define INT(x) x\n\n\tint ifloor(float v) { return int(v); }\n\tint ifloor(int v) { return v; }\n\tivec2 ifloor(vec2 v) { return ivec2(v); }\n\n#endif\n\nuniform sampler2D uSamplerStrokes;\nuniform sampler2D uSamplerRowStrokes;\nuniform sampler2D uSamplerRows;\nuniform sampler2D uSamplerColStrokes;\nuniform sampler2D uSamplerCols;\n\nuniform ivec2 uStrokeImageSize;\nuniform ivec2 uCellsImageSize;\nuniform ivec2 uGridImageSize;\n\nuniform ivec2 uGridOffset;\nuniform ivec2 uGridSize;\nuniform vec4 uMaterialColor;\n\nvarying vec2 vTexCoord;\n\n// some helper functions\nint round(float v) { return ifloor(v + 0.5); }\nivec2 round(vec2 v) { return ifloor(v + 0.5); }\nfloat saturate(float v) { return clamp(v, 0.0, 1.0); }\nvec2 saturate(vec2 v) { return clamp(v, 0.0, 1.0); }\n\nint mul(float v1, int v2) {\n return ifloor(v1 * float(v2));\n}\n\nivec2 mul(vec2 v1, ivec2 v2) {\n return ifloor(v1 * vec2(v2) + 0.5);\n}\n\n// unpack a 16-bit integer from a float vec2\nint getInt16(vec2 v) {\n ivec2 iv = round(v * 255.0);\n return iv.x * INT(128) + iv.y;\n}\n\nvec2 pixelScale;\nvec2 coverage = vec2(0.0);\nvec2 weight = vec2(0.5);\nconst float minDistance = 1.0/8192.0;\nconst float hardness = 1.05; // amount of antialias\n\n// the maximum number of curves in a glyph\nconst int N = INT(250);\n\n// retrieves an indexed pixel from a sampler\nvec4 getTexel(sampler2D sampler, int pos, ivec2 size) {\n int width = size.x;\n int y = ifloor(pos / width);\n int x = pos - y * width; // pos % width\n\n return texture2D(sampler, (vec2(x, y) + 0.5) / vec2(size));\n}\n\nvoid calulateCrossings(vec2 p0, vec2 p1, vec2 p2, out vec2 C1, out vec2 C2) {\n\n // get the coefficients of the quadratic in t\n vec2 a = p0 - p1 * 2.0 + p2;\n vec2 b = p0 - p1;\n vec2 c = p0 - vTexCoord;\n\n // found out which values of 't' it crosses the axes\n vec2 surd = sqrt(max(vec2(0.0), b * b - a * c));\n vec2 t1 = ((b - surd) / a).yx;\n vec2 t2 = ((b + surd) / a).yx;\n\n // approximate straight lines to avoid rounding errors\n if (abs(a.y) < 0.001)\n t1.x = t2.x = c.y / (2.0 * b.y);\n\n if (abs(a.x) < 0.001)\n t1.y = t2.y = c.x / (2.0 * b.x);\n\n // plug into quadratic formula to find the corrdinates of the crossings\n C1 = ((a * t1 - b * 2.0) * t1 + c) * pixelScale;\n C2 = ((a * t2 - b * 2.0) * t2 + c) * pixelScale;\n}\n\nvoid coverageX(vec2 p0, vec2 p1, vec2 p2) {\n\n vec2 C1, C2;\n calulateCrossings(p0, p1, p2, C1, C2);\n\n // determine on which side of the x-axis the points lie\n bool y0 = p0.y > vTexCoord.y;\n bool y1 = p1.y > vTexCoord.y;\n bool y2 = p2.y > vTexCoord.y;\n\n // could web be under the curve (after t1)?\n if (y1 ? !y2 : y0) {\n // add the coverage for t1\n coverage.x += saturate(C1.x + 0.5);\n // calculate the anti-aliasing for t1\n weight.x = min(weight.x, abs(C1.x));\n }\n\n // are we outside the curve (after t2)?\n if (y1 ? !y0 : y2) {\n // subtract the coverage for t2\n coverage.x -= saturate(C2.x + 0.5);\n // calculate the anti-aliasing for t2\n weight.x = min(weight.x, abs(C2.x));\n }\n}\n\n// this is essentially the same as coverageX, but with the axes swapped\nvoid coverageY(vec2 p0, vec2 p1, vec2 p2) {\n\n vec2 C1, C2;\n calulateCrossings(p0, p1, p2, C1, C2);\n\n bool x0 = p0.x > vTexCoord.x;\n bool x1 = p1.x > vTexCoord.x;\n bool x2 = p2.x > vTexCoord.x;\n\n if (x1 ? !x2 : x0) {\n coverage.y -= saturate(C1.y + 0.5);\n weight.y = min(weight.y, abs(C1.y));\n }\n\n if (x1 ? !x0 : x2) {\n coverage.y += saturate(C2.y + 0.5);\n weight.y = min(weight.y, abs(C2.y));\n }\n}\n\nvoid main() {\n\n // calculate the pixel scale based on screen-coordinates\n pixelScale = hardness / fwidth(vTexCoord);\n\n // which grid cell is this pixel in?\n ivec2 gridCoord = ifloor(vTexCoord * vec2(uGridSize));\n\n // intersect curves in this row\n {\n // the index into the row info bitmap\n int rowIndex = gridCoord.y + uGridOffset.y;\n // fetch the info texel\n vec4 rowInfo = getTexel(uSamplerRows, rowIndex, uGridImageSize);\n // unpack the rowInfo\n int rowStrokeIndex = getInt16(rowInfo.xy);\n int rowStrokeCount = getInt16(rowInfo.zw);\n\n for (int iRowStroke = INT(0); iRowStroke < N; iRowStroke++) {\n if (iRowStroke >= rowStrokeCount)\n break;\n\n // each stroke is made up of 3 points: the start and control point\n // and the start of the next curve.\n // fetch the indices of this pair of strokes:\n vec4 strokeIndices = getTexel(uSamplerRowStrokes, rowStrokeIndex++, uCellsImageSize);\n\n // unpack the stroke index\n int strokePos = getInt16(strokeIndices.xy);\n\n // fetch the two strokes\n vec4 stroke0 = getTexel(uSamplerStrokes, strokePos + INT(0), uStrokeImageSize);\n vec4 stroke1 = getTexel(uSamplerStrokes, strokePos + INT(1), uStrokeImageSize);\n\n // calculate the coverage\n coverageX(stroke0.xy, stroke0.zw, stroke1.xy);\n }\n }\n\n // intersect curves in this column\n {\n int colIndex = gridCoord.x + uGridOffset.x;\n vec4 colInfo = getTexel(uSamplerCols, colIndex, uGridImageSize);\n int colStrokeIndex = getInt16(colInfo.xy);\n int colStrokeCount = getInt16(colInfo.zw);\n \n for (int iColStroke = INT(0); iColStroke < N; iColStroke++) {\n if (iColStroke >= colStrokeCount)\n break;\n\n vec4 strokeIndices = getTexel(uSamplerColStrokes, colStrokeIndex++, uCellsImageSize);\n\n int strokePos = getInt16(strokeIndices.xy);\n vec4 stroke0 = getTexel(uSamplerStrokes, strokePos + INT(0), uStrokeImageSize);\n vec4 stroke1 = getTexel(uSamplerStrokes, strokePos + INT(1), uStrokeImageSize);\n coverageY(stroke0.xy, stroke0.zw, stroke1.xy);\n }\n }\n\n weight = saturate(1.0 - weight * 2.0);\n float distance = max(weight.x + weight.y, minDistance); // manhattan approx.\n float antialias = abs(dot(coverage, weight) / distance);\n float cover = min(abs(coverage.x), abs(coverage.y));\n gl_FragColor = uMaterialColor;\n gl_FragColor.a *= saturate(max(antialias, cover));\n}",
89353 lineVert:
89354 "/*\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;\nuniform int uPerspective;\n\nattribute vec4 aPosition;\nattribute vec4 aDirection;\n \nvoid main() {\n // using a scale <1 moves the lines towards the camera\n // in order to prevent popping effects due to half of\n // the line disappearing behind the geometry faces.\n vec3 scale = vec3(0.9995);\n\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 components 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 vec2 curPerspScale;\n\n if(uPerspective == 1) {\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 curPerspScale = (uProjectionMatrix * vec4(1, -1, 0, 0)).xy;\n } else {\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 curPerspScale = p.w / (0.5 * uViewport.zw);\n }\n\n gl_Position.xy = p.xy + offset.xy * curPerspScale;\n gl_Position.zw = p.zw;\n}\n",
89355 lineFrag:
89356 'precision mediump float;\nprecision mediump int;\n\nuniform vec4 uMaterialColor;\n\nvoid main() {\n gl_FragColor = uMaterialColor;\n}',
89357 pointVert:
89358 'attribute vec3 aPosition;\nuniform float uPointSize;\nvarying float vStrokeWeight;\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\nvoid main() {\n\tvec4 positionVec4 = vec4(aPosition, 1.0);\n\tgl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;\n\tgl_PointSize = uPointSize;\n\tvStrokeWeight = uPointSize;\n}',
89359 pointFrag:
89360 'precision mediump float;\nprecision mediump int;\nuniform vec4 uMaterialColor;\nvarying float vStrokeWeight;\n\nvoid main(){\n\tfloat mask = 0.0;\n\n\t// make a circular mask using the gl_PointCoord (goes from 0 - 1 on a point)\n // might be able to get a nicer edge on big strokeweights with smoothstep but slightly less performant\n\n\tmask = step(0.98, length(gl_PointCoord * 2.0 - 1.0));\n\n\t// if strokeWeight is 1 or less lets just draw a square\n\t// this prevents weird artifacting from carving circles when our points are really small\n\t// if strokeWeight is larger than 1, we just use it as is\n\n\tmask = mix(0.0, mask, clamp(floor(vStrokeWeight - 0.5),0.0,1.0));\n\n\t// throw away the borders of the mask\n // otherwise we get weird alpha blending issues\n\n\tif(mask > 0.98){\n discard;\n \t}\n\n \tgl_FragColor = vec4(uMaterialColor.rgb * (1.0 - mask), uMaterialColor.a) ;\n}'
89361 };
89362
89363 /**
89364 * 3D graphics class
89365 * @private
89366 * @class p5.RendererGL
89367 * @constructor
89368 * @extends p5.Renderer
89369 * @todo extend class to include public method for offscreen
89370 * rendering (FBO).
89371 */
89372 _main.default.RendererGL = function(elt, pInst, isMainCanvas, attr) {
89373 _main.default.Renderer.call(this, elt, pInst, isMainCanvas);
89374 this._setAttributeDefaults(pInst);
89375 this._initContext();
89376 this.isP3D = true; //lets us know we're in 3d mode
89377
89378 // This redundant property is useful in reminding you that you are
89379 // interacting with WebGLRenderingContext, still worth considering future removal
89380 this.GL = this.drawingContext;
89381 this._pInst._setProperty('drawingContext', this.drawingContext);
89382
89383 // erasing
89384 this._isErasing = false;
89385
89386 // lights
89387 this._enableLighting = false;
89388
89389 this.ambientLightColors = [];
89390 this.specularColors = [1, 1, 1];
89391
89392 this.directionalLightDirections = [];
89393 this.directionalLightDiffuseColors = [];
89394 this.directionalLightSpecularColors = [];
89395
89396 this.pointLightPositions = [];
89397 this.pointLightDiffuseColors = [];
89398 this.pointLightSpecularColors = [];
89399
89400 this.spotLightPositions = [];
89401 this.spotLightDirections = [];
89402 this.spotLightDiffuseColors = [];
89403 this.spotLightSpecularColors = [];
89404 this.spotLightAngle = [];
89405 this.spotLightConc = [];
89406
89407 this.drawMode = constants.FILL;
89408
89409 this.curFillColor = this._cachedFillStyle = [1, 1, 1, 1];
89410 this.curStrokeColor = this._cachedStrokeStyle = [0, 0, 0, 1];
89411
89412 this.curBlendMode = constants.BLEND;
89413 this._cachedBlendMode = undefined;
89414 this.blendExt = this.GL.getExtension('EXT_blend_minmax');
89415 this._isBlending = false;
89416
89417 this._useSpecularMaterial = false;
89418 this._useEmissiveMaterial = false;
89419 this._useNormalMaterial = false;
89420 this._useShininess = 1;
89421
89422 this._tint = [255, 255, 255, 255];
89423
89424 // lightFalloff variables
89425 this.constantAttenuation = 1;
89426 this.linearAttenuation = 0;
89427 this.quadraticAttenuation = 0;
89428
89429 /**
89430 * model view, projection, & normal
89431 * matrices
89432 */
89433 this.uMVMatrix = new _main.default.Matrix();
89434 this.uPMatrix = new _main.default.Matrix();
89435 this.uNMatrix = new _main.default.Matrix('mat3');
89436
89437 // Camera
89438 this._curCamera = new _main.default.Camera(this);
89439 this._curCamera._computeCameraDefaultSettings();
89440 this._curCamera._setDefaultCamera();
89441
89442 this._defaultLightShader = undefined;
89443 this._defaultImmediateModeShader = undefined;
89444 this._defaultNormalShader = undefined;
89445 this._defaultColorShader = undefined;
89446 this._defaultPointShader = undefined;
89447
89448 this.userFillShader = undefined;
89449 this.userStrokeShader = undefined;
89450 this.userPointShader = undefined;
89451
89452 // Default drawing is done in Retained Mode
89453 // Geometry and Material hashes stored here
89454 this.retainedMode = {
89455 geometry: {},
89456 buffers: {
89457 // prettier-ignore
89458 stroke: [
89459 new _main.default.RenderBuffer(3, 'lineVertices', 'lineVertexBuffer', 'aPosition', this, this._flatten),
89460 new _main.default.RenderBuffer(4, 'lineNormals', 'lineNormalBuffer', 'aDirection', this, this._flatten)],
89461
89462 // prettier-ignore
89463 fill: [
89464 new _main.default.RenderBuffer(3, 'vertices', 'vertexBuffer', 'aPosition', this, this._vToNArray),
89465 new _main.default.RenderBuffer(3, 'vertexNormals', 'normalBuffer', 'aNormal', this, this._vToNArray),
89466 new _main.default.RenderBuffer(4, 'vertexColors', 'colorBuffer', 'aMaterialColor', this),
89467 new _main.default.RenderBuffer(3, 'vertexAmbients', 'ambientBuffer', 'aAmbientColor', this),
89468 //new BufferDef(3, 'vertexSpeculars', 'specularBuffer', 'aSpecularColor'),
89469 new _main.default.RenderBuffer(2, 'uvs', 'uvBuffer', 'aTexCoord', this, this._flatten)],
89470
89471 // prettier-ignore
89472 text: [
89473 new _main.default.RenderBuffer(3, 'vertices', 'vertexBuffer', 'aPosition', this, this._vToNArray),
89474 new _main.default.RenderBuffer(2, 'uvs', 'uvBuffer', 'aTexCoord', this, this._flatten)]
89475 }
89476 };
89477
89478 // Imediate Mode
89479 // Geometry and Material hashes stored here
89480 this.immediateMode = {
89481 geometry: new _main.default.Geometry(),
89482 shapeMode: constants.TRIANGLE_FAN,
89483 _bezierVertex: [],
89484 _quadraticVertex: [],
89485 _curveVertex: [],
89486 buffers: {
89487 // prettier-ignore
89488 fill: [
89489 new _main.default.RenderBuffer(3, 'vertices', 'vertexBuffer', 'aPosition', this, this._vToNArray),
89490 new _main.default.RenderBuffer(3, 'vertexNormals', 'normalBuffer', 'aNormal', this, this._vToNArray),
89491 new _main.default.RenderBuffer(4, 'vertexColors', 'colorBuffer', 'aVertexColor', this),
89492 new _main.default.RenderBuffer(3, 'vertexAmbients', 'ambientBuffer', 'aAmbientColor', this),
89493 new _main.default.RenderBuffer(2, 'uvs', 'uvBuffer', 'aTexCoord', this, this._flatten)],
89494
89495 // prettier-ignore
89496 stroke: [
89497 new _main.default.RenderBuffer(3, 'lineVertices', 'lineVertexBuffer', 'aPosition', this, this._flatten),
89498 new _main.default.RenderBuffer(4, 'lineNormals', 'lineNormalBuffer', 'aDirection', this, this._flatten)],
89499
89500 point: this.GL.createBuffer()
89501 }
89502 };
89503
89504 this.pointSize = 5.0; //default point size
89505 this.curStrokeWeight = 1;
89506
89507 // array of textures created in this gl context via this.getTexture(src)
89508 this.textures = [];
89509
89510 this.textureMode = constants.IMAGE;
89511 // default wrap settings
89512 this.textureWrapX = constants.CLAMP;
89513 this.textureWrapY = constants.CLAMP;
89514 this._tex = null;
89515 this._curveTightness = 6;
89516
89517 // lookUpTable for coefficients needed to be calculated for bezierVertex, same are used for curveVertex
89518 this._lookUpTableBezier = [];
89519 // lookUpTable for coefficients needed to be calculated for quadraticVertex
89520 this._lookUpTableQuadratic = [];
89521
89522 // current curveDetail in the Bezier lookUpTable
89523 this._lutBezierDetail = 0;
89524 // current curveDetail in the Quadratic lookUpTable
89525 this._lutQuadraticDetail = 0;
89526
89527 this._tessy = this._initTessy();
89528
89529 this.fontInfos = {};
89530
89531 this._curShader = undefined;
89532
89533 return this;
89534 };
89535
89536 _main.default.RendererGL.prototype = Object.create(
89537 _main.default.Renderer.prototype
89538 );
89539
89540 //////////////////////////////////////////////
89541 // Setting
89542 //////////////////////////////////////////////
89543
89544 _main.default.RendererGL.prototype._setAttributeDefaults = function(pInst) {
89545 // See issue #3850, safer to enable AA in Safari
89546 var applyAA = navigator.userAgent.toLowerCase().includes('safari');
89547 var defaults = {
89548 alpha: true,
89549 depth: true,
89550 stencil: true,
89551 antialias: applyAA,
89552 premultipliedAlpha: false,
89553 preserveDrawingBuffer: true,
89554 perPixelLighting: true
89555 };
89556
89557 if (pInst._glAttributes === null) {
89558 pInst._glAttributes = defaults;
89559 } else {
89560 pInst._glAttributes = Object.assign(defaults, pInst._glAttributes);
89561 }
89562 return;
89563 };
89564
89565 _main.default.RendererGL.prototype._initContext = function() {
89566 try {
89567 this.drawingContext =
89568 this.canvas.getContext('webgl', this._pInst._glAttributes) ||
89569 this.canvas.getContext('experimental-webgl', this._pInst._glAttributes);
89570 if (this.drawingContext === null) {
89571 throw new Error('Error creating webgl context');
89572 } else {
89573 var gl = this.drawingContext;
89574 gl.enable(gl.DEPTH_TEST);
89575 gl.depthFunc(gl.LEQUAL);
89576 gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
89577 this._viewport = this.drawingContext.getParameter(
89578 this.drawingContext.VIEWPORT
89579 );
89580 }
89581 } catch (er) {
89582 throw er;
89583 }
89584 };
89585
89586 //This is helper function to reset the context anytime the attributes
89587 //are changed with setAttributes()
89588
89589 _main.default.RendererGL.prototype._resetContext = function(options, callback) {
89590 var w = this.width;
89591 var h = this.height;
89592 var defaultId = this.canvas.id;
89593 var isPGraphics = this._pInst instanceof _main.default.Graphics;
89594
89595 if (isPGraphics) {
89596 var pg = this._pInst;
89597 pg.canvas.parentNode.removeChild(pg.canvas);
89598 pg.canvas = document.createElement('canvas');
89599 var node = pg._pInst._userNode || document.body;
89600 node.appendChild(pg.canvas);
89601 _main.default.Element.call(pg, pg.canvas, pg._pInst);
89602 pg.width = w;
89603 pg.height = h;
89604 } else {
89605 var c = this.canvas;
89606 if (c) {
89607 c.parentNode.removeChild(c);
89608 }
89609 c = document.createElement('canvas');
89610 c.id = defaultId;
89611 if (this._pInst._userNode) {
89612 this._pInst._userNode.appendChild(c);
89613 } else {
89614 document.body.appendChild(c);
89615 }
89616 this._pInst.canvas = c;
89617 }
89618
89619 var renderer = new _main.default.RendererGL(
89620 this._pInst.canvas,
89621 this._pInst,
89622 !isPGraphics
89623 );
89624
89625 this._pInst._setProperty('_renderer', renderer);
89626 renderer.resize(w, h);
89627 renderer._applyDefaults();
89628
89629 if (!isPGraphics) {
89630 this._pInst._elements.push(renderer);
89631 }
89632
89633 if (typeof callback === 'function') {
89634 //setTimeout with 0 forces the task to the back of the queue, this ensures that
89635 //we finish switching out the renderer
89636 setTimeout(function() {
89637 callback.apply(window._renderer, options);
89638 }, 0);
89639 }
89640 };
89641 /**
89642 * @module Rendering
89643 * @submodule Rendering
89644 * @for p5
89645 */
89646 /**
89647 * Set attributes for the WebGL Drawing context.
89648 * This is a way of adjusting how the WebGL
89649 * renderer works to fine-tune the display and performance.
89650 *
89651 * Note that this will reinitialize the drawing context
89652 * if called after the WebGL canvas is made.
89653 *
89654 * If an object is passed as the parameter, all attributes
89655 * not declared in the object will be set to defaults.
89656 *
89657 * The available attributes are:
89658 * <br>
89659 * alpha - indicates if the canvas contains an alpha buffer
89660 * default is true
89661 *
89662 * depth - indicates whether the drawing buffer has a depth buffer
89663 * of at least 16 bits - default is true
89664 *
89665 * stencil - indicates whether the drawing buffer has a stencil buffer
89666 * of at least 8 bits
89667 *
89668 * antialias - indicates whether or not to perform anti-aliasing
89669 * default is false (true in Safari)
89670 *
89671 * premultipliedAlpha - indicates that the page compositor will assume
89672 * the drawing buffer contains colors with pre-multiplied alpha
89673 * default is false
89674 *
89675 * preserveDrawingBuffer - if true the buffers will not be cleared and
89676 * and will preserve their values until cleared or overwritten by author
89677 * (note that p5 clears automatically on draw loop)
89678 * default is true
89679 *
89680 * perPixelLighting - if true, per-pixel lighting will be used in the
89681 * lighting shader otherwise per-vertex lighting is used.
89682 * default is true.
89683 *
89684 * @method setAttributes
89685 * @for p5
89686 * @param {String} key Name of attribute
89687 * @param {Boolean} value New value of named attribute
89688 * @example
89689 * <div>
89690 * <code>
89691 * function setup() {
89692 * createCanvas(100, 100, WEBGL);
89693 * }
89694 *
89695 * function draw() {
89696 * background(255);
89697 * push();
89698 * rotateZ(frameCount * 0.02);
89699 * rotateX(frameCount * 0.02);
89700 * rotateY(frameCount * 0.02);
89701 * fill(0, 0, 0);
89702 * box(50);
89703 * pop();
89704 * }
89705 * </code>
89706 * </div>
89707 * <br>
89708 * Now with the antialias attribute set to true.
89709 * <br>
89710 * <div>
89711 * <code>
89712 * function setup() {
89713 * setAttributes('antialias', true);
89714 * createCanvas(100, 100, WEBGL);
89715 * }
89716 *
89717 * function draw() {
89718 * background(255);
89719 * push();
89720 * rotateZ(frameCount * 0.02);
89721 * rotateX(frameCount * 0.02);
89722 * rotateY(frameCount * 0.02);
89723 * fill(0, 0, 0);
89724 * box(50);
89725 * pop();
89726 * }
89727 * </code>
89728 * </div>
89729 *
89730 * <div>
89731 * <code>
89732 * // press the mouse button to disable perPixelLighting
89733 * function setup() {
89734 * createCanvas(100, 100, WEBGL);
89735 * noStroke();
89736 * fill(255);
89737 * }
89738 *
89739 * let lights = [
89740 * { c: '#f00', t: 1.12, p: 1.91, r: 0.2 },
89741 * { c: '#0f0', t: 1.21, p: 1.31, r: 0.2 },
89742 * { c: '#00f', t: 1.37, p: 1.57, r: 0.2 },
89743 * { c: '#ff0', t: 1.12, p: 1.91, r: 0.7 },
89744 * { c: '#0ff', t: 1.21, p: 1.31, r: 0.7 },
89745 * { c: '#f0f', t: 1.37, p: 1.57, r: 0.7 }
89746 * ];
89747 *
89748 * function draw() {
89749 * let t = millis() / 1000 + 1000;
89750 * background(0);
89751 * directionalLight(color('#222'), 1, 1, 1);
89752 *
89753 * for (let i = 0; i < lights.length; i++) {
89754 * let light = lights[i];
89755 * pointLight(
89756 * color(light.c),
89757 * p5.Vector.fromAngles(t * light.t, t * light.p, width * light.r)
89758 * );
89759 * }
89760 *
89761 * specularMaterial(255);
89762 * sphere(width * 0.1);
89763 *
89764 * rotateX(t * 0.77);
89765 * rotateY(t * 0.83);
89766 * rotateZ(t * 0.91);
89767 * torus(width * 0.3, width * 0.07, 24, 10);
89768 * }
89769 *
89770 * function mousePressed() {
89771 * setAttributes('perPixelLighting', false);
89772 * noStroke();
89773 * fill(255);
89774 * }
89775 * function mouseReleased() {
89776 * setAttributes('perPixelLighting', true);
89777 * noStroke();
89778 * fill(255);
89779 * }
89780 * </code>
89781 * </div>
89782 *
89783 * @alt a rotating cube with smoother edges
89784 */
89785 /**
89786 * @method setAttributes
89787 * @for p5
89788 * @param {Object} obj object with key-value pairs
89789 */
89790
89791 _main.default.prototype.setAttributes = function(key, value) {
89792 if (typeof this._glAttributes === 'undefined') {
89793 console.log(
89794 'You are trying to use setAttributes on a p5.Graphics object ' +
89795 'that does not use a WEBGL renderer.'
89796 );
89797
89798 return;
89799 }
89800 var unchanged = true;
89801 if (typeof value !== 'undefined') {
89802 //first time modifying the attributes
89803 if (this._glAttributes === null) {
89804 this._glAttributes = {};
89805 }
89806 if (this._glAttributes[key] !== value) {
89807 //changing value of previously altered attribute
89808 this._glAttributes[key] = value;
89809 unchanged = false;
89810 }
89811 //setting all attributes with some change
89812 } else if (key instanceof Object) {
89813 if (this._glAttributes !== key) {
89814 this._glAttributes = key;
89815 unchanged = false;
89816 }
89817 }
89818 //@todo_FES
89819 if (!this._renderer.isP3D || unchanged) {
89820 return;
89821 }
89822
89823 if (!this._setupDone) {
89824 for (var x in this._renderer.retainedMode.geometry) {
89825 if (this._renderer.retainedMode.geometry.hasOwnProperty(x)) {
89826 console.error(
89827 'Sorry, Could not set the attributes, you need to call setAttributes() ' +
89828 'before calling the other drawing methods in setup()'
89829 );
89830
89831 return;
89832 }
89833 }
89834 }
89835
89836 this.push();
89837 this._renderer._resetContext();
89838 this.pop();
89839
89840 if (this._renderer._curCamera) {
89841 this._renderer._curCamera._renderer = this._renderer;
89842 }
89843 };
89844
89845 /**
89846 * @class p5.RendererGL
89847 */
89848
89849 _main.default.RendererGL.prototype._update = function() {
89850 // reset model view and apply initial camera transform
89851 // (containing only look at info; no projection).
89852 this.uMVMatrix.set(
89853 this._curCamera.cameraMatrix.mat4[0],
89854 this._curCamera.cameraMatrix.mat4[1],
89855 this._curCamera.cameraMatrix.mat4[2],
89856 this._curCamera.cameraMatrix.mat4[3],
89857 this._curCamera.cameraMatrix.mat4[4],
89858 this._curCamera.cameraMatrix.mat4[5],
89859 this._curCamera.cameraMatrix.mat4[6],
89860 this._curCamera.cameraMatrix.mat4[7],
89861 this._curCamera.cameraMatrix.mat4[8],
89862 this._curCamera.cameraMatrix.mat4[9],
89863 this._curCamera.cameraMatrix.mat4[10],
89864 this._curCamera.cameraMatrix.mat4[11],
89865 this._curCamera.cameraMatrix.mat4[12],
89866 this._curCamera.cameraMatrix.mat4[13],
89867 this._curCamera.cameraMatrix.mat4[14],
89868 this._curCamera.cameraMatrix.mat4[15]
89869 );
89870
89871 // reset light data for new frame.
89872
89873 this.ambientLightColors.length = 0;
89874 this.specularColors = [1, 1, 1];
89875
89876 this.directionalLightDirections.length = 0;
89877 this.directionalLightDiffuseColors.length = 0;
89878 this.directionalLightSpecularColors.length = 0;
89879
89880 this.pointLightPositions.length = 0;
89881 this.pointLightDiffuseColors.length = 0;
89882 this.pointLightSpecularColors.length = 0;
89883
89884 this.spotLightPositions.length = 0;
89885 this.spotLightDirections.length = 0;
89886 this.spotLightDiffuseColors.length = 0;
89887 this.spotLightSpecularColors.length = 0;
89888 this.spotLightAngle.length = 0;
89889 this.spotLightConc.length = 0;
89890
89891 this._enableLighting = false;
89892
89893 //reset tint value for new frame
89894 this._tint = [255, 255, 255, 255];
89895
89896 //Clear depth every frame
89897 this.GL.clear(this.GL.DEPTH_BUFFER_BIT);
89898 };
89899
89900 /**
89901 * [background description]
89902 */
89903 _main.default.RendererGL.prototype.background = function() {
89904 var _this$_pInst;
89905 var _col = (_this$_pInst = this._pInst).color.apply(_this$_pInst, arguments);
89906 var _r = _col.levels[0] / 255;
89907 var _g = _col.levels[1] / 255;
89908 var _b = _col.levels[2] / 255;
89909 var _a = _col.levels[3] / 255;
89910 this.GL.clearColor(_r, _g, _b, _a);
89911
89912 this.GL.clear(this.GL.COLOR_BUFFER_BIT);
89913 };
89914
89915 //////////////////////////////////////////////
89916 // COLOR
89917 //////////////////////////////////////////////
89918 /**
89919 * Basic fill material for geometry with a given color
89920 * @method fill
89921 * @class p5.RendererGL
89922 * @param {Number|Number[]|String|p5.Color} v1 gray value,
89923 * red or hue value (depending on the current color mode),
89924 * or color Array, or CSS color string
89925 * @param {Number} [v2] green or saturation value
89926 * @param {Number} [v3] blue or brightness value
89927 * @param {Number} [a] opacity
89928 * @chainable
89929 * @example
89930 * <div>
89931 * <code>
89932 * function setup() {
89933 * createCanvas(200, 200, WEBGL);
89934 * }
89935 *
89936 * function draw() {
89937 * background(0);
89938 * noStroke();
89939 * fill(100, 100, 240);
89940 * rotateX(frameCount * 0.01);
89941 * rotateY(frameCount * 0.01);
89942 * box(75, 75, 75);
89943 * }
89944 * </code>
89945 * </div>
89946 *
89947 * @alt
89948 * black canvas with purple cube spinning
89949 */
89950 _main.default.RendererGL.prototype.fill = function(v1, v2, v3, a) {
89951 //see material.js for more info on color blending in webgl
89952 var color = _main.default.prototype.color.apply(this._pInst, arguments);
89953 this.curFillColor = color._array;
89954 this.drawMode = constants.FILL;
89955 this._useNormalMaterial = false;
89956 this._tex = null;
89957 };
89958
89959 /**
89960 * Basic stroke material for geometry with a given color
89961 * @method stroke
89962 * @param {Number|Number[]|String|p5.Color} v1 gray value,
89963 * red or hue value (depending on the current color mode),
89964 * or color Array, or CSS color string
89965 * @param {Number} [v2] green or saturation value
89966 * @param {Number} [v3] blue or brightness value
89967 * @param {Number} [a] opacity
89968 * @example
89969 * <div>
89970 * <code>
89971 * function setup() {
89972 * createCanvas(200, 200, WEBGL);
89973 * }
89974 *
89975 * function draw() {
89976 * background(0);
89977 * stroke(240, 150, 150);
89978 * fill(100, 100, 240);
89979 * rotateX(frameCount * 0.01);
89980 * rotateY(frameCount * 0.01);
89981 * box(75, 75, 75);
89982 * }
89983 * </code>
89984 * </div>
89985 *
89986 * @alt
89987 * black canvas with purple cube with pink outline spinning
89988 */
89989 _main.default.RendererGL.prototype.stroke = function(r, g, b, a) {
89990 //@todo allow transparency in stroking currently doesn't have
89991 //any impact and causes problems with specularMaterial
89992 arguments[3] = 255;
89993 var color = _main.default.prototype.color.apply(this._pInst, arguments);
89994 this.curStrokeColor = color._array;
89995 };
89996
89997 _main.default.RendererGL.prototype.strokeCap = function(cap) {
89998 // @TODO : to be implemented
89999 console.error('Sorry, strokeCap() is not yet implemented in WEBGL mode');
90000 };
90001
90002 _main.default.RendererGL.prototype.strokeJoin = function(join) {
90003 // @TODO : to be implemented
90004 // https://processing.org/reference/strokeJoin_.html
90005 console.error('Sorry, strokeJoin() is not yet implemented in WEBGL mode');
90006 };
90007
90008 _main.default.RendererGL.prototype.filter = function(filterType) {
90009 // filter can be achieved using custom shaders.
90010 // https://github.com/aferriss/p5jsShaderExamples
90011 // https://itp-xstory.github.io/p5js-shaders/#/
90012 console.error('filter() does not work in WEBGL mode');
90013 };
90014
90015 _main.default.RendererGL.prototype.blendMode = function(mode) {
90016 if (
90017 mode === constants.DARKEST ||
90018 mode === constants.LIGHTEST ||
90019 mode === constants.ADD ||
90020 mode === constants.BLEND ||
90021 mode === constants.SUBTRACT ||
90022 mode === constants.SCREEN ||
90023 mode === constants.EXCLUSION ||
90024 mode === constants.REPLACE ||
90025 mode === constants.MULTIPLY ||
90026 mode === constants.REMOVE
90027 )
90028 this.curBlendMode = mode;
90029 else if (
90030 mode === constants.BURN ||
90031 mode === constants.OVERLAY ||
90032 mode === constants.HARD_LIGHT ||
90033 mode === constants.SOFT_LIGHT ||
90034 mode === constants.DODGE
90035 ) {
90036 console.warn(
90037 'BURN, OVERLAY, HARD_LIGHT, SOFT_LIGHT, and DODGE only work for blendMode in 2D mode.'
90038 );
90039 }
90040 };
90041
90042 _main.default.RendererGL.prototype.erase = function(opacityFill, opacityStroke) {
90043 if (!this._isErasing) {
90044 this._applyBlendMode(constants.REMOVE);
90045 this._isErasing = true;
90046
90047 this._cachedFillStyle = this.curFillColor.slice();
90048 this.curFillColor = [1, 1, 1, opacityFill / 255];
90049
90050 this._cachedStrokeStyle = this.curStrokeColor.slice();
90051 this.curStrokeColor = [1, 1, 1, opacityStroke / 255];
90052 }
90053 };
90054
90055 _main.default.RendererGL.prototype.noErase = function() {
90056 if (this._isErasing) {
90057 this._isErasing = false;
90058 this.curFillColor = this._cachedFillStyle.slice();
90059 this.curStrokeColor = this._cachedStrokeStyle.slice();
90060 this.blendMode(this._cachedBlendMode);
90061 }
90062 };
90063
90064 /**
90065 * Change weight of stroke
90066 * @method strokeWeight
90067 * @param {Number} stroke weight to be used for drawing
90068 * @example
90069 * <div>
90070 * <code>
90071 * function setup() {
90072 * createCanvas(200, 400, WEBGL);
90073 * setAttributes('antialias', true);
90074 * }
90075 *
90076 * function draw() {
90077 * background(0);
90078 * noStroke();
90079 * translate(0, -100, 0);
90080 * stroke(240, 150, 150);
90081 * fill(100, 100, 240);
90082 * push();
90083 * strokeWeight(8);
90084 * rotateX(frameCount * 0.01);
90085 * rotateY(frameCount * 0.01);
90086 * sphere(75);
90087 * pop();
90088 * push();
90089 * translate(0, 200, 0);
90090 * strokeWeight(1);
90091 * rotateX(frameCount * 0.01);
90092 * rotateY(frameCount * 0.01);
90093 * sphere(75);
90094 * pop();
90095 * }
90096 * </code>
90097 * </div>
90098 *
90099 * @alt
90100 * black canvas with two purple rotating spheres with pink
90101 * outlines the sphere on top has much heavier outlines,
90102 */
90103 _main.default.RendererGL.prototype.strokeWeight = function(w) {
90104 if (this.curStrokeWeight !== w) {
90105 this.pointSize = w;
90106 this.curStrokeWeight = w;
90107 }
90108 };
90109
90110 // x,y are canvas-relative (pre-scaled by _pixelDensity)
90111 _main.default.RendererGL.prototype._getPixel = function(x, y) {
90112 var imageData, index;
90113 imageData = new Uint8Array(4);
90114 // prettier-ignore
90115 this.drawingContext.readPixels(
90116 x, y, 1, 1,
90117 this.drawingContext.RGBA, this.drawingContext.UNSIGNED_BYTE,
90118 imageData);
90119
90120 index = 0;
90121 return [
90122 imageData[index + 0],
90123 imageData[index + 1],
90124 imageData[index + 2],
90125 imageData[index + 3]
90126 ];
90127 };
90128
90129 /**
90130 * Loads the pixels data for this canvas into the pixels[] attribute.
90131 * Note that updatePixels() and set() do not work.
90132 * Any pixel manipulation must be done directly to the pixels[] array.
90133 *
90134 * @private
90135 * @method loadPixels
90136 */
90137
90138 _main.default.RendererGL.prototype.loadPixels = function() {
90139 var pixelsState = this._pixelsState;
90140
90141 //@todo_FES
90142 if (this._pInst._glAttributes.preserveDrawingBuffer !== true) {
90143 console.log(
90144 'loadPixels only works in WebGL when preserveDrawingBuffer ' + 'is true.'
90145 );
90146
90147 return;
90148 }
90149
90150 //if there isn't a renderer-level temporary pixels buffer
90151 //make a new one
90152 var pixels = pixelsState.pixels;
90153 var len = this.GL.drawingBufferWidth * this.GL.drawingBufferHeight * 4;
90154 if (!(pixels instanceof Uint8Array) || pixels.length !== len) {
90155 pixels = new Uint8Array(len);
90156 this._pixelsState._setProperty('pixels', pixels);
90157 }
90158
90159 var pd = this._pInst._pixelDensity;
90160 // prettier-ignore
90161 this.GL.readPixels(
90162 0, 0, this.width * pd, this.height * pd,
90163 this.GL.RGBA, this.GL.UNSIGNED_BYTE,
90164 pixels);
90165 };
90166
90167 //////////////////////////////////////////////
90168 // HASH | for geometry
90169 //////////////////////////////////////////////
90170
90171 _main.default.RendererGL.prototype.geometryInHash = function(gId) {
90172 return this.retainedMode.geometry[gId] !== undefined;
90173 };
90174
90175 /**
90176 * [resize description]
90177 * @private
90178 * @param {Number} w [description]
90179 * @param {Number} h [description]
90180 */
90181 _main.default.RendererGL.prototype.resize = function(w, h) {
90182 _main.default.Renderer.prototype.resize.call(this, w, h);
90183 this.GL.viewport(0, 0, this.GL.drawingBufferWidth, this.GL.drawingBufferHeight);
90184
90185 this._viewport = this.GL.getParameter(this.GL.VIEWPORT);
90186
90187 this._curCamera._resize();
90188
90189 //resize pixels buffer
90190 var pixelsState = this._pixelsState;
90191 if (typeof pixelsState.pixels !== 'undefined') {
90192 pixelsState._setProperty(
90193 'pixels',
90194 new Uint8Array(this.GL.drawingBufferWidth * this.GL.drawingBufferHeight * 4)
90195 );
90196 }
90197 };
90198
90199 /**
90200 * clears color and depth buffers
90201 * with r,g,b,a
90202 * @private
90203 * @param {Number} r normalized red val.
90204 * @param {Number} g normalized green val.
90205 * @param {Number} b normalized blue val.
90206 * @param {Number} a normalized alpha val.
90207 */
90208 _main.default.RendererGL.prototype.clear = function() {
90209 var _r = (arguments.length <= 0 ? undefined : arguments[0]) || 0;
90210 var _g = (arguments.length <= 1 ? undefined : arguments[1]) || 0;
90211 var _b = (arguments.length <= 2 ? undefined : arguments[2]) || 0;
90212 var _a = (arguments.length <= 3 ? undefined : arguments[3]) || 0;
90213 this.GL.clearColor(_r, _g, _b, _a);
90214 this.GL.clear(this.GL.COLOR_BUFFER_BIT | this.GL.DEPTH_BUFFER_BIT);
90215 };
90216
90217 _main.default.RendererGL.prototype.applyMatrix = function(a, b, c, d, e, f) {
90218 if (arguments.length === 16) {
90219 _main.default.Matrix.prototype.apply.apply(this.uMVMatrix, arguments);
90220 } else {
90221 // prettier-ignore
90222 this.uMVMatrix.apply([
90223 a, b, 0, 0,
90224 c, d, 0, 0,
90225 0, 0, 1, 0,
90226 e, f, 0, 1]);
90227 }
90228 };
90229
90230 /**
90231 * [translate description]
90232 * @private
90233 * @param {Number} x [description]
90234 * @param {Number} y [description]
90235 * @param {Number} z [description]
90236 * @chainable
90237 * @todo implement handle for components or vector as args
90238 */
90239 _main.default.RendererGL.prototype.translate = function(x, y, z) {
90240 if (x instanceof _main.default.Vector) {
90241 z = x.z;
90242 y = x.y;
90243 x = x.x;
90244 }
90245 this.uMVMatrix.translate([x, y, z]);
90246 return this;
90247 };
90248
90249 /**
90250 * Scales the Model View Matrix by a vector
90251 * @private
90252 * @param {Number | p5.Vector | Array} x [description]
90253 * @param {Number} [y] y-axis scalar
90254 * @param {Number} [z] z-axis scalar
90255 * @chainable
90256 */
90257 _main.default.RendererGL.prototype.scale = function(x, y, z) {
90258 this.uMVMatrix.scale(x, y, z);
90259 return this;
90260 };
90261
90262 _main.default.RendererGL.prototype.rotate = function(rad, axis) {
90263 if (typeof axis === 'undefined') {
90264 return this.rotateZ(rad);
90265 }
90266 _main.default.Matrix.prototype.rotate.apply(this.uMVMatrix, arguments);
90267 return this;
90268 };
90269
90270 _main.default.RendererGL.prototype.rotateX = function(rad) {
90271 this.rotate(rad, 1, 0, 0);
90272 return this;
90273 };
90274
90275 _main.default.RendererGL.prototype.rotateY = function(rad) {
90276 this.rotate(rad, 0, 1, 0);
90277 return this;
90278 };
90279
90280 _main.default.RendererGL.prototype.rotateZ = function(rad) {
90281 this.rotate(rad, 0, 0, 1);
90282 return this;
90283 };
90284
90285 _main.default.RendererGL.prototype.push = function() {
90286 // get the base renderer style
90287 var style = _main.default.Renderer.prototype.push.apply(this);
90288
90289 // add webgl-specific style properties
90290 var properties = style.properties;
90291
90292 properties.uMVMatrix = this.uMVMatrix.copy();
90293 properties.uPMatrix = this.uPMatrix.copy();
90294 properties._curCamera = this._curCamera;
90295
90296 // make a copy of the current camera for the push state
90297 // this preserves any references stored using 'createCamera'
90298 this._curCamera = this._curCamera.copy();
90299
90300 properties.ambientLightColors = this.ambientLightColors.slice();
90301 properties.specularColors = this.specularColors.slice();
90302
90303 properties.directionalLightDirections = this.directionalLightDirections.slice();
90304 properties.directionalLightDiffuseColors = this.directionalLightDiffuseColors.slice();
90305 properties.directionalLightSpecularColors = this.directionalLightSpecularColors.slice();
90306
90307 properties.pointLightPositions = this.pointLightPositions.slice();
90308 properties.pointLightDiffuseColors = this.pointLightDiffuseColors.slice();
90309 properties.pointLightSpecularColors = this.pointLightSpecularColors.slice();
90310
90311 properties.spotLightPositions = this.spotLightPositions.slice();
90312 properties.spotLightDirections = this.spotLightDirections.slice();
90313 properties.spotLightDiffuseColors = this.spotLightDiffuseColors.slice();
90314 properties.spotLightSpecularColors = this.spotLightSpecularColors.slice();
90315 properties.spotLightAngle = this.spotLightAngle.slice();
90316 properties.spotLightConc = this.spotLightConc.slice();
90317
90318 properties.userFillShader = this.userFillShader;
90319 properties.userStrokeShader = this.userStrokeShader;
90320 properties.userPointShader = this.userPointShader;
90321
90322 properties.pointSize = this.pointSize;
90323 properties.curStrokeWeight = this.curStrokeWeight;
90324 properties.curStrokeColor = this.curStrokeColor;
90325 properties.curFillColor = this.curFillColor;
90326
90327 properties._useSpecularMaterial = this._useSpecularMaterial;
90328 properties._useEmissiveMaterial = this._useEmissiveMaterial;
90329 properties._useShininess = this._useShininess;
90330
90331 properties.constantAttenuation = this.constantAttenuation;
90332 properties.linearAttenuation = this.linearAttenuation;
90333 properties.quadraticAttenuation = this.quadraticAttenuation;
90334
90335 properties._enableLighting = this._enableLighting;
90336 properties._useNormalMaterial = this._useNormalMaterial;
90337 properties._tex = this._tex;
90338 properties.drawMode = this.drawMode;
90339
90340 return style;
90341 };
90342
90343 _main.default.RendererGL.prototype.resetMatrix = function() {
90344 this.uMVMatrix = _main.default.Matrix.identity(this._pInst);
90345 return this;
90346 };
90347
90348 //////////////////////////////////////////////
90349 // SHADER
90350 //////////////////////////////////////////////
90351
90352 /*
90353 * shaders are created and cached on a per-renderer basis,
90354 * on the grounds that each renderer will have its own gl context
90355 * and the shader must be valid in that context.
90356 */
90357
90358 _main.default.RendererGL.prototype._getImmediateStrokeShader = function() {
90359 // select the stroke shader to use
90360 var stroke = this.userStrokeShader;
90361 if (!stroke || !stroke.isStrokeShader()) {
90362 return this._getLineShader();
90363 }
90364 return stroke;
90365 };
90366
90367 _main.default.RendererGL.prototype._getRetainedStrokeShader =
90368 _main.default.RendererGL.prototype._getImmediateStrokeShader;
90369
90370 /*
90371 * selects which fill shader should be used based on renderer state,
90372 * for use with begin/endShape and immediate vertex mode.
90373 */
90374 _main.default.RendererGL.prototype._getImmediateFillShader = function() {
90375 var fill = this.userFillShader;
90376 if (this._useNormalMaterial) {
90377 if (!fill || !fill.isNormalShader()) {
90378 return this._getNormalShader();
90379 }
90380 }
90381 if (this._enableLighting) {
90382 if (!fill || !fill.isLightShader()) {
90383 return this._getLightShader();
90384 }
90385 } else if (this._tex) {
90386 if (!fill || !fill.isTextureShader()) {
90387 return this._getLightShader();
90388 }
90389 } else if (!fill /*|| !fill.isColorShader()*/) {
90390 return this._getImmediateModeShader();
90391 }
90392 return fill;
90393 };
90394
90395 /*
90396 * selects which fill shader should be used based on renderer state
90397 * for retained mode.
90398 */
90399 _main.default.RendererGL.prototype._getRetainedFillShader = function() {
90400 if (this._useNormalMaterial) {
90401 return this._getNormalShader();
90402 }
90403
90404 var fill = this.userFillShader;
90405 if (this._enableLighting) {
90406 if (!fill || !fill.isLightShader()) {
90407 return this._getLightShader();
90408 }
90409 } else if (this._tex) {
90410 if (!fill || !fill.isTextureShader()) {
90411 return this._getLightShader();
90412 }
90413 } else if (!fill /* || !fill.isColorShader()*/) {
90414 return this._getColorShader();
90415 }
90416 return fill;
90417 };
90418
90419 _main.default.RendererGL.prototype._getImmediatePointShader = function() {
90420 // select the point shader to use
90421 var point = this.userPointShader;
90422 if (!point || !point.isPointShader()) {
90423 return this._getPointShader();
90424 }
90425 return point;
90426 };
90427
90428 _main.default.RendererGL.prototype._getRetainedLineShader =
90429 _main.default.RendererGL.prototype._getImmediateLineShader;
90430
90431 _main.default.RendererGL.prototype._getLightShader = function() {
90432 if (!this._defaultLightShader) {
90433 if (this._pInst._glAttributes.perPixelLighting) {
90434 this._defaultLightShader = new _main.default.Shader(
90435 this,
90436 defaultShaders.phongVert,
90437 defaultShaders.phongFrag
90438 );
90439 } else {
90440 this._defaultLightShader = new _main.default.Shader(
90441 this,
90442 defaultShaders.lightVert,
90443 defaultShaders.lightTextureFrag
90444 );
90445 }
90446 }
90447
90448 return this._defaultLightShader;
90449 };
90450
90451 _main.default.RendererGL.prototype._getImmediateModeShader = function() {
90452 if (!this._defaultImmediateModeShader) {
90453 this._defaultImmediateModeShader = new _main.default.Shader(
90454 this,
90455 defaultShaders.immediateVert,
90456 defaultShaders.vertexColorFrag
90457 );
90458 }
90459
90460 return this._defaultImmediateModeShader;
90461 };
90462
90463 _main.default.RendererGL.prototype._getNormalShader = function() {
90464 if (!this._defaultNormalShader) {
90465 this._defaultNormalShader = new _main.default.Shader(
90466 this,
90467 defaultShaders.normalVert,
90468 defaultShaders.normalFrag
90469 );
90470 }
90471
90472 return this._defaultNormalShader;
90473 };
90474
90475 _main.default.RendererGL.prototype._getColorShader = function() {
90476 if (!this._defaultColorShader) {
90477 this._defaultColorShader = new _main.default.Shader(
90478 this,
90479 defaultShaders.normalVert,
90480 defaultShaders.basicFrag
90481 );
90482 }
90483
90484 return this._defaultColorShader;
90485 };
90486
90487 _main.default.RendererGL.prototype._getPointShader = function() {
90488 if (!this._defaultPointShader) {
90489 this._defaultPointShader = new _main.default.Shader(
90490 this,
90491 defaultShaders.pointVert,
90492 defaultShaders.pointFrag
90493 );
90494 }
90495 return this._defaultPointShader;
90496 };
90497
90498 _main.default.RendererGL.prototype._getLineShader = function() {
90499 if (!this._defaultLineShader) {
90500 this._defaultLineShader = new _main.default.Shader(
90501 this,
90502 defaultShaders.lineVert,
90503 defaultShaders.lineFrag
90504 );
90505 }
90506
90507 return this._defaultLineShader;
90508 };
90509
90510 _main.default.RendererGL.prototype._getFontShader = function() {
90511 if (!this._defaultFontShader) {
90512 this.GL.getExtension('OES_standard_derivatives');
90513 this._defaultFontShader = new _main.default.Shader(
90514 this,
90515 defaultShaders.fontVert,
90516 defaultShaders.fontFrag
90517 );
90518 }
90519 return this._defaultFontShader;
90520 };
90521
90522 _main.default.RendererGL.prototype._getEmptyTexture = function() {
90523 if (!this._emptyTexture) {
90524 // a plain white texture RGBA, full alpha, single pixel.
90525 var im = new _main.default.Image(1, 1);
90526 im.set(0, 0, 255);
90527 this._emptyTexture = new _main.default.Texture(this, im);
90528 }
90529 return this._emptyTexture;
90530 };
90531
90532 _main.default.RendererGL.prototype.getTexture = function(img) {
90533 var textures = this.textures;
90534 var _iteratorNormalCompletion = true;
90535 var _didIteratorError = false;
90536 var _iteratorError = undefined;
90537 try {
90538 for (
90539 var _iterator = textures[Symbol.iterator](), _step;
90540 !(_iteratorNormalCompletion = (_step = _iterator.next()).done);
90541 _iteratorNormalCompletion = true
90542 ) {
90543 var texture = _step.value;
90544 if (texture.src === img) return texture;
90545 }
90546 } catch (err) {
90547 _didIteratorError = true;
90548 _iteratorError = err;
90549 } finally {
90550 try {
90551 if (!_iteratorNormalCompletion && _iterator.return != null) {
90552 _iterator.return();
90553 }
90554 } finally {
90555 if (_didIteratorError) {
90556 throw _iteratorError;
90557 }
90558 }
90559 }
90560
90561 var tex = new _main.default.Texture(this, img);
90562 textures.push(tex);
90563 return tex;
90564 };
90565
90566 _main.default.RendererGL.prototype._setStrokeUniforms = function(strokeShader) {
90567 strokeShader.bindShader();
90568
90569 // set the uniform values
90570 strokeShader.setUniform('uMaterialColor', this.curStrokeColor);
90571 strokeShader.setUniform('uStrokeWeight', this.curStrokeWeight);
90572 };
90573
90574 _main.default.RendererGL.prototype._setFillUniforms = function(fillShader) {
90575 fillShader.bindShader();
90576
90577 // TODO: optimize
90578 fillShader.setUniform('uMaterialColor', this.curFillColor);
90579 fillShader.setUniform('isTexture', !!this._tex);
90580 if (this._tex) {
90581 fillShader.setUniform('uSampler', this._tex);
90582 }
90583 fillShader.setUniform('uTint', this._tint);
90584
90585 fillShader.setUniform('uSpecular', this._useSpecularMaterial);
90586 fillShader.setUniform('uEmissive', this._useEmissiveMaterial);
90587 fillShader.setUniform('uShininess', this._useShininess);
90588
90589 fillShader.setUniform('uUseLighting', this._enableLighting);
90590
90591 var pointLightCount = this.pointLightDiffuseColors.length / 3;
90592 fillShader.setUniform('uPointLightCount', pointLightCount);
90593 fillShader.setUniform('uPointLightLocation', this.pointLightPositions);
90594 fillShader.setUniform('uPointLightDiffuseColors', this.pointLightDiffuseColors);
90595
90596 fillShader.setUniform(
90597 'uPointLightSpecularColors',
90598 this.pointLightSpecularColors
90599 );
90600
90601 var directionalLightCount = this.directionalLightDiffuseColors.length / 3;
90602 fillShader.setUniform('uDirectionalLightCount', directionalLightCount);
90603 fillShader.setUniform('uLightingDirection', this.directionalLightDirections);
90604 fillShader.setUniform(
90605 'uDirectionalDiffuseColors',
90606 this.directionalLightDiffuseColors
90607 );
90608
90609 fillShader.setUniform(
90610 'uDirectionalSpecularColors',
90611 this.directionalLightSpecularColors
90612 );
90613
90614 // TODO: sum these here...
90615 var ambientLightCount = this.ambientLightColors.length / 3;
90616 fillShader.setUniform('uAmbientLightCount', ambientLightCount);
90617 fillShader.setUniform('uAmbientColor', this.ambientLightColors);
90618
90619 var spotLightCount = this.spotLightDiffuseColors.length / 3;
90620 fillShader.setUniform('uSpotLightCount', spotLightCount);
90621 fillShader.setUniform('uSpotLightAngle', this.spotLightAngle);
90622 fillShader.setUniform('uSpotLightConc', this.spotLightConc);
90623 fillShader.setUniform('uSpotLightDiffuseColors', this.spotLightDiffuseColors);
90624 fillShader.setUniform('uSpotLightSpecularColors', this.spotLightSpecularColors);
90625
90626 fillShader.setUniform('uSpotLightLocation', this.spotLightPositions);
90627 fillShader.setUniform('uSpotLightDirection', this.spotLightDirections);
90628
90629 fillShader.setUniform('uConstantAttenuation', this.constantAttenuation);
90630 fillShader.setUniform('uLinearAttenuation', this.linearAttenuation);
90631 fillShader.setUniform('uQuadraticAttenuation', this.quadraticAttenuation);
90632
90633 fillShader.bindTextures();
90634 };
90635
90636 _main.default.RendererGL.prototype._setPointUniforms = function(pointShader) {
90637 pointShader.bindShader();
90638
90639 // set the uniform values
90640 pointShader.setUniform('uMaterialColor', this.curStrokeColor);
90641 // @todo is there an instance where this isn't stroke weight?
90642 // should be they be same var?
90643 pointShader.setUniform('uPointSize', this.pointSize);
90644 };
90645
90646 /* Binds a buffer to the drawing context
90647 * when passed more than two arguments it also updates or initializes
90648 * the data associated with the buffer
90649 */
90650 _main.default.RendererGL.prototype._bindBuffer = function(
90651 buffer,
90652 target,
90653 values,
90654 type,
90655 usage
90656 ) {
90657 if (!target) target = this.GL.ARRAY_BUFFER;
90658 this.GL.bindBuffer(target, buffer);
90659 if (values !== undefined) {
90660 var data = new (type || Float32Array)(values);
90661 this.GL.bufferData(target, data, usage || this.GL.STATIC_DRAW);
90662 }
90663 };
90664
90665 ///////////////////////////////
90666 //// UTILITY FUNCTIONS
90667 //////////////////////////////
90668 _main.default.RendererGL.prototype._arraysEqual = function(a, b) {
90669 var aLength = a.length;
90670 if (aLength !== b.length) return false;
90671 for (var i = 0; i < aLength; i++) {
90672 if (a[i] !== b[i]) return false;
90673 }
90674 return true;
90675 };
90676
90677 _main.default.RendererGL.prototype._isTypedArray = function(arr) {
90678 var res = false;
90679 res = arr instanceof Float32Array;
90680 res = arr instanceof Float64Array;
90681 res = arr instanceof Int16Array;
90682 res = arr instanceof Uint16Array;
90683 res = arr instanceof Uint32Array;
90684 return res;
90685 };
90686 /**
90687 * turn a two dimensional array into one dimensional array
90688 * @private
90689 * @param {Array} arr 2-dimensional array
90690 * @return {Array} 1-dimensional array
90691 * [[1, 2, 3],[4, 5, 6]] -> [1, 2, 3, 4, 5, 6]
90692 */
90693 _main.default.RendererGL.prototype._flatten = function(arr) {
90694 //when empty, return empty
90695 if (arr.length === 0) {
90696 return [];
90697 } else if (arr.length > 20000) {
90698 //big models , load slower to avoid stack overflow
90699 //faster non-recursive flatten via axelduch
90700 //stackoverflow.com/questions/27266550/how-to-flatten-nested-array-in-javascript
90701 var _toString = Object.prototype.toString;
90702 var arrayTypeStr = '[object Array]';
90703 var result = [];
90704 var nodes = arr.slice();
90705 var node;
90706 node = nodes.pop();
90707 do {
90708 if (_toString.call(node) === arrayTypeStr) {
90709 nodes.push.apply(nodes, _toConsumableArray(node));
90710 } else {
90711 result.push(node);
90712 }
90713 } while (nodes.length && (node = nodes.pop()) !== undefined);
90714 result.reverse(); // we reverse result to restore the original order
90715 return result;
90716 } else {
90717 var _ref;
90718 //otherwise if model within limits for browser
90719 //use faster recursive loading
90720 return (_ref = []).concat.apply(_ref, _toConsumableArray(arr));
90721 }
90722 };
90723
90724 /**
90725 * turn a p5.Vector Array into a one dimensional number array
90726 * @private
90727 * @param {p5.Vector[]} arr an array of p5.Vector
90728 * @return {Number[]} a one dimensional array of numbers
90729 * [p5.Vector(1, 2, 3), p5.Vector(4, 5, 6)] ->
90730 * [1, 2, 3, 4, 5, 6]
90731 */
90732 _main.default.RendererGL.prototype._vToNArray = function(arr) {
90733 var ret = [];
90734 var _iteratorNormalCompletion2 = true;
90735 var _didIteratorError2 = false;
90736 var _iteratorError2 = undefined;
90737 try {
90738 for (
90739 var _iterator2 = arr[Symbol.iterator](), _step2;
90740 !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done);
90741 _iteratorNormalCompletion2 = true
90742 ) {
90743 var item = _step2.value;
90744 ret.push(item.x, item.y, item.z);
90745 }
90746 } catch (err) {
90747 _didIteratorError2 = true;
90748 _iteratorError2 = err;
90749 } finally {
90750 try {
90751 if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
90752 _iterator2.return();
90753 }
90754 } finally {
90755 if (_didIteratorError2) {
90756 throw _iteratorError2;
90757 }
90758 }
90759 }
90760
90761 return ret;
90762 };
90763
90764 /**
90765 * ensures that p5 is using a 3d renderer. throws an error if not.
90766 */
90767 _main.default.prototype._assert3d = function(name) {
90768 if (!this._renderer.isP3D)
90769 throw new Error(
90770 ''.concat(
90771 name,
90772 "() is only supported in WEBGL mode. If you'd like to use 3D graphics and WebGL, see https://p5js.org/examples/form-3d-primitives.html for more information."
90773 )
90774 );
90775 };
90776
90777 // function to initialize GLU Tesselator
90778
90779 _main.default.RendererGL.prototype._initTessy = function initTesselator() {
90780 // function called for each vertex of tesselator output
90781 function vertexCallback(data, polyVertArray) {
90782 polyVertArray[polyVertArray.length] = data[0];
90783 polyVertArray[polyVertArray.length] = data[1];
90784 polyVertArray[polyVertArray.length] = data[2];
90785 }
90786
90787 function begincallback(type) {
90788 if (type !== _libtess.default.primitiveType.GL_TRIANGLES) {
90789 console.log('expected TRIANGLES but got type: '.concat(type));
90790 }
90791 }
90792
90793 function errorcallback(errno) {
90794 console.log('error callback');
90795 console.log('error number: '.concat(errno));
90796 }
90797 // callback for when segments intersect and must be split
90798 function combinecallback(coords, data, weight) {
90799 return [coords[0], coords[1], coords[2]];
90800 }
90801
90802 function edgeCallback(flag) {
90803 // don't really care about the flag, but need no-strip/no-fan behavior
90804 }
90805
90806 var tessy = new _libtess.default.GluTesselator();
90807 tessy.gluTessCallback(
90808 _libtess.default.gluEnum.GLU_TESS_VERTEX_DATA,
90809 vertexCallback
90810 );
90811 tessy.gluTessCallback(_libtess.default.gluEnum.GLU_TESS_BEGIN, begincallback);
90812 tessy.gluTessCallback(_libtess.default.gluEnum.GLU_TESS_ERROR, errorcallback);
90813 tessy.gluTessCallback(
90814 _libtess.default.gluEnum.GLU_TESS_COMBINE,
90815 combinecallback
90816 );
90817 tessy.gluTessCallback(
90818 _libtess.default.gluEnum.GLU_TESS_EDGE_FLAG,
90819 edgeCallback
90820 );
90821
90822 return tessy;
90823 };
90824
90825 _main.default.RendererGL.prototype._triangulate = function(contours) {
90826 // libtess will take 3d verts and flatten to a plane for tesselation
90827 // since only doing 2d tesselation here, provide z=1 normal to skip
90828 // iterating over verts only to get the same answer.
90829 // comment out to test normal-generation code
90830 this._tessy.gluTessNormal(0, 0, 1);
90831
90832 var triangleVerts = [];
90833 this._tessy.gluTessBeginPolygon(triangleVerts);
90834
90835 for (var i = 0; i < contours.length; i++) {
90836 this._tessy.gluTessBeginContour();
90837 var contour = contours[i];
90838 for (var j = 0; j < contour.length; j += 3) {
90839 var coords = [contour[j], contour[j + 1], contour[j + 2]];
90840 this._tessy.gluTessVertex(coords, coords);
90841 }
90842 this._tessy.gluTessEndContour();
90843 }
90844
90845 // finish polygon
90846 this._tessy.gluTessEndPolygon();
90847
90848 return triangleVerts;
90849 };
90850
90851 // function to calculate BezierVertex Coefficients
90852 _main.default.RendererGL.prototype._bezierCoefficients = function(t) {
90853 var t2 = t * t;
90854 var t3 = t2 * t;
90855 var mt = 1 - t;
90856 var mt2 = mt * mt;
90857 var mt3 = mt2 * mt;
90858 return [mt3, 3 * mt2 * t, 3 * mt * t2, t3];
90859 };
90860
90861 // function to calculate QuadraticVertex Coefficients
90862 _main.default.RendererGL.prototype._quadraticCoefficients = function(t) {
90863 var t2 = t * t;
90864 var mt = 1 - t;
90865 var mt2 = mt * mt;
90866 return [mt2, 2 * mt * t, t2];
90867 };
90868
90869 // function to convert Bezier coordinates to Catmull Rom Splines
90870 _main.default.RendererGL.prototype._bezierToCatmull = function(w) {
90871 var p1 = w[1];
90872 var p2 = w[1] + (w[2] - w[0]) / this._curveTightness;
90873 var p3 = w[2] - (w[3] - w[1]) / this._curveTightness;
90874 var p4 = w[2];
90875 var p = [p1, p2, p3, p4];
90876 return p;
90877 };
90878 var _default = _main.default.RendererGL;
90879 exports.default = _default;
90880 },
90881 {
90882 '../core/constants': 43,
90883 '../core/main': 54,
90884 '../core/p5.Renderer': 57,
90885 './p5.Camera': 102,
90886 './p5.Matrix': 104,
90887 './p5.Shader': 109,
90888 libtess: 32,
90889 path: 35
90890 }
90891 ],
90892 109: [
90893 function(_dereq_, module, exports) {
90894 'use strict';
90895 Object.defineProperty(exports, '__esModule', { value: true });
90896 exports.default = void 0;
90897
90898 var _main = _interopRequireDefault(_dereq_('../core/main'));
90899 function _interopRequireDefault(obj) {
90900 return obj && obj.__esModule ? obj : { default: obj };
90901 }
90902 /**
90903 * This module defines the p5.Shader class
90904 * @module Lights, Camera
90905 * @submodule Material
90906 * @for p5
90907 * @requires core
90908 */ /**
90909 * Shader class for WEBGL Mode
90910 * @class p5.Shader
90911 * @constructor
90912 * @param {p5.RendererGL} renderer an instance of p5.RendererGL that
90913 * will provide the GL context for this new p5.Shader
90914 * @param {String} vertSrc source code for the vertex shader (as a string)
90915 * @param {String} fragSrc source code for the fragment shader (as a string)
90916 */ _main.default.Shader = function(renderer, vertSrc, fragSrc) {
90917 // TODO: adapt this to not take ids, but rather,
90918 // to take the source for a vertex and fragment shader
90919 // to enable custom shaders at some later date
90920 this._renderer = renderer;
90921 this._vertSrc = vertSrc;
90922 this._fragSrc = fragSrc;
90923 this._vertShader = -1;
90924 this._fragShader = -1;
90925 this._glProgram = 0;
90926 this._loadedAttributes = false;
90927 this.attributes = {};
90928 this._loadedUniforms = false;
90929 this.uniforms = {};
90930 this._bound = false;
90931 this.samplers = [];
90932 };
90933
90934 /**
90935 * Creates, compiles, and links the shader based on its
90936 * sources for the vertex and fragment shaders (provided
90937 * to the constructor). Populates known attributes and
90938 * uniforms from the shader.
90939 * @method init
90940 * @chainable
90941 * @private
90942 */
90943 _main.default.Shader.prototype.init = function() {
90944 if (this._glProgram === 0 /* or context is stale? */) {
90945 var gl = this._renderer.GL;
90946
90947 // @todo: once custom shading is allowed,
90948 // friendly error messages should be used here to share
90949 // compiler and linker errors.
90950
90951 //set up the shader by
90952 // 1. creating and getting a gl id for the shader program,
90953 // 2. compliling its vertex & fragment sources,
90954 // 3. linking the vertex and fragment shaders
90955 this._vertShader = gl.createShader(gl.VERTEX_SHADER);
90956 //load in our default vertex shader
90957 gl.shaderSource(this._vertShader, this._vertSrc);
90958 gl.compileShader(this._vertShader);
90959 // if our vertex shader failed compilation?
90960 if (!gl.getShaderParameter(this._vertShader, gl.COMPILE_STATUS)) {
90961 console.error(
90962 'Yikes! An error occurred compiling the vertex shader:'.concat(
90963 gl.getShaderInfoLog(this._vertShader)
90964 )
90965 );
90966
90967 return null;
90968 }
90969
90970 this._fragShader = gl.createShader(gl.FRAGMENT_SHADER);
90971 //load in our material frag shader
90972 gl.shaderSource(this._fragShader, this._fragSrc);
90973 gl.compileShader(this._fragShader);
90974 // if our frag shader failed compilation?
90975 if (!gl.getShaderParameter(this._fragShader, gl.COMPILE_STATUS)) {
90976 console.error(
90977 'Darn! An error occurred compiling the fragment shader:'.concat(
90978 gl.getShaderInfoLog(this._fragShader)
90979 )
90980 );
90981
90982 return null;
90983 }
90984
90985 this._glProgram = gl.createProgram();
90986 gl.attachShader(this._glProgram, this._vertShader);
90987 gl.attachShader(this._glProgram, this._fragShader);
90988 gl.linkProgram(this._glProgram);
90989 if (!gl.getProgramParameter(this._glProgram, gl.LINK_STATUS)) {
90990 console.error(
90991 'Snap! Error linking shader program: '.concat(
90992 gl.getProgramInfoLog(this._glProgram)
90993 )
90994 );
90995 }
90996
90997 this._loadAttributes();
90998 this._loadUniforms();
90999 }
91000 return this;
91001 };
91002
91003 /**
91004 * Queries the active attributes for this shader and loads
91005 * their names and locations into the attributes array.
91006 * @method _loadAttributes
91007 * @private
91008 */
91009 _main.default.Shader.prototype._loadAttributes = function() {
91010 if (this._loadedAttributes) {
91011 return;
91012 }
91013
91014 this.attributes = {};
91015
91016 var gl = this._renderer.GL;
91017
91018 var numAttributes = gl.getProgramParameter(
91019 this._glProgram,
91020 gl.ACTIVE_ATTRIBUTES
91021 );
91022
91023 for (var i = 0; i < numAttributes; ++i) {
91024 var attributeInfo = gl.getActiveAttrib(this._glProgram, i);
91025 var name = attributeInfo.name;
91026 var location = gl.getAttribLocation(this._glProgram, name);
91027 var attribute = {};
91028 attribute.name = name;
91029 attribute.location = location;
91030 attribute.index = i;
91031 attribute.type = attributeInfo.type;
91032 attribute.size = attributeInfo.size;
91033 this.attributes[name] = attribute;
91034 }
91035
91036 this._loadedAttributes = true;
91037 };
91038
91039 /**
91040 * Queries the active uniforms for this shader and loads
91041 * their names and locations into the uniforms array.
91042 * @method _loadUniforms
91043 * @private
91044 */
91045 _main.default.Shader.prototype._loadUniforms = function() {
91046 if (this._loadedUniforms) {
91047 return;
91048 }
91049
91050 var gl = this._renderer.GL;
91051
91052 // Inspect shader and cache uniform info
91053 var numUniforms = gl.getProgramParameter(this._glProgram, gl.ACTIVE_UNIFORMS);
91054
91055 var samplerIndex = 0;
91056 for (var i = 0; i < numUniforms; ++i) {
91057 var uniformInfo = gl.getActiveUniform(this._glProgram, i);
91058 var uniform = {};
91059 uniform.location = gl.getUniformLocation(this._glProgram, uniformInfo.name);
91060 uniform.size = uniformInfo.size;
91061 var uniformName = uniformInfo.name;
91062 //uniforms thats are arrays have their name returned as
91063 //someUniform[0] which is a bit silly so we trim it
91064 //off here. The size property tells us that its an array
91065 //so we dont lose any information by doing this
91066 if (uniformInfo.size > 1) {
91067 uniformName = uniformName.substring(0, uniformName.indexOf('[0]'));
91068 }
91069 uniform.name = uniformName;
91070 uniform.type = uniformInfo.type;
91071 uniform._cachedData = undefined;
91072 if (uniform.type === gl.SAMPLER_2D) {
91073 uniform.samplerIndex = samplerIndex;
91074 samplerIndex++;
91075 this.samplers.push(uniform);
91076 }
91077 uniform.isArray =
91078 uniform.type === gl.FLOAT_MAT3 ||
91079 uniform.type === gl.FLOAT_MAT4 ||
91080 uniform.type === gl.FLOAT_VEC2 ||
91081 uniform.type === gl.FLOAT_VEC3 ||
91082 uniform.type === gl.FLOAT_VEC4 ||
91083 uniform.type === gl.INT_VEC2 ||
91084 uniform.type === gl.INT_VEC3 ||
91085 uniform.type === gl.INT_VEC4;
91086
91087 this.uniforms[uniformName] = uniform;
91088 }
91089 this._loadedUniforms = true;
91090 };
91091
91092 _main.default.Shader.prototype.compile = function() {
91093 // TODO
91094 };
91095
91096 /**
91097 * initializes (if needed) and binds the shader program.
91098 * @method bindShader
91099 * @private
91100 */
91101 _main.default.Shader.prototype.bindShader = function() {
91102 this.init();
91103 if (!this._bound) {
91104 this.useProgram();
91105 this._bound = true;
91106
91107 this._setMatrixUniforms();
91108
91109 this.setUniform('uViewport', this._renderer._viewport);
91110 }
91111 };
91112
91113 /**
91114 * @method unbindShader
91115 * @chainable
91116 * @private
91117 */
91118 _main.default.Shader.prototype.unbindShader = function() {
91119 if (this._bound) {
91120 this.unbindTextures();
91121 //this._renderer.GL.useProgram(0); ??
91122 this._bound = false;
91123 }
91124 return this;
91125 };
91126
91127 _main.default.Shader.prototype.bindTextures = function() {
91128 var gl = this._renderer.GL;
91129 var _iteratorNormalCompletion = true;
91130 var _didIteratorError = false;
91131 var _iteratorError = undefined;
91132 try {
91133 for (
91134 var _iterator = this.samplers[Symbol.iterator](), _step;
91135 !(_iteratorNormalCompletion = (_step = _iterator.next()).done);
91136 _iteratorNormalCompletion = true
91137 ) {
91138 var uniform = _step.value;
91139 var tex = uniform.texture;
91140 if (tex === undefined) {
91141 // user hasn't yet supplied a texture for this slot.
91142 // (or there may not be one--maybe just lighting),
91143 // so we supply a default texture instead.
91144 tex = this._renderer._getEmptyTexture();
91145 }
91146 gl.activeTexture(gl.TEXTURE0 + uniform.samplerIndex);
91147 tex.bindTexture();
91148 tex.update();
91149 gl.uniform1i(uniform.location, uniform.samplerIndex);
91150 }
91151 } catch (err) {
91152 _didIteratorError = true;
91153 _iteratorError = err;
91154 } finally {
91155 try {
91156 if (!_iteratorNormalCompletion && _iterator.return != null) {
91157 _iterator.return();
91158 }
91159 } finally {
91160 if (_didIteratorError) {
91161 throw _iteratorError;
91162 }
91163 }
91164 }
91165 };
91166
91167 _main.default.Shader.prototype.updateTextures = function() {
91168 var _iteratorNormalCompletion2 = true;
91169 var _didIteratorError2 = false;
91170 var _iteratorError2 = undefined;
91171 try {
91172 for (
91173 var _iterator2 = this.samplers[Symbol.iterator](), _step2;
91174 !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done);
91175 _iteratorNormalCompletion2 = true
91176 ) {
91177 var uniform = _step2.value;
91178 var tex = uniform.texture;
91179 if (tex) {
91180 tex.update();
91181 }
91182 }
91183 } catch (err) {
91184 _didIteratorError2 = true;
91185 _iteratorError2 = err;
91186 } finally {
91187 try {
91188 if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
91189 _iterator2.return();
91190 }
91191 } finally {
91192 if (_didIteratorError2) {
91193 throw _iteratorError2;
91194 }
91195 }
91196 }
91197 };
91198
91199 _main.default.Shader.prototype.unbindTextures = function() {
91200 // TODO: migrate stuff from material.js here
91201 // - OR - have material.js define this function
91202 };
91203
91204 _main.default.Shader.prototype._setMatrixUniforms = function() {
91205 this.setUniform('uProjectionMatrix', this._renderer.uPMatrix.mat4);
91206 if (this.isStrokeShader()) {
91207 if (this._renderer._curCamera.cameraType === 'default') {
91208 // strokes scale up as they approach camera, default
91209 this.setUniform('uPerspective', 1);
91210 } else {
91211 // strokes have uniform scale regardless of distance from camera
91212 this.setUniform('uPerspective', 0);
91213 }
91214 }
91215 this.setUniform('uModelViewMatrix', this._renderer.uMVMatrix.mat4);
91216 this.setUniform('uViewMatrix', this._renderer._curCamera.cameraMatrix.mat4);
91217 if (this.uniforms.uNormalMatrix) {
91218 this._renderer.uNMatrix.inverseTranspose(this._renderer.uMVMatrix);
91219 this.setUniform('uNormalMatrix', this._renderer.uNMatrix.mat3);
91220 }
91221 };
91222
91223 /**
91224 * @method useProgram
91225 * @chainable
91226 * @private
91227 */
91228 _main.default.Shader.prototype.useProgram = function() {
91229 var gl = this._renderer.GL;
91230 if (this._renderer._curShader !== this) {
91231 gl.useProgram(this._glProgram);
91232 this._renderer._curShader = this;
91233 }
91234 return this;
91235 };
91236
91237 /**
91238 * Wrapper around gl.uniform functions.
91239 * As we store uniform info in the shader we can use that
91240 * to do type checking on the supplied data and call
91241 * the appropriate function.
91242 * @method setUniform
91243 * @chainable
91244 * @param {String} uniformName the name of the uniform in the
91245 * shader program
91246 * @param {Object|Number|Boolean|Number[]} data the data to be associated
91247 * with that uniform; type varies (could be a single numerical value, array,
91248 * matrix, or texture / sampler reference)
91249 *
91250 * @example
91251 * <div modernizr='webgl'>
91252 * <code>
91253 * // Click within the image to toggle the value of uniforms
91254 * // Note: for an alternative approach to the same example,
91255 * // involving toggling between shaders please refer to:
91256 * // https://p5js.org/reference/#/p5/shader
91257 *
91258 * let grad;
91259 * let showRedGreen = false;
91260 *
91261 * function preload() {
91262 * // note that we are using two instances
91263 * // of the same vertex and fragment shaders
91264 * grad = loadShader('assets/shader.vert', 'assets/shader-gradient.frag');
91265 * }
91266 *
91267 * function setup() {
91268 * createCanvas(100, 100, WEBGL);
91269 * shader(grad);
91270 * noStroke();
91271 * }
91272 *
91273 * function draw() {
91274 * // update the offset values for each scenario,
91275 * // moving the "grad" shader in either vertical or
91276 * // horizontal direction each with differing colors
91277 *
91278 * if (showRedGreen === true) {
91279 * grad.setUniform('colorCenter', [1, 0, 0]);
91280 * grad.setUniform('colorBackground', [0, 1, 0]);
91281 * grad.setUniform('offset', [sin(millis() / 2000), 1]);
91282 * } else {
91283 * grad.setUniform('colorCenter', [1, 0.5, 0]);
91284 * grad.setUniform('colorBackground', [0.226, 0, 0.615]);
91285 * grad.setUniform('offset', [0, sin(millis() / 2000) + 1]);
91286 * }
91287 * quad(-1, -1, 1, -1, 1, 1, -1, 1);
91288 * }
91289 *
91290 * function mouseClicked() {
91291 * showRedGreen = !showRedGreen;
91292 * }
91293 * </code>
91294 * </div>
91295 *
91296 * @alt
91297 * canvas toggles between a circular gradient of orange and blue vertically. and a circular gradient of red and green moving horizontally when mouse is clicked/pressed.
91298 */
91299 _main.default.Shader.prototype.setUniform = function(uniformName, data) {
91300 var uniform = this.uniforms[uniformName];
91301 if (!uniform) {
91302 return;
91303 }
91304 var gl = this._renderer.GL;
91305
91306 if (uniform.isArray) {
91307 if (
91308 uniform._cachedData &&
91309 this._renderer._arraysEqual(uniform._cachedData, data)
91310 ) {
91311 return;
91312 } else {
91313 uniform._cachedData = data.slice(0);
91314 }
91315 } else if (uniform._cachedData && uniform._cachedData === data) {
91316 return;
91317 } else {
91318 uniform._cachedData = data;
91319 }
91320
91321 var location = uniform.location;
91322
91323 this.useProgram();
91324
91325 switch (uniform.type) {
91326 case gl.BOOL:
91327 if (data === true) {
91328 gl.uniform1i(location, 1);
91329 } else {
91330 gl.uniform1i(location, 0);
91331 }
91332 break;
91333 case gl.INT:
91334 if (uniform.size > 1) {
91335 data.length && gl.uniform1iv(location, data);
91336 } else {
91337 gl.uniform1i(location, data);
91338 }
91339 break;
91340 case gl.FLOAT:
91341 if (uniform.size > 1) {
91342 data.length && gl.uniform1fv(location, data);
91343 } else {
91344 gl.uniform1f(location, data);
91345 }
91346 break;
91347 case gl.FLOAT_MAT3:
91348 gl.uniformMatrix3fv(location, false, data);
91349 break;
91350 case gl.FLOAT_MAT4:
91351 gl.uniformMatrix4fv(location, false, data);
91352 break;
91353 case gl.FLOAT_VEC2:
91354 if (uniform.size > 1) {
91355 data.length && gl.uniform2fv(location, data);
91356 } else {
91357 gl.uniform2f(location, data[0], data[1]);
91358 }
91359 break;
91360 case gl.FLOAT_VEC3:
91361 if (uniform.size > 1) {
91362 data.length && gl.uniform3fv(location, data);
91363 } else {
91364 gl.uniform3f(location, data[0], data[1], data[2]);
91365 }
91366 break;
91367 case gl.FLOAT_VEC4:
91368 if (uniform.size > 1) {
91369 data.length && gl.uniform4fv(location, data);
91370 } else {
91371 gl.uniform4f(location, data[0], data[1], data[2], data[3]);
91372 }
91373 break;
91374 case gl.INT_VEC2:
91375 if (uniform.size > 1) {
91376 data.length && gl.uniform2iv(location, data);
91377 } else {
91378 gl.uniform2i(location, data[0], data[1]);
91379 }
91380 break;
91381 case gl.INT_VEC3:
91382 if (uniform.size > 1) {
91383 data.length && gl.uniform3iv(location, data);
91384 } else {
91385 gl.uniform3i(location, data[0], data[1], data[2]);
91386 }
91387 break;
91388 case gl.INT_VEC4:
91389 if (uniform.size > 1) {
91390 data.length && gl.uniform4iv(location, data);
91391 } else {
91392 gl.uniform4i(location, data[0], data[1], data[2], data[3]);
91393 }
91394 break;
91395 case gl.SAMPLER_2D:
91396 gl.activeTexture(gl.TEXTURE0 + uniform.samplerIndex);
91397 uniform.texture = this._renderer.getTexture(data);
91398 gl.uniform1i(uniform.location, uniform.samplerIndex);
91399 break;
91400 //@todo complete all types
91401 }
91402 return this;
91403 };
91404
91405 /* NONE OF THIS IS FAST OR EFFICIENT BUT BEAR WITH ME
91406 *
91407 * these shader "type" query methods are used by various
91408 * facilities of the renderer to determine if changing
91409 * the shader type for the required action (for example,
91410 * do we need to load the default lighting shader if the
91411 * current shader cannot handle lighting?)
91412 *
91413 **/
91414
91415 _main.default.Shader.prototype.isLightShader = function() {
91416 return (
91417 this.attributes.aNormal !== undefined ||
91418 this.uniforms.uUseLighting !== undefined ||
91419 this.uniforms.uAmbientLightCount !== undefined ||
91420 this.uniforms.uDirectionalLightCount !== undefined ||
91421 this.uniforms.uPointLightCount !== undefined ||
91422 this.uniforms.uAmbientColor !== undefined ||
91423 this.uniforms.uDirectionalDiffuseColors !== undefined ||
91424 this.uniforms.uDirectionalSpecularColors !== undefined ||
91425 this.uniforms.uPointLightLocation !== undefined ||
91426 this.uniforms.uPointLightDiffuseColors !== undefined ||
91427 this.uniforms.uPointLightSpecularColors !== undefined ||
91428 this.uniforms.uLightingDirection !== undefined ||
91429 this.uniforms.uSpecular !== undefined
91430 );
91431 };
91432
91433 _main.default.Shader.prototype.isNormalShader = function() {
91434 return this.attributes.aNormal !== undefined;
91435 };
91436
91437 _main.default.Shader.prototype.isTextureShader = function() {
91438 return this.samplerIndex > 0;
91439 };
91440
91441 _main.default.Shader.prototype.isColorShader = function() {
91442 return (
91443 this.attributes.aVertexColor !== undefined ||
91444 this.uniforms.uMaterialColor !== undefined
91445 );
91446 };
91447
91448 _main.default.Shader.prototype.isTexLightShader = function() {
91449 return this.isLightShader() && this.isTextureShader();
91450 };
91451
91452 _main.default.Shader.prototype.isStrokeShader = function() {
91453 return this.uniforms.uStrokeWeight !== undefined;
91454 };
91455
91456 /**
91457 * @method enableAttrib
91458 * @chainable
91459 * @private
91460 */
91461 _main.default.Shader.prototype.enableAttrib = function(
91462 attr,
91463 size,
91464 type,
91465 normalized,
91466 stride,
91467 offset
91468 ) {
91469 if (attr) {
91470 if (
91471 typeof IS_MINIFIED === 'undefined' &&
91472 this.attributes[attr.name] !== attr
91473 ) {
91474 console.warn(
91475 'The attribute "'.concat(
91476 attr.name,
91477 '"passed to enableAttrib does not belong to this shader.'
91478 )
91479 );
91480 }
91481 var loc = attr.location;
91482 if (loc !== -1) {
91483 var gl = this._renderer.GL;
91484 if (!attr.enabled) {
91485 gl.enableVertexAttribArray(loc);
91486 attr.enabled = true;
91487 }
91488 this._renderer.GL.vertexAttribPointer(
91489 loc,
91490 size,
91491 type || gl.FLOAT,
91492 normalized || false,
91493 stride || 0,
91494 offset || 0
91495 );
91496 }
91497 }
91498 return this;
91499 };
91500 var _default = _main.default.Shader;
91501 exports.default = _default;
91502 },
91503 { '../core/main': 54 }
91504 ],
91505 110: [
91506 function(_dereq_, module, exports) {
91507 'use strict';
91508 function _typeof(obj) {
91509 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
91510 _typeof = function _typeof(obj) {
91511 return typeof obj;
91512 };
91513 } else {
91514 _typeof = function _typeof(obj) {
91515 return obj &&
91516 typeof Symbol === 'function' &&
91517 obj.constructor === Symbol &&
91518 obj !== Symbol.prototype
91519 ? 'symbol'
91520 : typeof obj;
91521 };
91522 }
91523 return _typeof(obj);
91524 }
91525 Object.defineProperty(exports, '__esModule', { value: true });
91526 exports.default = void 0;
91527
91528 var _main = _interopRequireDefault(_dereq_('../core/main'));
91529 var constants = _interopRequireWildcard(_dereq_('../core/constants'));
91530 function _getRequireWildcardCache() {
91531 if (typeof WeakMap !== 'function') return null;
91532 var cache = new WeakMap();
91533 _getRequireWildcardCache = function _getRequireWildcardCache() {
91534 return cache;
91535 };
91536 return cache;
91537 }
91538 function _interopRequireWildcard(obj) {
91539 if (obj && obj.__esModule) {
91540 return obj;
91541 }
91542 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) {
91543 return { default: obj };
91544 }
91545 var cache = _getRequireWildcardCache();
91546 if (cache && cache.has(obj)) {
91547 return cache.get(obj);
91548 }
91549 var newObj = {};
91550 var hasPropertyDescriptor =
91551 Object.defineProperty && Object.getOwnPropertyDescriptor;
91552 for (var key in obj) {
91553 if (Object.prototype.hasOwnProperty.call(obj, key)) {
91554 var desc = hasPropertyDescriptor
91555 ? Object.getOwnPropertyDescriptor(obj, key)
91556 : null;
91557 if (desc && (desc.get || desc.set)) {
91558 Object.defineProperty(newObj, key, desc);
91559 } else {
91560 newObj[key] = obj[key];
91561 }
91562 }
91563 }
91564 newObj.default = obj;
91565 if (cache) {
91566 cache.set(obj, newObj);
91567 }
91568 return newObj;
91569 }
91570 function _interopRequireDefault(obj) {
91571 return obj && obj.__esModule ? obj : { default: obj };
91572 }
91573 /**
91574 * This module defines the p5.Texture class
91575 * @module Lights, Camera
91576 * @submodule Material
91577 * @for p5
91578 * @requires core
91579 */ /**
91580 * Texture class for WEBGL Mode
91581 * @private
91582 * @class p5.Texture
91583 * @param {p5.RendererGL} renderer an instance of p5.RendererGL that
91584 * will provide the GL context for this new p5.Texture
91585 * @param {p5.Image|p5.Graphics|p5.Element|p5.MediaElement|ImageData} [obj] the
91586 * object containing the image data to store in the texture.
91587 */ _main.default.Texture = function(renderer, obj) {
91588 this._renderer = renderer;
91589 var gl = this._renderer.GL;
91590
91591 this.src = obj;
91592 this.glTex = undefined;
91593 this.glTarget = gl.TEXTURE_2D;
91594 this.glFormat = gl.RGBA;
91595 this.mipmaps = false;
91596 this.glMinFilter = gl.LINEAR;
91597 this.glMagFilter = gl.LINEAR;
91598 this.glWrapS = gl.CLAMP_TO_EDGE;
91599 this.glWrapT = gl.CLAMP_TO_EDGE;
91600
91601 // used to determine if this texture might need constant updating
91602 // because it is a video or gif.
91603 this.isSrcMediaElement =
91604 typeof _main.default.MediaElement !== 'undefined' &&
91605 obj instanceof _main.default.MediaElement;
91606 this._videoPrevUpdateTime = 0;
91607 this.isSrcHTMLElement =
91608 typeof _main.default.Element !== 'undefined' &&
91609 obj instanceof _main.default.Element &&
91610 !(obj instanceof _main.default.Graphics);
91611 this.isSrcP5Image = obj instanceof _main.default.Image;
91612 this.isSrcP5Graphics = obj instanceof _main.default.Graphics;
91613 this.isImageData = typeof ImageData !== 'undefined' && obj instanceof ImageData;
91614
91615 var textureData = this._getTextureDataFromSource();
91616 this.width = textureData.width;
91617 this.height = textureData.height;
91618
91619 this.init(textureData);
91620 return this;
91621 };
91622
91623 _main.default.Texture.prototype._getTextureDataFromSource = function() {
91624 var textureData;
91625 if (this.isSrcP5Image) {
91626 // param is a p5.Image
91627 textureData = this.src.canvas;
91628 } else if (
91629 this.isSrcMediaElement ||
91630 this.isSrcP5Graphics ||
91631 this.isSrcHTMLElement
91632 ) {
91633 // if param is a video HTML element
91634 textureData = this.src.elt;
91635 } else if (this.isImageData) {
91636 textureData = this.src;
91637 }
91638 return textureData;
91639 };
91640
91641 /**
91642 * Initializes common texture parameters, creates a gl texture,
91643 * tries to upload the texture for the first time if data is
91644 * already available.
91645 * @private
91646 * @method init
91647 */
91648 _main.default.Texture.prototype.init = function(data) {
91649 var gl = this._renderer.GL;
91650 this.glTex = gl.createTexture();
91651
91652 this.glWrapS = this._renderer.textureWrapX;
91653 this.glWrapT = this._renderer.textureWrapY;
91654
91655 this.setWrapMode(this.glWrapS, this.glWrapT);
91656 this.bindTexture();
91657
91658 //gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
91659 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, this.glMagFilter);
91660 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, this.glMinFilter);
91661
91662 if (
91663 this.width === 0 ||
91664 this.height === 0 ||
91665 (this.isSrcMediaElement && !this.src.loadedmetadata)
91666 ) {
91667 // assign a 1x1 empty texture initially, because data is not yet ready,
91668 // so that no errors occur in gl console!
91669 var tmpdata = new Uint8Array([1, 1, 1, 1]);
91670 gl.texImage2D(
91671 this.glTarget,
91672 0,
91673 gl.RGBA,
91674 1,
91675 1,
91676 0,
91677 this.glFormat,
91678 gl.UNSIGNED_BYTE,
91679 tmpdata
91680 );
91681 } else {
91682 // data is ready: just push the texture!
91683 gl.texImage2D(
91684 this.glTarget,
91685 0,
91686 this.glFormat,
91687 this.glFormat,
91688 gl.UNSIGNED_BYTE,
91689 data
91690 );
91691 }
91692 };
91693
91694 /**
91695 * Checks if the source data for this texture has changed (if it's
91696 * easy to do so) and reuploads the texture if necessary. If it's not
91697 * possible or to expensive to do a calculation to determine wheter or
91698 * not the data has occurred, this method simply re-uploads the texture.
91699 * @method update
91700 */
91701 _main.default.Texture.prototype.update = function() {
91702 var data = this.src;
91703 if (data.width === 0 || data.height === 0) {
91704 return false; // nothing to do!
91705 }
91706
91707 var textureData = this._getTextureDataFromSource();
91708 var updated = false;
91709
91710 var gl = this._renderer.GL;
91711 // pull texture from data, make sure width & height are appropriate
91712 if (textureData.width !== this.width || textureData.height !== this.height) {
91713 updated = true;
91714
91715 // make sure that if the width and height of this.src have changed
91716 // for some reason, we update our metadata and upload the texture again
91717 this.width = textureData.width;
91718 this.height = textureData.height;
91719
91720 if (this.isSrcP5Image) {
91721 data.setModified(false);
91722 } else if (this.isSrcMediaElement || this.isSrcHTMLElement) {
91723 // on the first frame the metadata comes in, the size will be changed
91724 // from 0 to actual size, but pixels may not be available.
91725 // flag for update in a future frame.
91726 // if we don't do this, a paused video, for example, may not
91727 // send the first frame to texture memory.
91728 data.setModified(true);
91729 }
91730 } else if (this.isSrcP5Image) {
91731 // for an image, we only update if the modified field has been set,
91732 // for example, by a call to p5.Image.set
91733 if (data.isModified()) {
91734 updated = true;
91735 data.setModified(false);
91736 }
91737 } else if (this.isSrcMediaElement) {
91738 // for a media element (video), we'll check if the current time in
91739 // the video frame matches the last time. if it doesn't match, the
91740 // video has advanced or otherwise been taken to a new frame,
91741 // and we need to upload it.
91742 if (data.isModified()) {
91743 // p5.MediaElement may have also had set/updatePixels, etc. called
91744 // on it and should be updated, or may have been set for the first
91745 // time!
91746 updated = true;
91747 data.setModified(false);
91748 } else if (data.loadedmetadata) {
91749 // if the meta data has been loaded, we can ask the video
91750 // what it's current position (in time) is.
91751 if (this._videoPrevUpdateTime !== data.time()) {
91752 // update the texture in gpu mem only if the current
91753 // video timestamp does not match the timestamp of the last
91754 // time we uploaded this texture (and update the time we
91755 // last uploaded, too)
91756 this._videoPrevUpdateTime = data.time();
91757 updated = true;
91758 }
91759 }
91760 } else if (this.isImageData) {
91761 if (data._dirty) {
91762 data._dirty = false;
91763 updated = true;
91764 }
91765 } else {
91766 /* data instanceof p5.Graphics, probably */
91767 // there is not enough information to tell if the texture can be
91768 // conditionally updated; so to be safe, we just go ahead and upload it.
91769 updated = true;
91770 }
91771
91772 if (updated) {
91773 this.bindTexture();
91774 gl.texImage2D(
91775 this.glTarget,
91776 0,
91777 this.glFormat,
91778 this.glFormat,
91779 gl.UNSIGNED_BYTE,
91780 textureData
91781 );
91782 }
91783
91784 return updated;
91785 };
91786
91787 /**
91788 * Binds the texture to the appropriate GL target.
91789 * @method bindTexture
91790 */
91791 _main.default.Texture.prototype.bindTexture = function() {
91792 // bind texture using gl context + glTarget and
91793 // generated gl texture object
91794 var gl = this._renderer.GL;
91795 gl.bindTexture(this.glTarget, this.glTex);
91796
91797 return this;
91798 };
91799
91800 /**
91801 * Unbinds the texture from the appropriate GL target.
91802 * @method unbindTexture
91803 */
91804 _main.default.Texture.prototype.unbindTexture = function() {
91805 // unbind per above, disable texturing on glTarget
91806 var gl = this._renderer.GL;
91807 gl.bindTexture(this.glTarget, null);
91808 };
91809
91810 /**
91811 * Sets how a texture is be interpolated when upscaled or downscaled.
91812 * Nearest filtering uses nearest neighbor scaling when interpolating
91813 * Linear filtering uses WebGL's linear scaling when interpolating
91814 * @method setInterpolation
91815 * @param {String} downScale Specifies the texture filtering when
91816 * textures are shrunk. Options are LINEAR or NEAREST
91817 * @param {String} upScale Specifies the texture filtering when
91818 * textures are magnified. Options are LINEAR or NEAREST
91819 * @todo implement mipmapping filters
91820 */
91821 _main.default.Texture.prototype.setInterpolation = function(downScale, upScale) {
91822 var gl = this._renderer.GL;
91823
91824 if (downScale === constants.NEAREST) {
91825 this.glMinFilter = gl.NEAREST;
91826 } else {
91827 this.glMinFilter = gl.LINEAR;
91828 }
91829
91830 if (upScale === constants.NEAREST) {
91831 this.glMagFilter = gl.NEAREST;
91832 } else {
91833 this.glMagFilter = gl.LINEAR;
91834 }
91835
91836 this.bindTexture();
91837 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, this.glMinFilter);
91838 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, this.glMagFilter);
91839 this.unbindTexture();
91840 };
91841
91842 /**
91843 * Sets the texture wrapping mode. This controls how textures behave
91844 * when their uv's go outside of the 0 - 1 range. There are three options:
91845 * CLAMP, REPEAT, and MIRROR. REPEAT & MIRROR are only available if the texture
91846 * is a power of two size (128, 256, 512, 1024, etc.).
91847 * @method setWrapMode
91848 * @param {String} wrapX Controls the horizontal texture wrapping behavior
91849 * @param {String} wrapY Controls the vertical texture wrapping behavior
91850 */
91851 _main.default.Texture.prototype.setWrapMode = function(wrapX, wrapY) {
91852 var gl = this._renderer.GL;
91853
91854 // for webgl 1 we need to check if the texture is power of two
91855 // if it isn't we will set the wrap mode to CLAMP
91856 // webgl2 will support npot REPEAT and MIRROR but we don't check for it yet
91857 var isPowerOfTwo = function isPowerOfTwo(x) {
91858 return (x & (x - 1)) === 0;
91859 };
91860
91861 var widthPowerOfTwo = isPowerOfTwo(this.width);
91862 var heightPowerOfTwo = isPowerOfTwo(this.height);
91863
91864 if (wrapX === constants.REPEAT) {
91865 if (widthPowerOfTwo && heightPowerOfTwo) {
91866 this.glWrapS = gl.REPEAT;
91867 } else {
91868 console.warn(
91869 'You tried to set the wrap mode to REPEAT but the texture size is not a power of two. Setting to CLAMP instead'
91870 );
91871
91872 this.glWrapS = gl.CLAMP_TO_EDGE;
91873 }
91874 } else if (wrapX === constants.MIRROR) {
91875 if (widthPowerOfTwo && heightPowerOfTwo) {
91876 this.glWrapS = gl.MIRRORED_REPEAT;
91877 } else {
91878 console.warn(
91879 'You tried to set the wrap mode to MIRROR but the texture size is not a power of two. Setting to CLAMP instead'
91880 );
91881
91882 this.glWrapS = gl.CLAMP_TO_EDGE;
91883 }
91884 } else {
91885 // falling back to default if didn't get a proper mode
91886 this.glWrapS = gl.CLAMP_TO_EDGE;
91887 }
91888
91889 if (wrapY === constants.REPEAT) {
91890 if (widthPowerOfTwo && heightPowerOfTwo) {
91891 this.glWrapT = gl.REPEAT;
91892 } else {
91893 console.warn(
91894 'You tried to set the wrap mode to REPEAT but the texture size is not a power of two. Setting to CLAMP instead'
91895 );
91896
91897 this.glWrapT = gl.CLAMP_TO_EDGE;
91898 }
91899 } else if (wrapY === constants.MIRROR) {
91900 if (widthPowerOfTwo && heightPowerOfTwo) {
91901 this.glWrapT = gl.MIRRORED_REPEAT;
91902 } else {
91903 console.warn(
91904 'You tried to set the wrap mode to MIRROR but the texture size is not a power of two. Setting to CLAMP instead'
91905 );
91906
91907 this.glWrapT = gl.CLAMP_TO_EDGE;
91908 }
91909 } else {
91910 // falling back to default if didn't get a proper mode
91911 this.glWrapT = gl.CLAMP_TO_EDGE;
91912 }
91913
91914 this.bindTexture();
91915 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, this.glWrapS);
91916 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, this.glWrapT);
91917 this.unbindTexture();
91918 };
91919 var _default = _main.default.Texture;
91920 exports.default = _default;
91921 },
91922 { '../core/constants': 43, '../core/main': 54 }
91923 ],
91924 111: [
91925 function(_dereq_, module, exports) {
91926 'use strict';
91927 function _typeof(obj) {
91928 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
91929 _typeof = function _typeof(obj) {
91930 return typeof obj;
91931 };
91932 } else {
91933 _typeof = function _typeof(obj) {
91934 return obj &&
91935 typeof Symbol === 'function' &&
91936 obj.constructor === Symbol &&
91937 obj !== Symbol.prototype
91938 ? 'symbol'
91939 : typeof obj;
91940 };
91941 }
91942 return _typeof(obj);
91943 }
91944 var _main = _interopRequireDefault(_dereq_('../core/main'));
91945 var constants = _interopRequireWildcard(_dereq_('../core/constants'));
91946 _dereq_('./p5.Shader');
91947 _dereq_('./p5.RendererGL.Retained');
91948 function _getRequireWildcardCache() {
91949 if (typeof WeakMap !== 'function') return null;
91950 var cache = new WeakMap();
91951 _getRequireWildcardCache = function _getRequireWildcardCache() {
91952 return cache;
91953 };
91954 return cache;
91955 }
91956 function _interopRequireWildcard(obj) {
91957 if (obj && obj.__esModule) {
91958 return obj;
91959 }
91960 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) {
91961 return { default: obj };
91962 }
91963 var cache = _getRequireWildcardCache();
91964 if (cache && cache.has(obj)) {
91965 return cache.get(obj);
91966 }
91967 var newObj = {};
91968 var hasPropertyDescriptor =
91969 Object.defineProperty && Object.getOwnPropertyDescriptor;
91970 for (var key in obj) {
91971 if (Object.prototype.hasOwnProperty.call(obj, key)) {
91972 var desc = hasPropertyDescriptor
91973 ? Object.getOwnPropertyDescriptor(obj, key)
91974 : null;
91975 if (desc && (desc.get || desc.set)) {
91976 Object.defineProperty(newObj, key, desc);
91977 } else {
91978 newObj[key] = obj[key];
91979 }
91980 }
91981 }
91982 newObj.default = obj;
91983 if (cache) {
91984 cache.set(obj, newObj);
91985 }
91986 return newObj;
91987 }
91988 function _interopRequireDefault(obj) {
91989 return obj && obj.__esModule ? obj : { default: obj };
91990 }
91991
91992 // Text/Typography
91993 // @TODO:
91994 _main.default.RendererGL.prototype._applyTextProperties = function() {
91995 //@TODO finish implementation
91996 //console.error('text commands not yet implemented in webgl');
91997 };
91998
91999 _main.default.RendererGL.prototype.textWidth = function(s) {
92000 if (this._isOpenType()) {
92001 return this._textFont._textWidth(s, this._textSize);
92002 }
92003
92004 return 0; // TODO: error
92005 };
92006
92007 // rendering constants
92008
92009 // the number of rows/columns dividing each glyph
92010 var charGridWidth = 9;
92011 var charGridHeight = charGridWidth;
92012
92013 // size of the image holding the bezier stroke info
92014 var strokeImageWidth = 64;
92015 var strokeImageHeight = 64;
92016
92017 // size of the image holding the stroke indices for each row/col
92018 var gridImageWidth = 64;
92019 var gridImageHeight = 64;
92020
92021 // size of the image holding the offset/length of each row/col stripe
92022 var cellImageWidth = 64;
92023 var cellImageHeight = 64;
92024
92025 /**
92026 * @private
92027 * @class ImageInfos
92028 * @param {Integer} width
92029 * @param {Integer} height
92030 *
92031 * the ImageInfos class holds a list of ImageDatas of a given size.
92032 */
92033 function ImageInfos(width, height) {
92034 this.width = width;
92035 this.height = height;
92036 this.infos = []; // the list of images
92037
92038 /**
92039 *
92040 * @method findImage
92041 * @param {Integer} space
92042 * @return {Object} contains the ImageData, and pixel index into that
92043 * ImageData where the free space was allocated.
92044 *
92045 * finds free space of a given size in the ImageData list
92046 */
92047 this.findImage = function(space) {
92048 var imageSize = this.width * this.height;
92049 if (space > imageSize) throw new Error('font is too complex to render in 3D');
92050
92051 // search through the list of images, looking for one with
92052 // anough unused space.
92053 var imageInfo, imageData;
92054 for (var ii = this.infos.length - 1; ii >= 0; --ii) {
92055 var imageInfoTest = this.infos[ii];
92056 if (imageInfoTest.index + space < imageSize) {
92057 // found one
92058 imageInfo = imageInfoTest;
92059 imageData = imageInfoTest.imageData;
92060 break;
92061 }
92062 }
92063
92064 if (!imageInfo) {
92065 try {
92066 // create a new image
92067 imageData = new ImageData(this.width, this.height);
92068 } catch (err) {
92069 // for browsers that don't support ImageData constructors (ie IE11)
92070 // create an ImageData using the old method
92071 var canvas = document.getElementsByTagName('canvas')[0];
92072 var created = !canvas;
92073 if (!canvas) {
92074 // create a temporary canvas
92075 canvas = document.createElement('canvas');
92076 canvas.style.display = 'none';
92077 document.body.appendChild(canvas);
92078 }
92079 var ctx = canvas.getContext('2d');
92080 if (ctx) {
92081 imageData = ctx.createImageData(this.width, this.height);
92082 }
92083 if (created) {
92084 // distroy the temporary canvas, if necessary
92085 document.body.removeChild(canvas);
92086 }
92087 }
92088 // construct & dd the new image info
92089 imageInfo = { index: 0, imageData: imageData };
92090 this.infos.push(imageInfo);
92091 }
92092
92093 var index = imageInfo.index;
92094 imageInfo.index += space; // move to the start of the next image
92095 imageData._dirty = true;
92096 return { imageData: imageData, index: index };
92097 };
92098 }
92099
92100 /**
92101 * @function setPixel
92102 * @param {Object} imageInfo
92103 * @param {Number} r
92104 * @param {Number} g
92105 * @param {Number} b
92106 * @param {Number} a
92107 *
92108 * writes the next pixel into an indexed ImageData
92109 */
92110 function setPixel(imageInfo, r, g, b, a) {
92111 var imageData = imageInfo.imageData;
92112 var pixels = imageData.data;
92113 var index = imageInfo.index++ * 4;
92114 pixels[index++] = r;
92115 pixels[index++] = g;
92116 pixels[index++] = b;
92117 pixels[index++] = a;
92118 }
92119
92120 var SQRT3 = Math.sqrt(3);
92121
92122 /**
92123 * @private
92124 * @class FontInfo
92125 * @param {Object} font an opentype.js font object
92126 *
92127 * contains cached images and glyph information for an opentype font
92128 */
92129 var FontInfo = function FontInfo(font) {
92130 this.font = font;
92131 // the bezier curve coordinates
92132 this.strokeImageInfos = new ImageInfos(strokeImageWidth, strokeImageHeight);
92133 // lists of curve indices for each row/column slice
92134 this.colDimImageInfos = new ImageInfos(gridImageWidth, gridImageHeight);
92135 this.rowDimImageInfos = new ImageInfos(gridImageWidth, gridImageHeight);
92136 // the offset & length of each row/col slice in the glyph
92137 this.colCellImageInfos = new ImageInfos(cellImageWidth, cellImageHeight);
92138 this.rowCellImageInfos = new ImageInfos(cellImageWidth, cellImageHeight);
92139
92140 // the cached information for each glyph
92141 this.glyphInfos = {};
92142
92143 /**
92144 * @method getGlyphInfo
92145 * @param {Glyph} glyph the x positions of points in the curve
92146 * @returns {Object} the glyphInfo for that glyph
92147 *
92148 * calculates rendering info for a glyph, including the curve information,
92149 * row & column stripes compiled into textures.
92150 */
92151
92152 this.getGlyphInfo = function(glyph) {
92153 // check the cache
92154 var gi = this.glyphInfos[glyph.index];
92155 if (gi) return gi;
92156
92157 // get the bounding box of the glyph from opentype.js
92158 var bb = glyph.getBoundingBox();
92159 var xMin = bb.x1;
92160 var yMin = bb.y1;
92161 var gWidth = bb.x2 - xMin;
92162 var gHeight = bb.y2 - yMin;
92163 var cmds = glyph.path.commands;
92164 // don't bother rendering invisible glyphs
92165 if (gWidth === 0 || gHeight === 0 || !cmds.length) {
92166 return (this.glyphInfos[glyph.index] = {});
92167 }
92168
92169 var i;
92170 var strokes = []; // the strokes in this glyph
92171 var rows = []; // the indices of strokes in each row
92172 var cols = []; // the indices of strokes in each column
92173 for (i = charGridWidth - 1; i >= 0; --i) {
92174 cols.push([]);
92175 }
92176 for (i = charGridHeight - 1; i >= 0; --i) {
92177 rows.push([]);
92178 }
92179
92180 /**
92181 * @function push
92182 * @param {Number[]} xs the x positions of points in the curve
92183 * @param {Number[]} ys the y positions of points in the curve
92184 * @param {Object} v the curve information
92185 *
92186 * adds a curve to the rows & columns that it intersects with
92187 */
92188 function push(xs, ys, v) {
92189 var index = strokes.length; // the index of this stroke
92190 strokes.push(v); // add this stroke to the list
92191
92192 /**
92193 * @function minMax
92194 * @param {Number[]} rg the list of values to compare
92195 * @param {Number} min the initial minimum value
92196 * @param {Number} max the initial maximum value
92197 *
92198 * find the minimum & maximum value in a list of values
92199 */
92200 function minMax(rg, min, max) {
92201 for (var _i = rg.length; _i-- > 0; ) {
92202 var _v = rg[_i];
92203 if (min > _v) min = _v;
92204 if (max < _v) max = _v;
92205 }
92206 return { min: min, max: max };
92207 }
92208
92209 // loop through the rows & columns that the curve intersects
92210 // adding the curve to those slices
92211 var mmX = minMax(xs, 1, 0);
92212 var ixMin = Math.max(Math.floor(mmX.min * charGridWidth), 0);
92213 var ixMax = Math.min(Math.ceil(mmX.max * charGridWidth), charGridWidth);
92214 for (var iCol = ixMin; iCol < ixMax; ++iCol) {
92215 cols[iCol].push(index);
92216 }
92217
92218 var mmY = minMax(ys, 1, 0);
92219 var iyMin = Math.max(Math.floor(mmY.min * charGridHeight), 0);
92220 var iyMax = Math.min(Math.ceil(mmY.max * charGridHeight), charGridHeight);
92221
92222 for (var iRow = iyMin; iRow < iyMax; ++iRow) {
92223 rows[iRow].push(index);
92224 }
92225 }
92226
92227 /**
92228 * @function clamp
92229 * @param {Number} v the value to clamp
92230 * @param {Number} min the minimum value
92231 * @param {Number} max the maxmimum value
92232 *
92233 * clamps a value between a minimum & maximum value
92234 */
92235 function clamp(v, min, max) {
92236 if (v < min) return min;
92237 if (v > max) return max;
92238 return v;
92239 }
92240
92241 /**
92242 * @function byte
92243 * @param {Number} v the value to scale
92244 *
92245 * converts a floating-point number in the range 0-1 to a byte 0-255
92246 */
92247 function byte(v) {
92248 return clamp(255 * v, 0, 255);
92249 }
92250
92251 /**
92252 * @private
92253 * @class Cubic
92254 * @param {Number} p0 the start point of the curve
92255 * @param {Number} c0 the first control point
92256 * @param {Number} c1 the second control point
92257 * @param {Number} p1 the end point
92258 *
92259 * a cubic curve
92260 */
92261 function Cubic(p0, c0, c1, p1) {
92262 this.p0 = p0;
92263 this.c0 = c0;
92264 this.c1 = c1;
92265 this.p1 = p1;
92266
92267 /**
92268 * @method toQuadratic
92269 * @return {Object} the quadratic approximation
92270 *
92271 * converts the cubic to a quadtratic approximation by
92272 * picking an appropriate quadratic control point
92273 */
92274 this.toQuadratic = function() {
92275 return {
92276 x: this.p0.x,
92277 y: this.p0.y,
92278 x1: this.p1.x,
92279 y1: this.p1.y,
92280 cx: ((this.c0.x + this.c1.x) * 3 - (this.p0.x + this.p1.x)) / 4,
92281 cy: ((this.c0.y + this.c1.y) * 3 - (this.p0.y + this.p1.y)) / 4
92282 };
92283 };
92284
92285 /**
92286 * @method quadError
92287 * @return {Number} the error
92288 *
92289 * calculates the magnitude of error of this curve's
92290 * quadratic approximation.
92291 */
92292 this.quadError = function() {
92293 return (
92294 _main.default.Vector.sub(
92295 _main.default.Vector.sub(this.p1, this.p0),
92296 _main.default.Vector.mult(
92297 _main.default.Vector.sub(this.c1, this.c0),
92298 3
92299 )
92300 ).mag() / 2
92301 );
92302 };
92303
92304 /**
92305 * @method split
92306 * @param {Number} t the value (0-1) at which to split
92307 * @return {Cubic} the second part of the curve
92308 *
92309 * splits the cubic into two parts at a point 't' along the curve.
92310 * this cubic keeps its start point and its end point becomes the
92311 * point at 't'. the 'end half is returned.
92312 */
92313 this.split = function(t) {
92314 var m1 = _main.default.Vector.lerp(this.p0, this.c0, t);
92315 var m2 = _main.default.Vector.lerp(this.c0, this.c1, t);
92316 var mm1 = _main.default.Vector.lerp(m1, m2, t);
92317
92318 this.c1 = _main.default.Vector.lerp(this.c1, this.p1, t);
92319 this.c0 = _main.default.Vector.lerp(m2, this.c1, t);
92320 var pt = _main.default.Vector.lerp(mm1, this.c0, t);
92321 var part1 = new Cubic(this.p0, m1, mm1, pt);
92322 this.p0 = pt;
92323 return part1;
92324 };
92325
92326 /**
92327 * @method splitInflections
92328 * @return {Cubic[]} the non-inflecting pieces of this cubic
92329 *
92330 * returns an array containing 0, 1 or 2 cubics split resulting
92331 * from splitting this cubic at its inflection points.
92332 * this cubic is (potentially) altered and returned in the list.
92333 */
92334 this.splitInflections = function() {
92335 var a = _main.default.Vector.sub(this.c0, this.p0);
92336 var b = _main.default.Vector.sub(
92337 _main.default.Vector.sub(this.c1, this.c0),
92338 a
92339 );
92340 var c = _main.default.Vector.sub(
92341 _main.default.Vector.sub(_main.default.Vector.sub(this.p1, this.c1), a),
92342 _main.default.Vector.mult(b, 2)
92343 );
92344
92345 var cubics = [];
92346
92347 // find the derivative coefficients
92348 var A = b.x * c.y - b.y * c.x;
92349 if (A !== 0) {
92350 var B = a.x * c.y - a.y * c.x;
92351 var C = a.x * b.y - a.y * b.x;
92352 var disc = B * B - 4 * A * C;
92353 if (disc >= 0) {
92354 if (A < 0) {
92355 A = -A;
92356 B = -B;
92357 C = -C;
92358 }
92359
92360 var Q = Math.sqrt(disc);
92361 var t0 = (-B - Q) / (2 * A); // the first inflection point
92362 var t1 = (-B + Q) / (2 * A); // the second inflection point
92363
92364 // test if the first inflection point lies on the curve
92365 if (t0 > 0 && t0 < 1) {
92366 // split at the first inflection point
92367 cubics.push(this.split(t0));
92368 // scale t2 into the second part
92369 t1 = 1 - (1 - t1) / (1 - t0);
92370 }
92371
92372 // test if the second inflection point lies on the curve
92373 if (t1 > 0 && t1 < 1) {
92374 // split at the second inflection point
92375 cubics.push(this.split(t1));
92376 }
92377 }
92378 }
92379
92380 cubics.push(this);
92381 return cubics;
92382 };
92383 }
92384
92385 /**
92386 * @function cubicToQuadratics
92387 * @param {Number} x0
92388 * @param {Number} y0
92389 * @param {Number} cx0
92390 * @param {Number} cy0
92391 * @param {Number} cx1
92392 * @param {Number} cy1
92393 * @param {Number} x1
92394 * @param {Number} y1
92395 * @returns {Cubic[]} an array of cubics whose quadratic approximations
92396 * closely match the civen cubic.
92397 *
92398 * converts a cubic curve to a list of quadratics.
92399 */
92400 function cubicToQuadratics(x0, y0, cx0, cy0, cx1, cy1, x1, y1) {
92401 // create the Cubic object and split it at its inflections
92402 var cubics = new Cubic(
92403 new _main.default.Vector(x0, y0),
92404 new _main.default.Vector(cx0, cy0),
92405 new _main.default.Vector(cx1, cy1),
92406 new _main.default.Vector(x1, y1)
92407 ).splitInflections();
92408
92409 var qs = []; // the final list of quadratics
92410 var precision = 30 / SQRT3;
92411
92412 // for each of the non-inflected pieces of the original cubic
92413 var _iteratorNormalCompletion = true;
92414 var _didIteratorError = false;
92415 var _iteratorError = undefined;
92416 try {
92417 for (
92418 var _iterator = cubics[Symbol.iterator](), _step;
92419 !(_iteratorNormalCompletion = (_step = _iterator.next()).done);
92420 _iteratorNormalCompletion = true
92421 ) {
92422 var cubic = _step.value;
92423 // the cubic is iteratively split in 3 pieces:
92424 // the first piece is accumulated in 'qs', the result.
92425 // the last piece is accumulated in 'tail', temporarily.
92426 // the middle piece is repeatedly split again, while necessary.
92427 var tail = [];
92428
92429 var t3 = void 0;
92430 for (;;) {
92431 // calculate this cubic's precision
92432 t3 = precision / cubic.quadError();
92433 if (t3 >= 0.5 * 0.5 * 0.5) {
92434 break; // not too bad, we're done
92435 }
92436
92437 // find a split point based on the error
92438 var t = Math.pow(t3, 1.0 / 3.0);
92439 // split the cubic in 3
92440 var start = cubic.split(t);
92441 var middle = cubic.split(1 - t / (1 - t));
92442
92443 qs.push(start); // the first part
92444 tail.push(cubic); // the last part
92445 cubic = middle; // iterate on the middle piece
92446 }
92447
92448 if (t3 < 1) {
92449 // a little excess error, split the middle in two
92450 qs.push(cubic.split(0.5));
92451 }
92452 // add the middle piece to the result
92453 qs.push(cubic);
92454
92455 // finally add the tail, reversed, onto the result
92456 Array.prototype.push.apply(qs, tail.reverse());
92457 }
92458 } catch (err) {
92459 _didIteratorError = true;
92460 _iteratorError = err;
92461 } finally {
92462 try {
92463 if (!_iteratorNormalCompletion && _iterator.return != null) {
92464 _iterator.return();
92465 }
92466 } finally {
92467 if (_didIteratorError) {
92468 throw _iteratorError;
92469 }
92470 }
92471 }
92472
92473 return qs;
92474 }
92475
92476 /**
92477 * @function pushLine
92478 * @param {Number} x0
92479 * @param {Number} y0
92480 * @param {Number} x1
92481 * @param {Number} y1
92482 *
92483 * add a straight line to the row/col grid of a glyph
92484 */
92485 function pushLine(x0, y0, x1, y1) {
92486 var mx = (x0 + x1) / 2;
92487 var my = (y0 + y1) / 2;
92488 push([x0, x1], [y0, y1], { x: x0, y: y0, cx: mx, cy: my });
92489 }
92490
92491 /**
92492 * @function samePoint
92493 * @param {Number} x0
92494 * @param {Number} y0
92495 * @param {Number} x1
92496 * @param {Number} y1
92497 * @return {Boolean} true if the two points are sufficiently close
92498 *
92499 * tests if two points are close enough to be considered the same
92500 */
92501 function samePoint(x0, y0, x1, y1) {
92502 return Math.abs(x1 - x0) < 0.00001 && Math.abs(y1 - y0) < 0.00001;
92503 }
92504
92505 var x0, y0, xs, ys;
92506 var _iteratorNormalCompletion2 = true;
92507 var _didIteratorError2 = false;
92508 var _iteratorError2 = undefined;
92509 try {
92510 for (
92511 var _iterator2 = cmds[Symbol.iterator](), _step2;
92512 !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done);
92513 _iteratorNormalCompletion2 = true
92514 ) {
92515 var cmd = _step2.value;
92516 // scale the coordinates to the range 0-1
92517 var x1 = (cmd.x - xMin) / gWidth;
92518 var y1 = (cmd.y - yMin) / gHeight;
92519
92520 // don't bother if this point is the same as the last
92521 if (samePoint(x0, y0, x1, y1)) continue;
92522
92523 switch (cmd.type) {
92524 case 'M': {
92525 // move
92526 xs = x1;
92527 ys = y1;
92528 break;
92529 }
92530 case 'L': {
92531 // line
92532 pushLine(x0, y0, x1, y1);
92533 break;
92534 }
92535 case 'Q': {
92536 // quadratic
92537 var cx = (cmd.x1 - xMin) / gWidth;
92538 var cy = (cmd.y1 - yMin) / gHeight;
92539 push([x0, x1, cx], [y0, y1, cy], { x: x0, y: y0, cx: cx, cy: cy });
92540 break;
92541 }
92542 case 'Z': {
92543 // end
92544 if (!samePoint(x0, y0, xs, ys)) {
92545 // add an extra line closing the loop, if necessary
92546 pushLine(x0, y0, xs, ys);
92547 strokes.push({ x: xs, y: ys });
92548 } else {
92549 strokes.push({ x: x0, y: y0 });
92550 }
92551 break;
92552 }
92553 case 'C': {
92554 // cubic
92555 var cx1 = (cmd.x1 - xMin) / gWidth;
92556 var cy1 = (cmd.y1 - yMin) / gHeight;
92557 var cx2 = (cmd.x2 - xMin) / gWidth;
92558 var cy2 = (cmd.y2 - yMin) / gHeight;
92559 var qs = cubicToQuadratics(x0, y0, cx1, cy1, cx2, cy2, x1, y1);
92560 for (var iq = 0; iq < qs.length; iq++) {
92561 var q = qs[iq].toQuadratic();
92562 push([q.x, q.x1, q.cx], [q.y, q.y1, q.cy], q);
92563 }
92564 break;
92565 }
92566 default:
92567 throw new Error('unknown command type: '.concat(cmd.type));
92568 }
92569
92570 x0 = x1;
92571 y0 = y1;
92572 }
92573
92574 // allocate space for the strokes
92575 } catch (err) {
92576 _didIteratorError2 = true;
92577 _iteratorError2 = err;
92578 } finally {
92579 try {
92580 if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
92581 _iterator2.return();
92582 }
92583 } finally {
92584 if (_didIteratorError2) {
92585 throw _iteratorError2;
92586 }
92587 }
92588 }
92589 var strokeCount = strokes.length;
92590 var strokeImageInfo = this.strokeImageInfos.findImage(strokeCount);
92591 var strokeOffset = strokeImageInfo.index;
92592
92593 // fill the stroke image
92594 for (var il = 0; il < strokeCount; ++il) {
92595 var s = strokes[il];
92596 setPixel(strokeImageInfo, byte(s.x), byte(s.y), byte(s.cx), byte(s.cy));
92597 }
92598
92599 /**
92600 * @function layout
92601 * @param {Number[][]} dim
92602 * @param {ImageInfo[]} dimImageInfos
92603 * @param {ImageInfo[]} cellImageInfos
92604 * @return {Object}
92605 *
92606 * lays out the curves in a dimension (row or col) into two
92607 * images, one for the indices of the curves themselves, and
92608 * one containing the offset and length of those index spans.
92609 */
92610 function layout(dim, dimImageInfos, cellImageInfos) {
92611 var dimLength = dim.length; // the number of slices in this dimension
92612 var dimImageInfo = dimImageInfos.findImage(dimLength);
92613 var dimOffset = dimImageInfo.index;
92614 // calculate the total number of stroke indices in this dimension
92615 var totalStrokes = 0;
92616 for (var id = 0; id < dimLength; ++id) {
92617 totalStrokes += dim[id].length;
92618 }
92619
92620 // allocate space for the stroke indices
92621 var cellImageInfo = cellImageInfos.findImage(totalStrokes);
92622
92623 // for each slice in the glyph
92624 for (var _i2 = 0; _i2 < dimLength; ++_i2) {
92625 var strokeIndices = dim[_i2];
92626 var _strokeCount = strokeIndices.length;
92627 var cellLineIndex = cellImageInfo.index;
92628
92629 // write the offset and count into the glyph slice image
92630 setPixel(
92631 dimImageInfo,
92632 cellLineIndex >> 7,
92633 cellLineIndex & 0x7f,
92634 _strokeCount >> 7,
92635 _strokeCount & 0x7f
92636 );
92637
92638 // for each stroke index in that slice
92639 for (var iil = 0; iil < _strokeCount; ++iil) {
92640 // write the stroke index into the slice's image
92641 var strokeIndex = strokeIndices[iil] + strokeOffset;
92642 setPixel(cellImageInfo, strokeIndex >> 7, strokeIndex & 0x7f, 0, 0);
92643 }
92644 }
92645
92646 return {
92647 cellImageInfo: cellImageInfo,
92648 dimOffset: dimOffset,
92649 dimImageInfo: dimImageInfo
92650 };
92651 }
92652
92653 // initialize the info for this glyph
92654 gi = this.glyphInfos[glyph.index] = {
92655 glyph: glyph,
92656 uGlyphRect: [bb.x1, -bb.y1, bb.x2, -bb.y2],
92657 strokeImageInfo: strokeImageInfo,
92658 strokes: strokes,
92659 colInfo: layout(cols, this.colDimImageInfos, this.colCellImageInfos),
92660 rowInfo: layout(rows, this.rowDimImageInfos, this.rowCellImageInfos)
92661 };
92662
92663 gi.uGridOffset = [gi.colInfo.dimOffset, gi.rowInfo.dimOffset];
92664 return gi;
92665 };
92666 };
92667
92668 _main.default.RendererGL.prototype._renderText = function(p, line, x, y, maxY) {
92669 if (!this._textFont || typeof this._textFont === 'string') {
92670 console.log(
92671 'WEBGL: you must load and set a font before drawing text. See `loadFont` and `textFont` for more details.'
92672 );
92673
92674 return;
92675 }
92676 if (y >= maxY || !this._doFill) {
92677 return; // don't render lines beyond our maxY position
92678 }
92679
92680 if (!this._isOpenType()) {
92681 console.log(
92682 'WEBGL: only Opentype (.otf) and Truetype (.ttf) fonts are supported'
92683 );
92684
92685 return p;
92686 }
92687
92688 p.push(); // fix to #803
92689
92690 // remember this state, so it can be restored later
92691 var doStroke = this._doStroke;
92692 var drawMode = this.drawMode;
92693
92694 this._doStroke = false;
92695 this.drawMode = constants.TEXTURE;
92696
92697 // get the cached FontInfo object
92698 var font = this._textFont.font;
92699 var fontInfo = this._textFont._fontInfo;
92700 if (!fontInfo) {
92701 fontInfo = this._textFont._fontInfo = new FontInfo(font);
92702 }
92703
92704 // calculate the alignment and move/scale the view accordingly
92705 var pos = this._textFont._handleAlignment(this, line, x, y);
92706 var fontSize = this._textSize;
92707 var scale = fontSize / font.unitsPerEm;
92708 this.translate(pos.x, pos.y, 0);
92709 this.scale(scale, scale, 1);
92710
92711 // initialize the font shader
92712 var gl = this.GL;
92713 var initializeShader = !this._defaultFontShader;
92714 var sh = this._getFontShader();
92715 sh.init();
92716 sh.bindShader(); // first time around, bind the shader fully
92717
92718 if (initializeShader) {
92719 // these are constants, really. just initialize them one-time.
92720 sh.setUniform('uGridImageSize', [gridImageWidth, gridImageHeight]);
92721 sh.setUniform('uCellsImageSize', [cellImageWidth, cellImageHeight]);
92722 sh.setUniform('uStrokeImageSize', [strokeImageWidth, strokeImageHeight]);
92723 sh.setUniform('uGridSize', [charGridWidth, charGridHeight]);
92724 }
92725 this._applyColorBlend(this.curFillColor);
92726
92727 var g = this.retainedMode.geometry['glyph'];
92728 if (!g) {
92729 // create the geometry for rendering a quad
92730 var geom = (this._textGeom = new _main.default.Geometry(1, 1, function() {
92731 for (var i = 0; i <= 1; i++) {
92732 for (var j = 0; j <= 1; j++) {
92733 this.vertices.push(new _main.default.Vector(j, i, 0));
92734 this.uvs.push(j, i);
92735 }
92736 }
92737 }));
92738 geom.computeFaces().computeNormals();
92739 g = this.createBuffers('glyph', geom);
92740 }
92741
92742 // bind the shader buffers
92743 var _iteratorNormalCompletion3 = true;
92744 var _didIteratorError3 = false;
92745 var _iteratorError3 = undefined;
92746 try {
92747 for (
92748 var _iterator3 = this.retainedMode.buffers.text[Symbol.iterator](), _step3;
92749 !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done);
92750 _iteratorNormalCompletion3 = true
92751 ) {
92752 var buff = _step3.value;
92753 buff._prepareBuffer(g, sh);
92754 }
92755 } catch (err) {
92756 _didIteratorError3 = true;
92757 _iteratorError3 = err;
92758 } finally {
92759 try {
92760 if (!_iteratorNormalCompletion3 && _iterator3.return != null) {
92761 _iterator3.return();
92762 }
92763 } finally {
92764 if (_didIteratorError3) {
92765 throw _iteratorError3;
92766 }
92767 }
92768 }
92769 this._bindBuffer(g.indexBuffer, gl.ELEMENT_ARRAY_BUFFER);
92770
92771 // this will have to do for now...
92772 sh.setUniform('uMaterialColor', this.curFillColor);
92773
92774 try {
92775 var dx = 0; // the x position in the line
92776 var glyphPrev = null; // the previous glyph, used for kerning
92777 // fetch the glyphs in the line of text
92778 var glyphs = font.stringToGlyphs(line);
92779 var _iteratorNormalCompletion4 = true;
92780 var _didIteratorError4 = false;
92781 var _iteratorError4 = undefined;
92782 try {
92783 for (
92784 var _iterator4 = glyphs[Symbol.iterator](), _step4;
92785 !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done);
92786 _iteratorNormalCompletion4 = true
92787 ) {
92788 var glyph = _step4.value;
92789 // kern
92790 if (glyphPrev) dx += font.getKerningValue(glyphPrev, glyph);
92791
92792 var gi = fontInfo.getGlyphInfo(glyph);
92793 if (gi.uGlyphRect) {
92794 var rowInfo = gi.rowInfo;
92795 var colInfo = gi.colInfo;
92796 sh.setUniform('uSamplerStrokes', gi.strokeImageInfo.imageData);
92797 sh.setUniform('uSamplerRowStrokes', rowInfo.cellImageInfo.imageData);
92798 sh.setUniform('uSamplerRows', rowInfo.dimImageInfo.imageData);
92799 sh.setUniform('uSamplerColStrokes', colInfo.cellImageInfo.imageData);
92800 sh.setUniform('uSamplerCols', colInfo.dimImageInfo.imageData);
92801 sh.setUniform('uGridOffset', gi.uGridOffset);
92802 sh.setUniform('uGlyphRect', gi.uGlyphRect);
92803 sh.setUniform('uGlyphOffset', dx);
92804
92805 sh.bindTextures(); // afterwards, only textures need updating
92806
92807 // draw it
92808 gl.drawElements(gl.TRIANGLES, 6, this.GL.UNSIGNED_SHORT, 0);
92809 }
92810 dx += glyph.advanceWidth;
92811 glyphPrev = glyph;
92812 }
92813 } catch (err) {
92814 _didIteratorError4 = true;
92815 _iteratorError4 = err;
92816 } finally {
92817 try {
92818 if (!_iteratorNormalCompletion4 && _iterator4.return != null) {
92819 _iterator4.return();
92820 }
92821 } finally {
92822 if (_didIteratorError4) {
92823 throw _iteratorError4;
92824 }
92825 }
92826 }
92827 } finally {
92828 // clean up
92829 sh.unbindShader();
92830
92831 this._doStroke = doStroke;
92832 this.drawMode = drawMode;
92833
92834 p.pop();
92835 }
92836
92837 return p;
92838 };
92839 },
92840 {
92841 '../core/constants': 43,
92842 '../core/main': 54,
92843 './p5.RendererGL.Retained': 107,
92844 './p5.Shader': 109
92845 }
92846 ],
92847 112: [
92848 function(_dereq_, module, exports) {
92849 module.exports = {
92850 fes: {
92851 autoplay:
92852 "The media that tried to play (with '{{src}}') wasn't allowed to by this browser, most likely due to the browser's autoplay policy. Check out {{link}} for more information about why.",
92853 checkUserDefinedFns:
92854 "It seems that you may have accidently written {{name}} instead of {{actualName}}.\n\nPlease correct it if it's not intentional.",
92855 fileLoadError: {
92856 bytes:
92857 'It looks like there was a problem loading your file. {{suggestion}}',
92858 font: 'It looks like there was a problem loading your font. {{suggestion}}',
92859 gif:
92860 'There was some trouble loading your GIF. Make sure that your GIF is using 87a or 89a encoding.',
92861 image:
92862 'It looks like there was a problem loading your image. {{suggestion}}',
92863 json:
92864 'It looks like there was a problem loading your JSON file. {{suggestion}}',
92865 large:
92866 "If your large file isn't fetched successfully, we recommend splitting the file into smaller segments and fetching those.",
92867 strings:
92868 'It looks like there was a problem loading your text file. {{suggestion}}',
92869 suggestion:
92870 'Try checking if the file path ({{filePath}}) is correct, hosting the file online, or running a local server. (More info at {{link}})',
92871 table:
92872 'It looks like there was a problem loading your table file. {{suggestion}}',
92873 xml:
92874 'It looks like there was a problem loading your XML file. {{suggestion}}'
92875 },
92876 friendlyParamError: {
92877 type_EMPTY_VAR:
92878 '{{func}}() was expecting {{formatType}} for the {{position}} parameter, received an empty variable instead. {{location}}\n\nIf not intentional, this is often a problem with scope: {{link}}',
92879 type_TOO_FEW_ARGUMENTS:
92880 '{{func}}() was expecting at least {{minParams}} arguments, but received only {{argCount}}. {{location}}',
92881 type_TOO_MANY_ARGUMENTS:
92882 '{{func}}() was expecting no more than {{maxParams}} arguments, but received {{argCount}}. {{location}}',
92883 type_WRONG_TYPE:
92884 '{{func}}() was expecting {{formatType}} for the {{position}} parameter, received {{argType}} instead. {{location}}'
92885 },
92886 globalErrors: {
92887 reference: {
92888 notDefined:
92889 'There\'s an error due to "{{symbol}}" not being defined in the current scope {{location}}.\n\nIf you have defined it in your code, you should check its scope, spelling, and letter-casing (JavaScript is case-sensitive). For more:\n{{url1}}\n{{url2}}'
92890 },
92891 stackSubseq:
92892 '▶️ Called from line {{line}} in "{{func}}" in {{file}} ({{location}})\n\n',
92893 stackTop:
92894 '▶️ Error at line {{line}} in "{{func}}" in {{file}} ({{location}})\n\n',
92895 syntax: {
92896 invalidToken:
92897 "There's a syntax error due to a symbol that JavaScript doesn't recognize or didn't expect at it's place.\nFor more: {{url}}",
92898 unexpectedToken:
92899 "There's a syntax error due to a symbol that wasn't expected at it's place.\nUsually this is due to a typo. Check the line number in the error below for anything missing/extra.\nFor more: {{url}}"
92900 },
92901 type: {
92902 notfunc:
92903 'There\'s an error as "{{symbol}}" could not be called as a function {{location}}.\nCheck the spelling, letter-casing (Javacript is case-sensitive) and its type.\nFor more: {{url}}',
92904 notfuncObj:
92905 'There\'s an error as "{{symbol}}" could not be called as a function {{location}}.\nVerify whether "{{obj}}" has "{{symbol}}" in it and check the spelling, letter-casing (Javacript is case-sensitive) and its type.\nFor more: {{url}}'
92906 }
92907 },
92908 libraryError:
92909 'An error with message "{{error}}" occured inside the p5js library when {{func}} was called {{location}}\n\nIf not stated otherwise, it might be an issue with the arguments passed to {{func}}.',
92910 location: '(on line {{line}} in {{file}} [{{location}}])',
92911 misspelling:
92912 'It seems that you may have accidently written {{name}} instead of {{actualName}} {{location}}.\n\nPlease correct it to {{actualName}} if you wish to use the {{type}} from p5.js',
92913 misusedTopLevel:
92914 "Did you just try to use p5.js's {{symbolName}} {{symbolType}}? If so, you may want to move it into your sketch's setup() function.\n\nFor more details, see: {{link}}",
92915 positions: {
92916 p_1: 'first',
92917 p_10: 'tenth',
92918 p_11: 'eleventh',
92919 p_12: 'twelfth',
92920 p_2: 'second',
92921 p_3: 'third',
92922 p_4: 'fourth',
92923 p_5: 'fifth',
92924 p_6: 'sixth',
92925 p_7: 'seventh',
92926 p_8: 'eighth',
92927 p_9: 'ninth'
92928 },
92929 pre: '\n🌸 p5.js says: {{message}}',
92930 welcome:
92931 'Welcome! This is your friendly debugger. To turn me off, switch to using p5.min.js.',
92932 wrongPreload:
92933 'An error with message "{{error}}" occured inside the p5js library when "{{func}}" was called {{location}}.\n\nIf not stated otherwise, it might be due to "{{func}}" being called from preload. Nothing besides load calls (loadImage, loadJSON, loadFont, loadStrings, etc.) should be inside the preload function.'
92934 }
92935 };
92936 },
92937 {}
92938 ],
92939 113: [
92940 function(_dereq_, module, exports) {
92941 module.exports = {
92942 fes: {
92943 autoplay:
92944 "Su browser impidío un medio tocar (de '{{src}}'), posiblemente porque las reglas de autoplay. Para aprender más, visite {{link}}.",
92945 checkUserDefinedFns: '',
92946 fileLoadError: {
92947 bytes: '',
92948 font: '',
92949 gif: '',
92950 image: '',
92951 json: '',
92952 large: '',
92953 strings: '',
92954 suggestion: '',
92955 table: '',
92956 xml: ''
92957 },
92958 friendlyParamError: {
92959 type_EMPTY_VAR: '',
92960 type_TOO_FEW_ARGUMENTS: '',
92961 type_TOO_MANY_ARGUMENTS: '',
92962 type_WRONG_TYPE: ''
92963 },
92964 globalErrors: {
92965 reference: {
92966 notDefined: ''
92967 },
92968 stackSubseq: '',
92969 stackTop: '',
92970 syntax: {
92971 invalidToken: '',
92972 unexpectedToken: ''
92973 },
92974 type: {
92975 notfunc: '',
92976 notfuncObj: ''
92977 }
92978 },
92979 libraryError: '',
92980 location: '',
92981 misspelling: '',
92982 misusedTopLevel: '',
92983 positions: {
92984 p_1: '',
92985 p_10: '',
92986 p_11: '',
92987 p_12: '',
92988 p_2: '',
92989 p_3: '',
92990 p_4: '',
92991 p_5: '',
92992 p_6: '',
92993 p_7: '',
92994 p_8: '',
92995 p_9: ''
92996 },
92997 pre: '🌸 p5.js dice: {{message}}',
92998 welcome: '',
92999 wrongPreload: ''
93000 }
93001 };
93002 },
93003 {}
93004 ],
93005 114: [
93006 function(_dereq_, module, exports) {
93007 'use strict';
93008 Object.defineProperty(exports, '__esModule', { value: true });
93009 exports.default = void 0;
93010 var _translation = _interopRequireDefault(_dereq_('./en/translation'));
93011 var _translation2 = _interopRequireDefault(_dereq_('./es/translation'));
93012 function _interopRequireDefault(obj) {
93013 return obj && obj.__esModule ? obj : { default: obj };
93014 }
93015
93016 /**
93017 * Maps our translations to their language key
93018 * (`en` is english, `es` es español)
93019 *
93020 * `translation` is the namespace we're using for
93021 * our initial set of translation strings.
93022 */ var _default = {
93023 en: {
93024 translation: _translation.default
93025 },
93026
93027 es: {
93028 translation: _translation2.default
93029 }
93030 };
93031 exports.default = _default;
93032 },
93033 { './en/translation': 112, './es/translation': 113 }
93034 ]
93035 },
93036 {},
93037 [38]
93038 )(38);
93039});